Refactoring source file layout

print-window-tiddler
Jeremy Ruston 2011-11-22 17:42:03 +00:00
rodzic 44974ddb44
commit d490e1543d
9 zmienionych plików z 297 dodań i 279 usunięć

1
.gitignore vendored 100644
Wyświetl plik

@ -0,0 +1 @@
.DS_Store

0
js/ArgParser.js 100644 → 100755
Wyświetl plik

12
js/Recipe.js 100644 → 100755
Wyświetl plik

@ -28,7 +28,9 @@ this.ingredients = {
*/
var tiddler = require("./Tiddler.js"),
tiddlerUtils = require("./TiddlerUtils.js"),
tiddlerInput = require("./TiddlerInput.js"),
tiddlerOutput = require("./TiddlerOutput.js"),
utils = require("./Utils.js"),
tiddlywiki = require("./TiddlyWiki.js"),
fs = require("fs"),
path = require("path"),
@ -102,11 +104,11 @@ Recipe.prototype.readIngredient = function(dirname,filepath) {
title: basename
};
// Read the tiddler file
fields = tiddlerUtils.parseTiddler(fs.readFileSync(fullpath,"utf8"),extname,fields);
fields = tiddlerInput.parseTiddler(fs.readFileSync(fullpath,"utf8"),extname,fields);
// Check for the .meta file
var metafile = fullpath + ".meta";
if(path.existsSync(metafile)) {
fields = tiddlerUtils.parseMetaDataBlock(fs.readFileSync(metafile,"utf8"),fields);
fields = tiddlerInput.parseMetaDataBlock(fs.readFileSync(metafile,"utf8"),fields);
}
return fields;
}
@ -164,7 +166,7 @@ Recipe.ingredientOutputter = {
// Ordinary tiddlers are output as a <DIV>
for(var t=0; t<ingredient.length; t++) {
var tid = ingredient[t];
tiddlerUtils.outputTiddlerDiv(out,tid);
tiddlerOutput.outputTiddlerDiv(out,tid);
}
},
javascript: function(out,ingredient) {
@ -196,7 +198,7 @@ Recipe.ingredientOutputter = {
} else {
tweakedTiddler = tid;
}
tiddlerUtils.outputTiddlerDiv(out,tweakedTiddler,{omitPrecedingLineFeed: true});
tiddlerOutput.outputTiddlerDiv(out,tweakedTiddler);
}
}
};

0
js/Tiddler.js 100644 → 100755
Wyświetl plik

154
js/TiddlerInput.js 100755
Wyświetl plik

@ -0,0 +1,154 @@
/*
Functions concerned with parsing representations of tiddlers
*/
var argParser = require("./ArgParser.js"),
utils = require("./Utils.js");
var tiddlerInput = exports;
/*
Parse a tiddler given its mimetype, and merge the results into a hashmap of tiddler fields.
A file extension can be passed as a shortcut for the mimetype, as shown in tiddlerUtils.fileExtensionMappings.
For example ".txt" file extension is mapped to the "text/plain" mimetype.
Special processing to extract embedded metadata is applied to some mimetypes.
*/
tiddlerInput.parseTiddler = function(text,type,fields) {
if(fields === undefined) {
var fields = {};
}
// Map extensions to mimetpyes
var fileExtensionMapping = tiddlerInput.fileExtensionMappings[type];
if(fileExtensionMapping)
type = fileExtensionMapping;
// Invoke the parser for the specified mimetype
var parser = tiddlerInput.parseTiddlerByMimeType[type];
if(parser) {
return parser(text,fields);
}
return fields;
}
tiddlerInput.fileExtensionMappings = {
".txt": "text/plain",
".html": "text/html",
".tiddler": "application/x-tiddler-html-div",
".tid": "application/x-tiddler",
".js": "application/javascript"
}
tiddlerInput.parseTiddlerByMimeType = {
"text/plain": function(text,fields) {
fields.text = text;
return fields;
},
"text/html": function(text,fields) {
fields.text = text;
return fields;
},
"application/x-tiddler-html-div": function(text,fields) {
fields = tiddlerInput.parseTiddlerDiv(text,fields);
return fields;
},
"application/x-tiddler": function(text,fields) {
var split = text.indexOf("\n\n");
if(split === -1) {
split = text.length;
}
fields = tiddlerInput.parseMetaDataBlock(text.substr(0,split),fields);
fields.text = text.substr(split + 2);
return fields;
},
"application/javascript": function(text,fields) {
fields.text = text;
return fields;
}
}
/*
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
*/
tiddlerInput.parseMetaDataBlock = function(metaData,fields) {
if(fields === undefined) {
var fields = {};
}
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();
fields[field] = tiddlerInput.parseMetaDataItem(field,value);
}
});
return fields;
}
/*
Parse an old-style tiddler DIV. It looks like this:
<div title="Title" creator="JoeBloggs" modifier="JoeBloggs" created="201102111106" modified="201102111310" tags="myTag [[my long tag]]">
<pre>The text of the tiddler (without the expected HTML encoding).
</pre>
</div>
Note that the field attributes are HTML encoded, but that the body of the <PRE> tag is not.
*/
tiddlerInput.parseTiddlerDiv = function(text,fields) {
if(fields === undefined) {
var fields = {};
}
var divRegExp = /^\s*<div\s+([^>]*)>((?:.|\n)*)<\/div>\s*$/gi;
var subDivRegExp = /^(?:\s*<pre>)((?:.|\n)*)(?:<\/pre>\s*)$/gi;
var attrRegExp = /\s*([^=\s]+)\s*=\s*"([^"]*)"/gi;
var match = divRegExp.exec(text);
if(match) {
var subMatch = subDivRegExp.exec(match[2]); // Body of the <DIV> tag
if(subMatch) {
fields.text = subMatch[1];
} else {
fields.text = match[2];
}
do {
var attrMatch = attrRegExp.exec(match[1]);
if(attrMatch) {
var name = attrMatch[1];
var value = attrMatch[2];
fields[name] = tiddlerInput.parseMetaDataItem(name,value);
}
} while(attrMatch);
}
return fields;
}
/*
Parse a single metadata field/value pair and return the value as the appropriate data type
*/
tiddlerInput.parseMetaDataItem = function(field,value) {
var result;
switch(field) {
case "modified":
case "created":
result = utils.convertFromYYYYMMDDHHMMSS(value);
break;
case "tags":
var parser = new argParser.ArgParser(value,{noNames: true});
result = parser.getValuesByName("","");
break;
default:
result = value;
break;
}
return result;
}

Wyświetl plik

@ -0,0 +1,61 @@
/*
Functions concerned with parsing representations of tiddlers
*/
var argParser = require("./ArgParser.js"),
utils = require("./Utils.js");
var tiddlerOutput = exports;
/*
Output a tiddler as an HTML <DIV>
out - array to push the output strings
tid - the tiddler to be output
options - options:
omitPrecedingLineFeed - determines if a linefeed is inserted between the <PRE> tag and the text
*/
tiddlerOutput.outputTiddlerDiv = function(out,tid) {
var result = [];
var outputAttribute = function(name,value) {
result.push(" " + name + "=\"" + value + "\"");
};
result.push("<div");
for(var t in tid.fields) {
switch(t) {
case "text":
// Ignore the text field
break;
case "tags":
// Output tags as a list
outputAttribute(t,tiddlerOutput.stringifyTags(tid.fields.tags));
break;
case "modified":
case "created":
// Output dates in YYYYMMDDHHMMSS
outputAttribute(t,utils.convertToYYYYMMDDHHMM(tid.fields[t]));
break;
default:
// Output other attributes raw
outputAttribute(t,tid.fields[t]);
break;
}
}
result.push(">\n<pre>\n");
result.push(utils.htmlEncode(tid.fields.text));
result.push("</pre>\n</div>");
out.push(result.join(""));
}
tiddlerOutput.stringifyTags = function(tags) {
var results = [];
for(var t=0; t<tags.length; t++) {
if(tags[t].indexOf(" ") !== -1) {
results.push("[[" + tags[t] + "]]");
} else {
results.push(tags[t]);
}
}
return results.join(" ");
}

Wyświetl plik

@ -1,274 +0,0 @@
/*
Various static utility functions concerned with parsing and generating representations of tiddlers and
other objects.
This file is a bit of a dumping ground; the expectation is that most of these functions will be refactored.
*/
var argParser = require("./ArgParser.js");
var tiddlerUtils = exports;
/*
Parse a tiddler given its mimetype, and merge the results into a hashmap of tiddler fields.
A file extension can be passed as a shortcut for the mimetype, as shown in tiddlerUtils.fileExtensionMappings.
For example ".txt" file extension is mapped to the "text/plain" mimetype.
Special processing to extract embedded metadata is applied to some mimetypes.
*/
tiddlerUtils.parseTiddler = function(text,type,fields) {
if(fields === undefined) {
var fields = {};
}
// Map extensions to mimetpyes
var fileExtensionMapping = tiddlerUtils.fileExtensionMappings[type];
if(fileExtensionMapping)
type = fileExtensionMapping;
// Invoke the parser for the specified mimetype
var parser = tiddlerUtils.parseTiddlerByMimeType[type];
if(parser) {
return parser(text,fields);
}
return fields;
}
tiddlerUtils.fileExtensionMappings = {
".txt": "text/plain",
".html": "text/html",
".tiddler": "application/x-tiddler-html-div",
".tid": "application/x-tiddler",
".js": "application/javascript"
}
tiddlerUtils.parseTiddlerByMimeType = {
"text/plain": function(text,fields) {
fields.text = text;
return fields;
},
"text/html": function(text,fields) {
fields.text = text;
return fields;
},
"application/x-tiddler-html-div": function(text,fields) {
fields = tiddlerUtils.parseTiddlerDiv(text,fields);
return fields;
},
"application/x-tiddler": function(text,fields) {
var split = text.indexOf("\n\n");
if(split === -1) {
split = text.length;
}
fields = tiddlerUtils.parseMetaDataBlock(text.substr(0,split),fields);
fields.text = text.substr(split + 2);
return fields;
},
"application/javascript": function(text,fields) {
fields.text = text;
return fields;
}
}
/*
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
*/
tiddlerUtils.parseMetaDataBlock = function(metaData,fields) {
if(fields === undefined) {
var fields = {};
}
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();
fields[field] = tiddlerUtils.parseMetaDataItem(field,value);
}
});
return fields;
}
/*
Parse an old-style tiddler DIV. It looks like this:
<div title="Title" creator="JoeBloggs" modifier="JoeBloggs" created="201102111106" modified="201102111310" tags="myTag [[my long tag]]">
<pre>The text of the tiddler (without the expected HTML encoding).
</pre>
</div>
Note that the field attributes are HTML encoded, but that the body of the <PRE> tag is not.
*/
tiddlerUtils.parseTiddlerDiv = function(text,fields) {
if(fields === undefined) {
var fields = {};
}
var divRegExp = /^\s*<div\s+([^>]*)>((?:.|\n)*)<\/div>\s*$/gi;
var subDivRegExp = /^(?:\s*<pre>)((?:.|\n)*)(?:<\/pre>\s*)$/gi;
var attrRegExp = /\s*([^=\s]+)\s*=\s*"([^"]*)"/gi;
var match = divRegExp.exec(text);
if(match) {
var subMatch = subDivRegExp.exec(match[2]); // Body of the <DIV> tag
if(subMatch) {
fields.text = subMatch[1];
} else {
fields.text = match[2];
}
do {
var attrMatch = attrRegExp.exec(match[1]);
if(attrMatch) {
var name = attrMatch[1];
var value = attrMatch[2];
fields[name] = tiddlerUtils.parseMetaDataItem(name,value);
}
} while(attrMatch);
}
return fields;
}
// Output a tiddler as an HTML <DIV>
// out - array to push the output strings
// tid - the tiddler to be output
// options - options:
// omitPrecedingLineFeed - determines if a linefeed is inserted between the <PRE> tag and the text
tiddlerUtils.outputTiddlerDiv = function(out,tid,options) {
var result = [];
var outputAttribute = function(name,value) {
result.push(" " + name + "=\"" + value + "\"");
};
result.push("<div");
for(var t in tid.fields) {
switch(t) {
case "text":
// Ignore the text field
break;
case "tags":
// Output tags as a list
outputAttribute(t,tiddlerUtils.stringifyTags(tid.fields.tags));
break;
case "modified":
case "created":
// Output dates in YYYYMMDDHHMMSS
outputAttribute(t,tiddlerUtils.convertToYYYYMMDDHHMM(tid.fields[t]));
break;
default:
// Output other attributes raw
outputAttribute(t,tid.fields[t]);
break;
}
}
result.push(">\n<pre>");
if(!(options && options.omitPrecedingLineFeed))
result.push("\n");
result.push(tiddlerUtils.htmlEncode(tid.fields.text));
result.push("</pre>\n</div>");
out.push(result.join(""));
}
tiddlerUtils.stringifyTags = function(tags) {
var results = [];
for(var t=0; t<tags.length; t++) {
if(tags[t].indexOf(" ") !== -1) {
results.push("[[" + tags[t] + "]]");
} else {
results.push(tags[t]);
}
}
return results.join(" ");
}
/*
Parse a single metadata field/value pair and return the value as the appropriate data type
*/
tiddlerUtils.parseMetaDataItem = function(field,value) {
var result;
switch(field) {
case "modified":
case "created":
result = tiddlerUtils.convertFromYYYYMMDDHHMMSS(value);
break;
case "tags":
var parser = new argParser.ArgParser(value,{noNames: true});
result = parser.getValuesByName("","");
break;
default:
result = value;
break;
}
return result;
}
// Pad a string to a certain length with zeros
tiddlerUtils.zeroPad = function(n,d)
{
var s = n.toString();
if(s.length < d)
s = "000000000000000000000000000".substr(0,d-s.length) + s;
return s;
};
// Convert a date to local YYYYMMDDHHMM string format
tiddlerUtils.convertToLocalYYYYMMDDHHMM = function(date)
{
return date.getFullYear() + tiddlerUtils.zeroPad(date.getMonth()+1,2) + tiddlerUtils.zeroPad(date.getDate(),2) + tiddlerUtils.zeroPad(date.getHours(),2) + tiddlerUtils.zeroPad(date.getMinutes(),2);
};
// Convert a date to UTC YYYYMMDDHHMM string format
tiddlerUtils.convertToYYYYMMDDHHMM = function(date)
{
return date.getUTCFullYear() + tiddlerUtils.zeroPad(date.getUTCMonth()+1,2) + tiddlerUtils.zeroPad(date.getUTCDate(),2) + tiddlerUtils.zeroPad(date.getUTCHours(),2) + tiddlerUtils.zeroPad(date.getUTCMinutes(),2);
};
// Convert a date to UTC YYYYMMDD.HHMMSSMMM string format
tiddlerUtils.convertToYYYYMMDDHHMMSSMMM = function(date)
{
return date.getUTCFullYear() + tiddlerUtils.zeroPad(date.getUTCMonth()+1,2) + tiddlerUtils.zeroPad(date.getUTCDate(),2) + "." + tiddlerUtils.zeroPad(date.getUTCHours(),2) + tiddlerUtils.zeroPad(date.getUTCMinutes(),2) + tiddlerUtils.zeroPad(date.getUTCSeconds(),2) + tiddlerUtils.zeroPad(date.getUTCMilliseconds(),3) +"0";
};
// Create a date from a UTC YYYYMMDDHHMM format string
tiddlerUtils.convertFromYYYYMMDDHHMM = function(d)
{
d = d?d.replace(/[^0-9]/g, ""):"";
return tiddlerUtils.convertFromYYYYMMDDHHMMSSMMM(d.substr(0,12));
};
// Create a date from a UTC YYYYMMDDHHMMSS format string
tiddlerUtils.convertFromYYYYMMDDHHMMSS = function(d)
{
d = d?d.replace(/[^0-9]/g, ""):"";
return tiddlerUtils.convertFromYYYYMMDDHHMMSSMMM(d.substr(0,14));
};
// Create a date from a UTC YYYYMMDDHHMMSSMMM format string
tiddlerUtils.convertFromYYYYMMDDHHMMSSMMM = function(d)
{
d = d ? d.replace(/[^0-9]/g, "") : "";
return new Date(Date.UTC(parseInt(d.substr(0,4),10),
parseInt(d.substr(4,2),10)-1,
parseInt(d.substr(6,2),10),
parseInt(d.substr(8,2)||"00",10),
parseInt(d.substr(10,2)||"00",10),
parseInt(d.substr(12,2)||"00",10),
parseInt(d.substr(14,3)||"000",10)));
};
// Convert & to "&amp;", < to "&lt;", > to "&gt;" and " to "&quot;"
tiddlerUtils.htmlEncode = function(s)
{
return s.replace(/&/mg,"&amp;").replace(/</mg,"&lt;").replace(/>/mg,"&gt;").replace(/\"/mg,"&quot;");
};
// Convert "&amp;" to &, "&lt;" to <, "&gt;" to > and "&quot;" to "
tiddlerUtils.htmlDecode = function(s)
{
return s.replace(/&lt;/mg,"<").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
};

0
js/TiddlyWiki.js 100644 → 100755
Wyświetl plik

74
js/Utils.js 100755
Wyświetl plik

@ -0,0 +1,74 @@
/*
Various static utility functions.
This file is a bit of a dumping ground; the expectation is that most of these functions will be refactored.
*/
var utils = exports;
// Pad a string to a certain length with zeros
utils.zeroPad = function(n,d)
{
var s = n.toString();
if(s.length < d)
s = "000000000000000000000000000".substr(0,d-s.length) + s;
return s;
};
// Convert a date to local YYYYMMDDHHMM string format
utils.convertToLocalYYYYMMDDHHMM = function(date)
{
return date.getFullYear() + utils.zeroPad(date.getMonth()+1,2) + utils.zeroPad(date.getDate(),2) + utils.zeroPad(date.getHours(),2) + utils.zeroPad(date.getMinutes(),2);
};
// Convert a date to UTC YYYYMMDDHHMM string format
utils.convertToYYYYMMDDHHMM = function(date)
{
return date.getUTCFullYear() + utils.zeroPad(date.getUTCMonth()+1,2) + utils.zeroPad(date.getUTCDate(),2) + utils.zeroPad(date.getUTCHours(),2) + utils.zeroPad(date.getUTCMinutes(),2);
};
// Convert a date to UTC YYYYMMDD.HHMMSSMMM string format
utils.convertToYYYYMMDDHHMMSSMMM = function(date)
{
return date.getUTCFullYear() + utils.zeroPad(date.getUTCMonth()+1,2) + utils.zeroPad(date.getUTCDate(),2) + "." + utils.zeroPad(date.getUTCHours(),2) + utils.zeroPad(date.getUTCMinutes(),2) + utils.zeroPad(date.getUTCSeconds(),2) + utils.zeroPad(date.getUTCMilliseconds(),3) +"0";
};
// Create a date from a UTC YYYYMMDDHHMM format string
utils.convertFromYYYYMMDDHHMM = function(d)
{
d = d?d.replace(/[^0-9]/g, ""):"";
return utils.convertFromYYYYMMDDHHMMSSMMM(d.substr(0,12));
};
// Create a date from a UTC YYYYMMDDHHMMSS format string
utils.convertFromYYYYMMDDHHMMSS = function(d)
{
d = d?d.replace(/[^0-9]/g, ""):"";
return utils.convertFromYYYYMMDDHHMMSSMMM(d.substr(0,14));
};
// Create a date from a UTC YYYYMMDDHHMMSSMMM format string
utils.convertFromYYYYMMDDHHMMSSMMM = function(d)
{
d = d ? d.replace(/[^0-9]/g, "") : "";
return new Date(Date.UTC(parseInt(d.substr(0,4),10),
parseInt(d.substr(4,2),10)-1,
parseInt(d.substr(6,2),10),
parseInt(d.substr(8,2)||"00",10),
parseInt(d.substr(10,2)||"00",10),
parseInt(d.substr(12,2)||"00",10),
parseInt(d.substr(14,3)||"000",10)));
};
// Convert & to "&amp;", < to "&lt;", > to "&gt;" and " to "&quot;"
utils.htmlEncode = function(s)
{
return s.replace(/&/mg,"&amp;").replace(/</mg,"&lt;").replace(/>/mg,"&gt;").replace(/\"/mg,"&quot;");
};
// Convert "&amp;" to &, "&lt;" to <, "&gt;" to > and "&quot;" to "
utils.htmlDecode = function(s)
{
return s.replace(/&lt;/mg,"<").replace(/&gt;/mg,">").replace(/&quot;/mg,"\"").replace(/&amp;/mg,"&");
};