Brought in the TiddlyWiki wikifier code

This is pretty much the raw TiddlyWiki code. Formatter.js incorporates
FormatterHelper.js, too.
This commit is contained in:
Jeremy Ruston 2011-12-03 16:13:35 +00:00
parent 9d4bfc1dec
commit 28cce8b269
2 changed files with 836 additions and 0 deletions

625
js/Formatter.js Executable file
View File

@ -0,0 +1,625 @@
/*global require: false, exports: false, process: false */
"use strict";
var Tiddler = require("./Tiddler.js").Tiddler,
TiddlyWiki = require("./TiddlyWiki.js").TiddlyWiki,
utils = require("./Utils.js"),
util = require("util");
function Formatter(formatters)
{
var n;
this.formatters = [];
var pattern = [];
for(n=0; n<formatters.length; n++) {
pattern.push("(" + formatters[n].match + ")");
this.formatters.push(formatters[n]);
}
this.formatterRegExp = new RegExp(pattern.join("|"),"mg");
}
config.formatterHelpers = {
createElementAndWikify: function(w)
{
w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
},
inlineCssHelper: function(w)
{
var styles = [];
config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
var s,v;
if(lookaheadMatch[1]) {
s = lookaheadMatch[1].unDash();
v = lookaheadMatch[2];
} else {
s = lookaheadMatch[3].unDash();
v = lookaheadMatch[4];
}
if(s=="bgcolor")
s = "backgroundColor";
if(s=="float")
s = "cssFloat";
styles.push({style: s, value: v});
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
config.textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = config.textPrimitives.cssLookaheadRegExp.exec(w.source);
}
return styles;
},
applyCssHelper: function(e,styles)
{
var t;
for(t=0; t< styles.length; t++) {
try {
e.style[styles[t].style] = styles[t].value;
} catch (ex) {
}
}
},
enclosedTextHelper: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
if(config.browser.isIE)
text = text.replace(/\n/g,"\r");
createTiddlyElement(w.output,this.element,null,null,text);
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
}
},
isExternalLink: function(link)
{
if(store.tiddlerExists(link) || store.isShadowTiddler(link)) {
//# Definitely not an external link
return false;
}
var urlRegExp = new RegExp(config.textPrimitives.urlPattern,"mg");
if(urlRegExp.exec(link)) {
//# Definitely an external link
return true;
}
if(link.indexOf(".")!=-1 || link.indexOf("\\")!=-1 || link.indexOf("/")!=-1 || link.indexOf("#")!=-1) {
//# Link contains . / \ or # so is probably an external link
return true;
}
//# Otherwise assume it is not an external link
return false;
}
};
config.formatters = [
{
name: "table",
match: "^\\|(?:[^\\n]*)\\|(?:[fhck]?)$",
lookaheadRegExp: /^\|([^\n]*)\|([fhck]?)$/mg,
rowTermRegExp: /(\|(?:[fhck]?)$\n?)/mg,
cellRegExp: /(?:\|([^\n\|]*)\|)|(\|[fhck]?$\n?)/mg,
cellTermRegExp: /((?:\x20*)\|)/mg,
rowTypes: {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
handler: function(w)
{
var table = createTiddlyElement(w.output,"table",null,"twtable");
var prevColumns = [];
var currRowType = null;
var rowContainer;
var rowCount = 0;
var onmouseover = function() {jQuery(this).addClass("hoverRow");};
var onmouseout = function() {jQuery(this).removeClass("hoverRow");};
w.nextMatch = w.matchStart;
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
var nextRowType = lookaheadMatch[2];
if(nextRowType == "k") {
table.className = lookaheadMatch[1];
w.nextMatch += lookaheadMatch[0].length+1;
} else {
if(nextRowType != currRowType) {
rowContainer = createTiddlyElement(table,this.rowTypes[nextRowType]);
currRowType = nextRowType;
}
if(currRowType == "c") {
// Caption
w.nextMatch++;
if(rowContainer != table.firstChild)
table.insertBefore(rowContainer,table.firstChild);
rowContainer.setAttribute("align",rowCount == 0?"top":"bottom");
w.subWikifyTerm(rowContainer,this.rowTermRegExp);
} else {
var theRow = createTiddlyElement(rowContainer,"tr",null,rowCount%2?"oddRow":"evenRow");
theRow.onmouseover = onmouseover;
theRow.onmouseout = onmouseout;
this.rowHandler(w,theRow,prevColumns);
rowCount++;
}
}
this.lookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
}
},
rowHandler: function(w,e,prevColumns)
{
var col = 0;
var colSpanCount = 1;
var prevCell = null;
this.cellRegExp.lastIndex = w.nextMatch;
var cellMatch = this.cellRegExp.exec(w.source);
while(cellMatch && cellMatch.index == w.nextMatch) {
if(cellMatch[1] == "~") {
// Rowspan
var last = prevColumns[col];
if(last) {
last.rowSpanCount++;
last.element.setAttribute("rowspan",last.rowSpanCount);
last.element.setAttribute("rowSpan",last.rowSpanCount); // Needed for IE
last.element.valign = "center";
if(colSpanCount > 1) {
last.element.setAttribute("colspan",colSpanCount);
last.element.setAttribute("colSpan",colSpanCount); // Needed for IE
colSpanCount = 1;
}
}
w.nextMatch = this.cellRegExp.lastIndex-1;
} else if(cellMatch[1] == ">") {
// Colspan
colSpanCount++;
w.nextMatch = this.cellRegExp.lastIndex-1;
} else if(cellMatch[2]) {
// End of row
if(prevCell && colSpanCount > 1) {
prevCell.setAttribute("colspan",colSpanCount);
prevCell.setAttribute("colSpan",colSpanCount); // Needed for IE
}
w.nextMatch = this.cellRegExp.lastIndex;
break;
} else {
// Cell
w.nextMatch++;
var styles = config.formatterHelpers.inlineCssHelper(w);
var spaceLeft = false;
var chr = w.source.substr(w.nextMatch,1);
while(chr == " ") {
spaceLeft = true;
w.nextMatch++;
chr = w.source.substr(w.nextMatch,1);
}
var cell;
if(chr == "!") {
cell = createTiddlyElement(e,"th");
w.nextMatch++;
} else {
cell = createTiddlyElement(e,"td");
}
prevCell = cell;
prevColumns[col] = {rowSpanCount:1,element:cell};
if(colSpanCount > 1) {
cell.setAttribute("colspan",colSpanCount);
cell.setAttribute("colSpan",colSpanCount); // Needed for IE
colSpanCount = 1;
}
config.formatterHelpers.applyCssHelper(cell,styles);
w.subWikifyTerm(cell,this.cellTermRegExp);
if(w.matchText.substr(w.matchText.length-2,1) == " ") // spaceRight
cell.align = spaceLeft ? "center" : "left";
else if(spaceLeft)
cell.align = "right";
w.nextMatch--;
}
col++;
this.cellRegExp.lastIndex = w.nextMatch;
cellMatch = this.cellRegExp.exec(w.source);
}
}
},
{
name: "heading",
match: "^!{1,6}",
termRegExp: /(\n)/mg,
handler: function(w)
{
w.subWikifyTerm(createTiddlyElement(w.output,"h" + w.matchLength),this.termRegExp);
}
},
{
name: "list",
match: "^(?:[\\*#;:]+)",
lookaheadRegExp: /^(?:(?:(\*)|(#)|(;)|(:))+)/mg,
termRegExp: /(\n)/mg,
handler: function(w)
{
var stack = [w.output];
var currLevel = 0, currType = null;
var listLevel, listType, itemType, baseType;
w.nextMatch = w.matchStart;
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
if(lookaheadMatch[1]) {
listType = "ul";
itemType = "li";
} else if(lookaheadMatch[2]) {
listType = "ol";
itemType = "li";
} else if(lookaheadMatch[3]) {
listType = "dl";
itemType = "dt";
} else if(lookaheadMatch[4]) {
listType = "dl";
itemType = "dd";
}
if(!baseType)
baseType = listType;
listLevel = lookaheadMatch[0].length;
w.nextMatch += lookaheadMatch[0].length;
var t;
if(listLevel > currLevel) {
for(t=currLevel; t<listLevel; t++) {
var target = (currLevel == 0) ? stack[stack.length-1] : stack[stack.length-1].lastChild;
stack.push(createTiddlyElement(target,listType));
}
} else if(listType!=baseType && listLevel==1) {
w.nextMatch -= lookaheadMatch[0].length;
return;
} else if(listLevel < currLevel) {
for(t=currLevel; t>listLevel; t--)
stack.pop();
} else if(listLevel == currLevel && listType != currType) {
stack.pop();
stack.push(createTiddlyElement(stack[stack.length-1].lastChild,listType));
}
currLevel = listLevel;
currType = listType;
var e = createTiddlyElement(stack[stack.length-1],itemType);
w.subWikifyTerm(e,this.termRegExp);
this.lookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
}
}
},
{
name: "quoteByBlock",
match: "^<<<\\n",
termRegExp: /(^<<<(\n|$))/mg,
element: "blockquote",
handler: config.formatterHelpers.createElementAndWikify
},
{
name: "quoteByLine",
match: "^>+",
lookaheadRegExp: /^>+/mg,
termRegExp: /(\n)/mg,
element: "blockquote",
handler: function(w)
{
var stack = [w.output];
var currLevel = 0;
var newLevel = w.matchLength;
var t,matched;
do {
if(newLevel > currLevel) {
for(t=currLevel; t<newLevel; t++)
stack.push(createTiddlyElement(stack[stack.length-1],this.element));
} else if(newLevel < currLevel) {
for(t=currLevel; t>newLevel; t--)
stack.pop();
}
currLevel = newLevel;
w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
createTiddlyElement(stack[stack.length-1],"br");
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
if(matched) {
newLevel = lookaheadMatch[0].length;
w.nextMatch += lookaheadMatch[0].length;
}
} while(matched);
}
},
{
name: "rule",
match: "^----+$\\n?|<hr ?/?>\\n?",
handler: function(w)
{
createTiddlyElement(w.output,"hr");
}
},
{
name: "monospacedByLine",
match: "^(?:/\\*\\{\\{\\{\\*/|\\{\\{\\{|//\\{\\{\\{|<!--\\{\\{\\{-->)\\n",
element: "pre",
handler: function(w)
{
switch(w.matchText) {
case "/*{{{*/\n": // CSS
this.lookaheadRegExp = /\/\*\{\{\{\*\/\n*((?:^[^\n]*\n)+?)(\n*^\f*\/\*\}\}\}\*\/$\n?)/mg;
break;
case "{{{\n": // monospaced block
this.lookaheadRegExp = /^\{\{\{\n((?:^[^\n]*\n)+?)(^\f*\}\}\}$\n?)/mg;
break;
case "//{{{\n": // plugin
this.lookaheadRegExp = /^\/\/\{\{\{\n\n*((?:^[^\n]*\n)+?)(\n*^\f*\/\/\}\}\}$\n?)/mg;
break;
case "<!--{{{-->\n": //template
this.lookaheadRegExp = /<!--\{\{\{-->\n*((?:^[^\n]*\n)+?)(\n*^\f*<!--\}\}\}-->$\n?)/mg;
break;
default:
break;
}
config.formatterHelpers.enclosedTextHelper.call(this,w);
}
},
{
name: "wikifyComment",
match: "^(?:/\\*\\*\\*|<!---)\\n",
handler: function(w)
{
var termRegExp = (w.matchText == "/***\n") ? (/(^\*\*\*\/\n)/mg) : (/(^--->\n)/mg);
w.subWikifyTerm(w.output,termRegExp);
}
},
{
name: "macro",
match: "<<",
lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
w.nextMatch = this.lookaheadRegExp.lastIndex;
invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
}
}
},
{
name: "prettyLink",
match: "\\[\\[",
lookaheadRegExp: /\[\[(.*?)(?:\|(~)?(.*?))?\]\]/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var e;
var text = lookaheadMatch[1];
if(lookaheadMatch[3]) {
// Pretty bracketted link
var link = lookaheadMatch[3];
e = (!lookaheadMatch[2] && config.formatterHelpers.isExternalLink(link)) ?
createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
} else {
// Simple bracketted link
e = createTiddlyLink(w.output,text,false,null,w.isStatic,w.tiddler);
}
createTiddlyText(e,text);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: "wikiLink",
match: config.textPrimitives.unWikiLink+"?"+config.textPrimitives.wikiLink,
handler: function(w)
{
if(w.matchText.substr(0,1) == config.textPrimitives.unWikiLink) {
w.outputText(w.output,w.matchStart+1,w.nextMatch);
return;
}
if(w.matchStart > 0) {
var preRegExp = new RegExp(config.textPrimitives.anyLetterStrict,"mg");
preRegExp.lastIndex = w.matchStart-1;
var preMatch = preRegExp.exec(w.source);
if(preMatch.index == w.matchStart-1) {
w.outputText(w.output,w.matchStart,w.nextMatch);
return;
}
}
if(w.autoLinkWikiWords || store.isShadowTiddler(w.matchText)) {
var link = createTiddlyLink(w.output,w.matchText,false,null,w.isStatic,w.tiddler);
w.outputText(link,w.matchStart,w.nextMatch);
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
}
},
{
name: "urlLink",
match: config.textPrimitives.urlPattern,
handler: function(w)
{
w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch);
}
},
{
name: "image",
match: "\\[[<>]?[Ii][Mm][Gg]\\[",
//# [<] sequence below is to avoid lessThan-questionMark sequence so TiddlyWikis can be included in PHP files
lookaheadRegExp: /\[([<]?)(>?)[Ii][Mm][Gg]\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var e = w.output;
if(lookaheadMatch[5]) {
var link = lookaheadMatch[5];
e = config.formatterHelpers.isExternalLink(link) ? createExternalLink(w.output,link) : createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler);
jQuery(e).addClass("imageLink");
}
var img = createTiddlyElement(e,"img");
if(lookaheadMatch[1])
img.align = "left";
else if(lookaheadMatch[2])
img.align = "right";
if(lookaheadMatch[3]) {
img.title = lookaheadMatch[3];
img.setAttribute("alt",lookaheadMatch[3]);
}
img.src = lookaheadMatch[4];
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: "html",
match: "<[Hh][Tt][Mm][Ll]>",
lookaheadRegExp: /<[Hh][Tt][Mm][Ll]>((?:.|\n)*?)<\/[Hh][Tt][Mm][Ll]>/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
createTiddlyElement(w.output,"span").innerHTML = lookaheadMatch[1];
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: "commentByBlock",
match: "/%",
lookaheadRegExp: /\/%((?:.|\n)*?)%\//mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
},
{
name: "characterFormat",
match: "''|//|__|\\^\\^|~~|--(?!\\s|$)|\\{\\{\\{",
handler: function(w)
{
switch(w.matchText) {
case "''":
w.subWikifyTerm(w.output.appendChild(document.createElement("strong")),/('')/mg);
break;
case "//":
w.subWikifyTerm(createTiddlyElement(w.output,"em"),/(\/\/)/mg);
break;
case "__":
w.subWikifyTerm(createTiddlyElement(w.output,"u"),/(__)/mg);
break;
case "^^":
w.subWikifyTerm(createTiddlyElement(w.output,"sup"),/(\^\^)/mg);
break;
case "~~":
w.subWikifyTerm(createTiddlyElement(w.output,"sub"),/(~~)/mg);
break;
case "--":
w.subWikifyTerm(createTiddlyElement(w.output,"strike"),/(--)/mg);
break;
case "{{{":
var lookaheadRegExp = /\{\{\{((?:.|\n)*?)\}\}\}/mg;
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
createTiddlyElement(w.output,"code",null,null,lookaheadMatch[1]);
w.nextMatch = lookaheadRegExp.lastIndex;
}
break;
}
}
},
{
name: "customFormat",
match: "@@|\\{\\{",
handler: function(w)
{
switch(w.matchText) {
case "@@":
var e = createTiddlyElement(w.output,"span");
var styles = config.formatterHelpers.inlineCssHelper(w);
if(styles.length == 0)
e.className = "marked";
else
config.formatterHelpers.applyCssHelper(e,styles);
w.subWikifyTerm(e,/(@@)/mg);
break;
case "{{":
var lookaheadRegExp = /\{\{[\s]*([\w]+[\s\w]*)[\s]*\{(\n?)/mg;
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source);
if(lookaheadMatch) {
w.nextMatch = lookaheadRegExp.lastIndex;
e = createTiddlyElement(w.output,lookaheadMatch[2] == "\n" ? "div" : "span",null,lookaheadMatch[1]);
w.subWikifyTerm(e,/(\}\}\})/mg);
}
break;
}
}
},
{
name: "mdash",
match: "--",
handler: function(w)
{
createTiddlyElement(w.output,"span").innerHTML = "&mdash;";
}
},
{
name: "lineBreak",
match: "\\n|<br ?/?>",
handler: function(w)
{
createTiddlyElement(w.output,"br");
}
},
{
name: "rawText",
match: "\"{3}|<nowiki>",
lookaheadRegExp: /(?:\"{3}|<nowiki>)((?:.|\n)*?)(?:\"{3}|<\/nowiki>)/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
createTiddlyElement(w.output,"span",null,null,lookaheadMatch[1]);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: "htmlEntitiesEncoding",
match: "(?:(?:&#?[a-zA-Z0-9]{2,8};|.)(?:&#?(?:x0*(?:3[0-6][0-9a-fA-F]|1D[c-fC-F][0-9a-fA-F]|20[d-fD-F][0-9a-fA-F]|FE2[0-9a-fA-F])|0*(?:76[89]|7[7-9][0-9]|8[0-7][0-9]|761[6-9]|76[2-7][0-9]|84[0-3][0-9]|844[0-7]|6505[6-9]|6506[0-9]|6507[0-1]));)+|&#?[a-zA-Z0-9]{2,8};)",
handler: function(w)
{
createTiddlyElement(w.output,"span").innerHTML = w.matchText;
}
}
];
exports.Formatter = Formatter;

211
js/Wikifier.js Executable file
View File

@ -0,0 +1,211 @@
/*global require: false, exports: false, process: false */
"use strict";
var Tiddler = require("./Tiddler.js").Tiddler,
TiddlyWiki = require("./TiddlyWiki.js").TiddlyWiki,
utils = require("./Utils.js"),
util = require("util");
//# Construct a wikifier object
//# source - source string that's going to be wikified
//# formatter - Formatter() object containing the list of formatters to be used
//# highlightRegExp - regular expression of the text string to highlight
//# tiddler - reference to the tiddler that's taken to be the container for this wikification
var Wikifier = function(source,formatter,highlightRegExp,tiddler)
{
this.source = source;
this.output = null;
this.formatter = formatter;
this.nextMatch = 0;
this.autoLinkWikiWords = tiddler && tiddler.autoLinkWikiWords() == false ? false : true;
this.highlightRegExp = highlightRegExp;
this.highlightMatch = null;
this.isStatic = false;
if(highlightRegExp) {
highlightRegExp.lastIndex = 0;
this.highlightMatch = highlightRegExp.exec(source);
}
this.tiddler = tiddler;
}
Wikifier.prototype.wikifyPlain = function()
{
var e = createTiddlyElement(document.body,"div");
e.style.display = "none";
this.subWikify(e);
var text = jQuery(e).text();
jQuery(e).remove();
return text;
};
Wikifier.prototype.subWikify = function(output,terminator)
{
//# Handle the terminated and unterminated cases separately, this speeds up wikifikation by about 30%
try {
if(terminator)
this.subWikifyTerm(output,new RegExp("(" + terminator + ")","mg"));
else
this.subWikifyUnterm(output);
} catch(ex) {
showException(ex);
}
};
Wikifier.prototype.subWikifyUnterm = function(output)
{
//# subWikify can be indirectly recursive, so we need to save the old output pointer
var oldOutput = this.output;
this.output = output;
//# Get the first match
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
var formatterMatch = this.formatter.formatterRegExp.exec(this.source);
while(formatterMatch) {
// Output any text before the match
if(formatterMatch.index > this.nextMatch)
this.outputText(this.output,this.nextMatch,formatterMatch.index);
// Set the match parameters for the handler
this.matchStart = formatterMatch.index;
this.matchLength = formatterMatch[0].length;
this.matchText = formatterMatch[0];
this.nextMatch = this.formatter.formatterRegExp.lastIndex;
//# Figure out which formatter matched and call its handler
var t;
for(t=1; t<formatterMatch.length; t++) {
if(formatterMatch[t]) {
this.formatter.formatters[t-1].handler(this);
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
break;
}
}
//# Get the next match
formatterMatch = this.formatter.formatterRegExp.exec(this.source);
}
//# Output any text after the last match
if(this.nextMatch < this.source.length) {
this.outputText(this.output,this.nextMatch,this.source.length);
this.nextMatch = this.source.length;
}
//# Restore the output pointer
this.output = oldOutput;
};
Wikifier.prototype.subWikifyTerm = function(output,terminatorRegExp)
{
//# subWikify can be indirectly recursive, so we need to save the old output pointer
var oldOutput = this.output;
this.output = output;
//# Get the first matches for the formatter and terminator RegExps
terminatorRegExp.lastIndex = this.nextMatch;
var terminatorMatch = terminatorRegExp.exec(this.source);
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
var formatterMatch = this.formatter.formatterRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
while(terminatorMatch || formatterMatch) {
//# Check for a terminator match before the next formatter match
if(terminatorMatch && (!formatterMatch || terminatorMatch.index <= formatterMatch.index)) {
//# Output any text before the match
if(terminatorMatch.index > this.nextMatch)
this.outputText(this.output,this.nextMatch,terminatorMatch.index);
//# Set the match parameters
this.matchText = terminatorMatch[1];
this.matchLength = terminatorMatch[1].length;
this.matchStart = terminatorMatch.index;
this.nextMatch = this.matchStart + this.matchLength;
//# Restore the output pointer
this.output = oldOutput;
return;
}
//# It must be a formatter match; output any text before the match
if(formatterMatch.index > this.nextMatch)
this.outputText(this.output,this.nextMatch,formatterMatch.index);
//# Set the match parameters
this.matchStart = formatterMatch.index;
this.matchLength = formatterMatch[0].length;
this.matchText = formatterMatch[0];
this.nextMatch = this.formatter.formatterRegExp.lastIndex;
//# Figure out which formatter matched and call its handler
var t;
for(t=1; t<formatterMatch.length; t++) {
if(formatterMatch[t]) {
this.formatter.formatters[t-1].handler(this);
this.formatter.formatterRegExp.lastIndex = this.nextMatch;
break;
}
}
//# Get the next match
terminatorRegExp.lastIndex = this.nextMatch;
terminatorMatch = terminatorRegExp.exec(this.source);
formatterMatch = this.formatter.formatterRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
}
//# Output any text after the last match
if(this.nextMatch < this.source.length) {
this.outputText(this.output,this.nextMatch,this.source.length);
this.nextMatch = this.source.length;
}
//# Restore the output pointer
this.output = oldOutput;
};
Wikifier.prototype.outputText = function(place,startPos,endPos)
{
//# Check for highlights
while(this.highlightMatch && (this.highlightRegExp.lastIndex > startPos) && (this.highlightMatch.index < endPos) && (startPos < endPos)) {
//# Deal with any plain text before the highlight
if(this.highlightMatch.index > startPos) {
createTiddlyText(place,this.source.substring(startPos,this.highlightMatch.index));
startPos = this.highlightMatch.index;
}
//# Deal with the highlight
var highlightEnd = Math.min(this.highlightRegExp.lastIndex,endPos);
createTiddlyElement(place,"span",null,"highlight",this.source.substring(startPos,highlightEnd));
startPos = highlightEnd;
//# Nudge along to the next highlight if we're done with this one
if(startPos >= this.highlightRegExp.lastIndex)
this.highlightMatch = this.highlightRegExp.exec(this.source);
}
//# Do the unhighlighted text left over
if(startPos < endPos) {
createTiddlyText(place,this.source.substring(startPos,endPos));
}
};
Wikifier.wikify = function(source,output,highlightRegExp,tiddler)
{
if(source) {
var wikifier = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
var t0 = new Date();
wikifier.subWikify(output);
if(tiddler && config.options.chkDisplayInstrumentation)
displayMessage("wikify:" +tiddler.title+ " in " + (new Date()-t0) + " ms");
}
};
Wikifier.wikifyStatic = function(source,highlightRegExp,tiddler,format)
{
var e = createTiddlyElement(document.body,"pre");
e.style.display = "none";
var html = "";
if(source && source != "") {
if(!tiddler)
tiddler = new Tiddler("temp");
var wikifier = new Wikifier(source,getParser(tiddler,format),highlightRegExp,tiddler);
wikifier.isStatic = true;
wikifier.subWikify(e);
html = e.innerHTML;
jQuery(e).remove();
}
return html;
};
//# Wikify a string to plain text
//# text - text to wikify
//# limit - maximum number of characters to generate
//# tiddler - optional reference to the tiddler containing this text
Wikifier.wikifyPlainText = function(text,limit,tiddler)
{
if(limit > 0)
text = text.substr(0,limit);
var wikifier = new Wikifier(text,formatter,null,tiddler);
return wikifier.wikifyPlain();
};
exports.Wikifier = Wikifier;