Older blog entries for cdent (starting at number 69)

20120312

Did some thinking about TiddlyWikiNeeds, particularly the downloaded TiddlyWiki, resulting in a groups posting and a github branch called downloadlite.

The basic idea is that the downloaded TiddlyWiki should be "lite", meaning not having extraneous stuff in it.

Syndicated 2012-03-12 17:28:52 from cdent

zzzeek : Pycon 2012 : Hand Coded Applications with SQLAlchemy

Here's the slides from my Pycon 2012 talk, "Hand Coded Applications with SQLAlchemy".
zzzeek : Pycon 2012 : Hand Coded Applications with SQLAlchemy

Syndicated 2012-03-12 08:49:24 from cdent

13 Mar 2012 (updated 14 Mar 2012 at 22:12 UTC) »

20120311

I endeavored to do some testing of the twp.mysql2 to twp.mysql3 transition today, but without complete success. On my main dev machine, I've upgraded to mysql 5.5. I did that to ensure that the new code solves the problems of working with 5.5. However, on 5.5 the old code doesn't work so I can't do a test migration on that machine. I have a few others to choose from.

The migration process is primarily documented here but there are some additional details:

  • Put up the 503 error setup on tiddlyspace.com
  • Turn off all the database related cronjobs
  • Make a full backup of the database
  • Put innodb support back in mysql by editing my.cnf
  • Before the migration the mysql3 branch of the TiddlySpace code should be merged to master.
  • Shutdown memcached, remove tiddlywebplugins.caching as the store, switching back to direct twp.tiddlyspace.store.
  • Migrate according to the other docs.
  • After the data is migrated but before the web server is started back up, the new code (from the branch) needs to be installed.
  • turn back on the cronjobs (in /etc/cron.d and /etc/cron.daily)

Syndicated 2012-03-11 15:33:46 (Updated 2012-03-14 21:40:57) from cdent

20120309

  • Released a new version of TiddlyWeb with a fix from fnd: render and fat on JSON tiddler and tiddlers are now mutually independent. This now makes it possible to get JSON that has a render field but doesn't have a text field.
  • Scheduled Maintenance 14 March, 2012.
  • Made sure that the auxbags branch of the TiddlySpace code is still working after merging in the latest master. I would still like to see some kind of AuxBags thing happen, but it's hard to say that we need it badly.

Syndicated 2012-03-09 17:26:08 (Updated 2012-03-09 18:19:55) from cdent

Scheduled Maintenance 14 March, 2012

After 11:59pm on the 14th of March there will be a 6 hour maintenance window during which tiddlyspace.com will be unavailable. See the google groups announcement.

Syndicated 2012-03-09 17:02:55 (Updated 2012-03-09 17:02:05) from cdent

20120308

  • Decided to change my sidebar so that it uses websockets to update itself, instead of a setInterval refresh. It turns out that my pages are viewed quite a lot and if the page is left open it bounces on the search that updates the sidebar. Since one of my goals is to minimize traffic while maximizing use, switching to websockets is more efficient. However the fact that my own pages have so much JavaScript making them go makes me feel dirty.
  • Created a branch (mysql3) of the TiddlySpace code that uses twp.mysql3 and used it in a dev env. Seems to work. Need to determine when the best time for a migration might be.
  • Good news about Eric becoming TiddlyWiki maintainer. I hope that he is able to estabish a regular release schedule and a culture of contribution, keeping things fresh and exciting.
  • Added "save & return" to edit so you can exit the editor conveniently.
  • Turned off disqus on my pages for two reasons:
    1. With reply coming along, that's the way to go.
    2. disqus spews all kinds of noise all over the JavaScript console making debugging other things quite noisy.

Syndicated 2012-03-08 14:23:44 (Updated 2012-03-08 16:40:22) from cdent

13 Mar 2012 (updated 5 Jul 2012 at 21:11 UTC) »

edit.js

$(function() {
var Set = function() {}
Set.prototype.add = function(o) { this[o] = true; }
Set.prototype.remove = function(o) { delete this[o]; }

var adler32 = function(a){for(var b=65521,c=1,d=0,e=0,f;f=a.charCodeAt(e++);d=(d+c)%b)c=(c+f)%b;return(d h1').text());
});

$('#save').bind('click', function() {
    saveEdit();
});

$('#saver').bind('click', function() {
    saveEdit(function() {
        var title = encodeURIComponent($('#editor > h1').text());
        startHash = adler32($('input[name=tags]').val()
                + $('textarea[name=text]').val());
        window.location.href = '/' + title;
    });
});

$('#delete').bind('click', function() {
    var title = encodeURIComponent($('#editor > h1').text());
    if (currentBag) {
        var confirmation = confirm('Are you sure you want to delete ' + title + '?');
        if (confirmation) {
            $('input[name=tags]').val('');
            $('textarea[name=text]').val('');
            $('#editor > h1').text('');
            startHash = adler32('');
            deleteTiddler(title);
        }
    } else {
        displayMessage('Tiddler never saved to server.');
    }
});

/*
 * Fade in an announcement text message.
 */
function displayMessage(message, extra) {
    var content = $('

').text(message); $('#message').empty(); $('#message').append(content) if (extra) { $('#message').append(extra); } $('#message').fadeIn(); } /* * Display an icon indicating privacy status of tiddler. */ function setIcon(privatep) { $('.privacyicon').remove(); var img = $('').attr({ src: host + (privatep ? privateIcon : publicIcon), 'class': 'privacyicon'}); if (!currentBag) { img.css('cursor', 'pointer') .click(function() { var target = privatep ? 'public' : 'private'; if (confirm('Switch to ' + (privatep ? 'public' : 'private') + '?')) { currentBag = space + '_' + target; setIcon(!privatep); } }); } $('#type').prepend(img); } /* * Send a DELETE for the tiddler named by title. */ function deleteTiddler(title) { if (title && currentBag) { $(window).unbind('hashchange'); window.location.hash = ''; $(window).bind('hashchange', checkHash); var uri = host + 'bags/' + encodeURIComponent(currentBag) + '/tiddlers/' + encodeURIComponent(title); $.ajax({ url: uri, type: 'DELETE', success: changes }); } else { displayMessage('Nothing to delete.'); } } /* * Inform a non-member that they may not edit. */ function guestPage() { $('button, input, .inputs').attr('disabled', 'disabled'); $('#message').text('You are not a member of this space, so cannot edit. '); var link = $('') .attr('href', host) .text('Visit the space.'); $('#message').append(link).fadeIn(); } /* * Save the text and tags to the title in currentBag. */ function saveEdit(callback) { callback = callback || changes; var title = $('#editor > h1').text(); if (title) { var text = $('textarea[name=text]').val() _processText(title, text, callback); } else { displayMessage('There is nothing to save'); } } /* * Search for '.extraclude' in page and do an * extraclusion if found. Multiples possible. */ function _processText(title, text, callback) { var newTiddlers = {} , match; while (match = extracludeRE.exec(text)) { var subtitle = match[1] , subtext = match[2].replace(/^\s*/, '').replace(/\s*$/, '') , tiddler = { text: subtext, type: currentFields.type }; newTiddlers[subtitle] = tiddler; } var countTiddlers = Object.keys(newTiddlers).length; var countSuccess = 0; var postExtra = function(data, status, xhr) { countSuccess++; if (countSuccess >= countTiddlers) { text = text.replace(extracludeRE, '>'); _saveEdit(title, text, callback) } }; var postExtraFail = function(xhr, status, errorThrown) { displayMessage('Extraclude failed' + status); } if (countTiddlers) { var subtitle; for (subtitle in newTiddlers) { _putTiddler(subtitle, newTiddlers[subtitle], postExtra, postExtraFail) } } else { _saveEdit(title, text, callback) } } /* * PUT a tiddler that was extracluded. */ function _putTiddler(title, tiddlerData, successCall, errorCall) { var jsonText = JSON.stringify(tiddlerData); if (!currentBag) { currentBag = space + '_public'; } $.ajax({ url: host + 'bags/' + encodeURIComponent(currentBag) + '/tiddlers/' + encodeURIComponent(title), type: 'PUT', data: jsonText, contentType: 'application/json', success: successCall, error: errorCall }); } function _saveEdit(title, text, callback) { var tags = readTagView() , tiddler = {}; tiddler.text = text; tiddler.tags = tags; tiddler.type = currentFields.type; delete currentFields.type; tiddler.fields = currentFields; // update content based on radio buttons var matchedType = $('[name=type]:checked').val(); if (matchedType !== 'other') { if (matchedType === 'default') { delete tiddler.type; } else { tiddler.type = matchedType; } } var jsonText = JSON.stringify(tiddler); if (!currentBag) { currentBag = space + '_public'; } $.ajax({ beforeSend: function(xhr) { if (tiddler.fields['server.etag']) { xhr.setRequestHeader('If-Match', tiddler.fields['server.etag']); } }, url: host + 'bags/' + encodeURIComponent(currentBag) + '/tiddlers/' + encodeURIComponent(title), type: "PUT", contentType: 'application/json', data: jsonText, success: callback, statusCode: { 412: function() { displayMessage('Edit Conflict'); } } }); } /* * Read the current tags from the input into an array. */ function readTagView(tagString) { var tags = []; tagString = tagString || $('input[name=tags]').val(); var matches = tagString.match(/([^ \]\[]+)|(?:\[\[([^\]]+)\]\])/g) || []; $.each(matches, function(index, value) { tags.push(value.replace(/[\]\[]+/g, '')); }); return tags; } /* * Write updated tags into the tag view. If a non-false second * argument is passed, it is assumed to be a tag that is being * added or removed. */ function updateTagView(tags, changedTag) { var outputTags = []; if (changedTag) { var tagIndex = tags.indexOf(changedTag); if (tagIndex == -1) { tags.push(changedTag); } else { tags.splice(tags.indexOf(changedTag), 1); } } $.each(tags, function(index, tag) { if (tag.match(/ /)) { outputTags.push('[[' + tag + ']]'); } else { outputTags.push(tag); } }); $('#editor input').val(outputTags.join(' ')) } /* * Display the most recently used tags. */ function updateTags(tags) { $('#tags').empty(); tags = Object.keys(tags); tags = tags.sort(); $.each(tags, function(index, tag) { var taglink = $('') .text(tag) .addClass('taglink') .bind('click', function() { updateTagView(readTagView(), tag); }); $('#tags').append(taglink); }); } function updateContentType(tiddlerType) { $('[name=type]').prop('checked', false); var matchedType = $('[name=type]') .filter('[value="' + tiddlerType + '"]'); if (matchedType.length) { matchedType.prop('checked', true) } else if (tiddlerType) { $('[name=type]').filter('[value=other]').prop('checked', true); } else { $('[name=type]').filter('[value="default"]').prop('checked', true); } } /* * Callback after tiddler is GET from server, filling in forms, * preparing for edit. */ function establishEdit(tiddler, status, xhr) { currentBag = tiddler.bag; $('textarea[name=text]').val(tiddler.text); var tagList = []; currentFields = tiddler.fields; currentFields['type'] = tiddler.type // update the content type buttons updateContentType(tiddler.type); currentFields['server.etag'] = xhr.getResponseHeader('etag'); updateTagView(tiddler.tags, null); if (currentBag.split(/_/)[0] !== space) { $('button, input, .inputs').attr('disabled', 'disabled'); displayMessage('Edit permission denied. Choose another tiddler.'); return; } startHash = adler32($('input[name=tags]').val() + $('textarea[name=text]').val()); if (currentBag.match(/_(private|public)$/)) { setIcon(currentBag.match(/_private$/)); } } /* * Get the named tiddler to do an edit. */ function startEdit(tiddlerTitle, freshTags, freshType) { $('#message').fadeOut('slow'); $('button, input, .inputs').removeAttr('disabled'); $('#editor > h1').text(tiddlerTitle); $.ajax({ dataType: 'json', headers: {'Cache-Control': 'max-age=0'}, url: host + encodeURIComponent(tiddlerTitle), success: establishEdit, statusCode: { 404: function() { $('[name=type]') .filter('[value="default"]') .prop('checked', true); $('textarea[name=text]').val(''); setIcon(false); updateContentType(freshType); updateTagView(readTagView(freshTags), null); } } }); } function emptyEdit() { $('button, input, .inputs').attr('disabled', 'disabled'); var titler = $('') .attr('placeholder', 'Or enter a new title') .bind('blur change', editNew); displayMessage('Select a tiddler to edit from the right.', titler); } function editNew() { var newTitle = $(this).val(); if (newTitle) { startEdit(newTitle); } } /* * Check the href anchor to see if we've been told what to edit. */ function checkHash() { var hash = window.location.hash; if (hash) { hash = hash.replace(/^#/, ''); var title, tagString, type, args; args = hash.split('/'); if (args.length == 4) { args[2] = args.slice(2).join('/'); args.pop(); } $.each(args, function(index, arg) { args[index] = decodeURIComponent(arg); }); title = args[0] || emptyEdit(); tagString = args[1] || ''; type = args[2] || ''; startEdit(title, tagString, type); } else { emptyEdit(); } } /* * Display the recent changes. */ function displayChanges(tiddlers) { $.each(tiddlers, function(index, tiddler) { if (!tiddler.type || tiddler.type.match(/^text/)) { $.each(tiddler.tags, function(index, tag) { recentTags.add(tag); }) var penSpan = $('').text('\u270E') .bind('click', function() { var title = $(this).parent().attr('data-tiddler-title'); $(window).unbind('hashchange'); window.location.hash = title; $(window).bind('hashchange', checkHash); startEdit(title); }); var tiddlerLink = $('').attr({ href: '/' + encodeURIComponent(tiddler.title), target: '_blank'}) .text(tiddler.title) var list = $('

  • ').attr('data-tiddler-title', tiddler.title).append(tiddlerLink).prepend(penSpan); $('#recents > ul').append(list); } }); updateTags(recentTags); } /* * Get the 20 most recently changed tiddlers in the public and private * bag of the space, callback to displayChanges. */ function changes() { $('#recents > ul').empty(); $.ajax({ dataType: 'json', headers: {'Cache-Control': 'max-age=0'}, url: host + 'search?q=bag:' + encodeURIComponent(space) + '_public%20OR%20bag:' + encodeURIComponent(space) + '_private', success: displayChanges }); checkHash(); } /* * Start up, establishing if the current user has the power to edit. */ function init() { $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader("X-ControlView", "false"); } }); var recipe = tiddlyweb.status.space.recipe; if (recipe.match(/_private$/)) { changes(); }else { guestPage(); } } init(); });
  • Syndicated 2012-02-13 22:19:22 (Updated 2012-07-05 20:37:29) from cdent

    edit.js

    $(function() {
    var Set = function() {}
    Set.prototype.add = function(o) { this[o] = true; }
    Set.prototype.remove = function(o) { delete this[o]; }
    
    var adler32 = function(a){for(var b=65521,c=1,d=0,e=0,f;f=a.charCodeAt(e++);d=(d+c)%b)c=(c+f)%b;return(d h1').text());
    });
    
    $('#save').bind('click', function() {
        saveEdit();
    });
    
    $('#saver').bind('click', function() {
        saveEdit(function() {
            var title = encodeURIComponent($('#editor > h1').text());
            startHash = adler32($('input[name=tags]').val()
                    + $('textarea[name=text]').val());
            window.location.href = '/' + title;
        });
    });
    
    $('#delete').bind('click', function() {
        var title = decodeURIComponent(window.location.hash.replace(/^#/, ''));
        if (currentBag) {
            var confirmation = confirm('Are you sure you want to delete ' + title + '?');
            if (confirmation) {
                $('input[name=tags]').val('');
                $('textarea[name=text]').val('');
                $('#editor > h1').text('');
                startHash = adler32('');
                deleteTiddler(title);
            }
        } else {
            displayMessage('Tiddler never saved to server.');
        }
    });
    
    /*
     * Fade in an announcement text message.
     */
    function displayMessage(message) {
        $('#message').text(message).fadeIn();
    }
    
    /*
     * Display an icon indicating privacy status of tiddler.
     */
    function setIcon(privatep) {
        $('.privacyicon').remove();
        var img = $('').attr({
            src: host + (privatep ? privateIcon : publicIcon),
            'class': 'privacyicon'});
    
        if (!currentBag) {
            img.css('cursor', 'pointer')
                .click(function() {
                    var target = privatep ? 'public' : 'private';
                    if (confirm('Switch to '
                            + (privatep ? 'public' : 'private') + '?')) {
                        currentBag = space + '_' + target;
                        setIcon(!privatep);
                    }
                });
        }
        $('#type').prepend(img);
    }
    
    /*
     * Send a DELETE for the tiddler named by title.
     */
    function deleteTiddler(title) {
        if (title && currentBag) {
            window.location.hash = '';
            var uri = host + 'bags/'
                + encodeURIComponent(currentBag)
                + '/tiddlers/'
                + encodeURIComponent(title);
            $.ajax({
                url: uri,
                type: 'DELETE',
                success: changes
            });
        } else {
            displayMessage('Nothing to delete.');
        }
    }
    
    /*
     * Inform a non-member that they may not edit.
     */
    function guestPage() {
        $('button, input, .inputs').attr('disabled', 'disabled');
        $('#message').text('You are not a member of this space, so cannot edit. ');
        var link = $('')
            .attr('href', host)
            .text('Visit the space.');
        $('#message').append(link).fadeIn();
    }
    
    /*
     * Save the text and tags to the title in currentBag.
     */
    function saveEdit(callback) {
        callback = callback || changes;
        var title = $('#editor > h1').text();
        if (title) {
            var text = $('textarea[name=text]').val()
                , tags = readTagView()
                , tiddler = {};
            tiddler.text = text;
            tiddler.tags = tags;
            tiddler.type = currentFields.type;
            delete currentFields.type;
            tiddler.fields = currentFields;
    
            // update content based on radio buttons
            var matchedType = $('[name=type]:checked').val();
            if (matchedType !== 'other') {
                if (matchedType === 'default') {
                    delete tiddler.type;
                } else {
                    tiddler.type = matchedType;
                }
            }
    
            var jsonText = JSON.stringify(tiddler);
            if (!currentBag) {
                currentBag = space + '_public';
            }
            $.ajax({
                beforeSend: function(xhr) {
                    if (tiddler.fields['server.etag']) {
                        xhr.setRequestHeader('If-Match',
                            tiddler.fields['server.etag']);
                    }
                },
                url: host + 'bags/' + encodeURIComponent(currentBag)
                    + '/tiddlers/' + encodeURIComponent(title),
                type: "PUT",
                contentType: 'application/json',
                data: jsonText,
                success: callback,
                statusCode: {
                    412: function() {
                             displayMessage('Edit Conflict');
                    }
                }
            });
        } else {
            displayMessage('There is nothing to save');
        }
    }
    
    /*
     * Read the current tags from the input into an array.
     */
    function readTagView(tagString) {
        var tags = [];
        tagString = tagString || $('input[name=tags]').val();
        var matches = tagString.match(/([^ \]\[]+)|(?:\[\[([^\]]+)\]\])/g) || [];
        $.each(matches, function(index, value) {
            tags.push(value.replace(/[\]\[]+/g, ''));
        });
        return tags;
    }
    
    /*
     * Write updated tags into the tag view. If a non-false second
     * argument is passed, it is assumed to be a tag that is being
     * added or removed.
     */
    function updateTagView(tags, changedTag) {
        var outputTags = [];
    
        if (changedTag) {
            var tagIndex = tags.indexOf(changedTag);
            if (tagIndex == -1) {
                tags.push(changedTag);
            } else {
                tags.splice(tags.indexOf(changedTag), 1);
            }
        }
    
        $.each(tags, function(index, tag) {
            if (tag.match(/ /)) {
                outputTags.push('[[' + tag + ']]');
            } else {
                outputTags.push(tag);
            }
        });
            
        $('#editor input').val(outputTags.join(' '))
    }
    
    /*
     * Display the most recently used tags.
     */
    function updateTags(tags) {
        $('#tags').empty();
        tags = Object.keys(tags);
        tags = tags.sort();
        $.each(tags, function(index, tag) {
            var taglink = $('')
                .text(tag)
                .addClass('taglink')
                .bind('click', function() {
                    updateTagView(readTagView(), tag);
                });
            $('#tags').append(taglink);
        });
    }
    
    function updateContentType(tiddlerType) {
        $('[name=type]').prop('checked', false);
        var matchedType = $('[name=type]')
            .filter('[value="' + tiddlerType + '"]');
        if (matchedType.length) {
            matchedType.prop('checked', true)
        } else if (tiddlerType) {
            $('[name=type]').filter('[value=other]').prop('checked', true);
        } else {
            $('[name=type]').filter('[value="default"]').prop('checked', true);
        }
    }
    
    /*
     * Callback after tiddler is GET from server, filling in forms,
     * preparing for edit.
     */
    function establishEdit(tiddler, status, xhr) {
        currentBag = tiddler.bag;
        $('textarea[name=text]').val(tiddler.text);
        var tagList = [];
        currentFields = tiddler.fields;
        currentFields['type'] = tiddler.type
    
        // update the content type buttons
        updateContentType(tiddler.type);
    
        currentFields['server.etag'] = xhr.getResponseHeader('etag');
        updateTagView(tiddler.tags, null);
        startHash = adler32($('input[name=tags]').val()
                + $('textarea[name=text]').val());
        if (currentBag.match(/_(private|public)$/)) {
            setIcon(currentBag.match(/_private$/));
        }
    }
    
    /*
     * Get the named tiddler to do an edit.
     */
    function startEdit(tiddlerTitle, freshTags, freshType) {
        $('#message').fadeOut('slow');
        $('button, input, .inputs').removeAttr('disabled');
        window.location.hash = tiddlerTitle;
        $('#editor > h1').text(tiddlerTitle);
        $.ajax({
            dataType: 'json',
            headers: {'Cache-Control': 'max-age=0'},
            url: host + encodeURIComponent(tiddlerTitle),
            success: establishEdit,
            statusCode: {
                404: function() {
                    $('[name=type]')
                        .filter('[value="default"]')
                        .prop('checked', true);
                    setIcon(false);
                    updateContentType(freshType);
                    updateTagView(readTagView(freshTags), null);
                 }
            }
        });
    }
    
    function emptyEdit() {
        $('button, input, .inputs').attr('disabled', 'disabled');
        displayMessage('Select a tiddler to edit');
    }
    
    /*
     * Check the href anchor to see if we've been told what to edit.
     */
    function checkHash() {
        var hash = window.location.href.split('#')[1] || '';
        if (hash) {
            var title, tagString, type, args;
            args = hash.split('/', 3);
            $.each(args, function(index, arg) {
                args[index] = decodeURIComponent(arg);
            });
            title = args[0] || emptyEdit();
            tagString = args[1] || '';
            type = args[2] || '';
            startEdit(title, tagString, type);
        } else {
            emptyEdit();
        }
    }
    
    /*
     * Display the recent changes.
     */
    function displayChanges(tiddlers) {
        $.each(tiddlers, function(index, tiddler) {
            if (!tiddler.type 
                || tiddler.type.match(/^text/)) {
                $.each(tiddler.tags, function(index, tag) {
                    recentTags.add(tag);
                })
                var penSpan = $('').text('\u270E')
                    .bind('click', function() {
                        startEdit($(this).parent().attr('data-tiddler-title'));
                    });
                var tiddlerLink = $('').attr({
                        href: '/' + encodeURIComponent(tiddler.title),
                        target: '_blank'})
                    .text(tiddler.title)
                var list = $('
  • ').attr('data-tiddler-title', tiddler.title).append(tiddlerLink).prepend(penSpan); $('#recents > ul').append(list); } }); updateTags(recentTags); } /* * Get the 20 most recently changed tiddlers in the public and private * bag of the space, callback to displayChanges. */ function changes() { $('#recents > ul').empty(); $.ajax({ dataType: 'json', headers: {'Cache-Control': 'max-age=0'}, url: host + 'search?q=bag:' + encodeURIComponent(space) + '_public%20OR%20bag:' + encodeURIComponent(space) + '_private', success: displayChanges }); checkHash(); } /* * Start up, establishing if the current user has the power to edit. */ function init() { $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader("X-ControlView", "false"); } }); var url = '/status' , genHost = false; if (window.location.href.match(/^file:/)) { // for dev url = 'http://cdent.tiddlyspace.com/status'; genHost = true; } $.ajax({ dataType: 'json', url: url, success: function(data) { space = data.space.name; host = '/'; if (genHost) { host = data.server_host.scheme + '://' + space + '.' + data.server_host.host + '/'; } if (data.username === 'GUEST') { guestPage(); } else { $.ajax({ url: host + 'spaces/' + space + '/members', success: changes, error: guestPage, }); } } }); } init(); });
  • Syndicated 2012-02-13 22:19:22 (Updated 2012-03-08 14:35:16) from cdent

    13 Mar 2012 (updated 7 May 2012 at 17:09 UTC) »

    plate

    Things on the plate are items that I've been told I need to work on or I feel I need to work on or think about. This ought to be much shorter than it is. ZOMG it's getting worse.

    • Clean up packaging of the common twp plugins: docs, code style, etc.
    • Database issues
      • some day it would be nice to stop mysql going away (see tiddlyweb.log)
    • start thinking about tiddlyspace+ec2 (and chef, puppet etc)
    • twp.webhooks investigations
    • hoster
    • write up Top 10 TiddlySpace Features You've Never Heard Of
    • There are some issues with transactional integrity in the tiddlywebredis code that need to be worked through but I require time and whiteboard to get it right.
    • Make it so that not all serializations are presented when seeing HTML rep, otherwise you can get 40x.
    • Start figuring out efficient ways to have space-valid, but not in the recipe, bags. That is bags that you can write to from within the space, bypassing ControlView and DropPrivs, without having to put them in the recipe. See AuxBags for some thoughts.
    • enumerate the filters which are available on TiddlySpace
    • twikifier sometimes gets a bit stuck, using 100% of cpu. Need more data.
    • continue with the tw5-based wikifier, tw5ikifier
    • fix css in sensus
    • complete drag and drop experiment, motus, for moving tiddlers between bags
    • document tiddlyspace.com customizations (perhaps in tsarch)
    • more on tsapp
    • get twikifier (or the tw5 replacement) and twsock properly packaged and deployable
    • continue with tiddlyweb space
    • translate timer.py to timer.js
    • CORS pre-flight checks plugin for TiddlyWeb.
    • extract some of the cpie stuff as widgets (e.g. file upload drag-n-drop)

    If you want something to be on my plate, tell me.

    Syndicated 2011-01-25 14:13:10 (Updated 2012-05-07 16:55:23) from cdent

    60 older entries...

    New Advogato Features

    New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

    Keep up with the latest Advogato features by reading the Advogato status blog.

    If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!