/*\ title: js/TiddlerInput.js Functions concerned with parsing representations of tiddlers \*/ (function(){ /*jslint node: true */ "use strict"; var utils = require("./Utils.js"), Tiddler = require("./Tiddler.js").Tiddler, util = require("util"); var tiddlerInput = exports; /* Utility function to parse a block of metadata and merge the results into a hashmap of tiddler fields. The block consists of newline delimited lines consisting of the field name, a colon, and then the value. For example: title: Safari modifier: blaine created: 20110211110700 modified: 20110211131020 tags: browsers issues creator: psd */ var parseMetaDataBlock = function(metaData,fields) { var result = {}; if(fields) { for(var t in fields) { result[t] = fields[t]; } } metaData.split("\n").forEach(function(line) { var p = line.indexOf(":"); if(p !== -1) { var field = line.substr(0, p).trim(); var value = line.substr(p+1).trim(); result[field] = value; } }); return result; }; /* Utility function to parse an old-style tiddler DIV. It looks like this:
The text of the tiddler (without the expected HTML encoding).
tag is not. */ var parseTiddlerDiv = function(text,fields) { var result = {}; if(fields) { for(var t in fields) { result[t] = fields[t]; } } var divRegExp = /^\s*]*)>((?:.|\n)*)<\/div>\s*$/gi, subDivRegExp = /^\s*((?:.|\n)*)<\/pre>\s*$/gi, attrRegExp = /\s*([^=\s]+)\s*=\s*"([^"]*)"/gi, match = divRegExp.exec(text); if(match) { var subMatch = subDivRegExp.exec(match[2]); // Body of thetag if(subMatch) { result.text = subMatch[1]; } else { result.text = match[2]; } var attrMatch; do { attrMatch = attrRegExp.exec(match[1]); if(attrMatch) { var name = attrMatch[1]; var value = attrMatch[2]; result[name] = value; } } while(attrMatch); } return result; }; var inputTiddlerPlain = function(text,fields) { fields.text = text; return [fields]; }; var inputTiddlerJavaScript = function(text,fields) { var headerCommentRegExp = /^\/\*\\\n((?:^[^\n]*\n)+?)(^\\\*\/$\n?)/mg, match = headerCommentRegExp.exec(text); fields.text = text; if(match) { fields = parseMetaDataBlock(match[1],fields); } return [fields]; }; var inputTiddlerDiv = function(text,fields) { return [parseTiddlerDiv(text,fields)]; }; var inputTiddler = function(text,fields) { var split = text.indexOf("\n\n"); if(split !== -1) { fields.text = text.substr(split + 2); } if(split === -1) { split = text.length; } fields = parseMetaDataBlock(text.substr(0,split),fields); return [fields]; }; var inputTiddlerJSON = function(text,fields) { var tiddlers = JSON.parse(text), result = [], getKnownFields = function(tid) { var fields = {}; "title text created creator modified modifier type tags".split(" ").forEach(function(value) { fields[value] = tid[value]; }); return fields; }; for(var t=0; t', startSaveAreaRegExp = / /gi, endSaveArea = '', endSaveAreaCaps = '', posOpeningDiv = tiddlywikidoc.search(startSaveAreaRegExp), limitClosingDiv = tiddlywikidoc.indexOf("<"+"!--POST-STOREAREA--"+">"); if(limitClosingDiv == -1) { limitClosingDiv = tiddlywikidoc.indexOf("<"+"!--POST-BODY-START--"+">"); } var start = limitClosingDiv == -1 ? tiddlywikidoc.length : limitClosingDiv, posClosingDiv = tiddlywikidoc.lastIndexOf(endSaveArea,start); if(posClosingDiv == -1) { posClosingDiv = tiddlywikidoc.lastIndexOf(endSaveAreaCaps,start); } return (posOpeningDiv != -1 && posClosingDiv != -1) ? [posOpeningDiv + startSaveArea.length,posClosingDiv] : null; }, results = [], storeAreaPos = locateStoreArea(text); if(storeAreaPos) { var endOfDivRegExp = /(<\/div>\s*)/gi, startPos = storeAreaPos[0]; endOfDivRegExp.lastIndex = startPos; var match = endOfDivRegExp.exec(text); while(match && startPos < storeAreaPos[1]) { var endPos = endOfDivRegExp.lastIndex, tiddlerFields = parseTiddlerDiv(text.substring(startPos,endPos),fields); if(tiddlerFields.text !== null) { tiddlerFields.text = utils.htmlDecode(tiddlerFields.text); results.push(tiddlerFields); } startPos = endPos; match = endOfDivRegExp.exec(text); } } return results; }; // Given a reference to a DOM node, return the tiddlers stored in the immediate child nodes var inputTiddlerDOM = function(node) { var extractTextTiddler = function(node) { var e = node.firstChild; while(e && e.nodeName.toLowerCase() !== "pre") { e = e.nextSibling; } var title = node.getAttribute ? node.getAttribute("title") : null; if(e && title) { var i, attrs = node.attributes, tiddler = { text: utils.htmlDecode(e.innerHTML) }; for(i=attrs.length-1; i >= 0; i--) { if(attrs[i].specified) { var value = attrs[i].value, name = attrs[i].name; if(!Tiddler.isStandardField(name)) { value = utils.unescapeLineBreaks(value); } tiddler[name] = value; } } return tiddler; } else { return null; } }, extractModuleTiddler = function(node) { if(node.hasAttribute && node.hasAttribute("data-tiddler-title")) { var text = node.innerHTML, s = text.indexOf("{"), e = text.lastIndexOf("}"); if(s !== -1 && e !== -1) { text = text.substring(s+1,e-1); } return { title: node.getAttribute("data-tiddler-title"), text: text, type: "application/javascript" }; } else { return null; } }, t,tiddlers = []; for(t = 0; t < node.childNodes.length; t++) { var tiddler = extractTextTiddler(node.childNodes[t]); tiddler = tiddler || extractModuleTiddler(node.childNodes[t]); if(tiddler) { tiddlers.push(tiddler); } } return tiddlers; }; tiddlerInput.register = function(store) { store.registerTiddlerDeserializer(".txt","text/plain",inputTiddlerPlain); store.registerTiddlerDeserializer(".js","application/javascript",inputTiddlerJavaScript); store.registerTiddlerDeserializer(".tiddler","application/x-tiddler-html-div",inputTiddlerDiv); store.registerTiddlerDeserializer(".tid","application/x-tiddler",inputTiddler); store.registerTiddlerDeserializer(".json","application/json",inputTiddlerJSON); store.registerTiddlerDeserializer(".tiddlywiki","application/x-tiddlywiki",inputTiddlyWiki); store.registerTiddlerDeserializer("(DOM)","(DOM)",inputTiddlerDOM); }; })();