mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2026-01-22 19:04:38 +00:00
Compare commits
5 Commits
multi-wiki
...
v0.0.2-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6315dbdeb | ||
|
|
dc098044dc | ||
|
|
b9e3550747 | ||
|
|
3d1a8ee703 | ||
|
|
17902d1a1e |
12
plugins/tiddlywiki/tw2parser/macrodefs.tid
Normal file
12
plugins/tiddlywiki/tw2parser/macrodefs.tid
Normal file
@@ -0,0 +1,12 @@
|
||||
title: $:/plugins/tiddlywiki/tw2parser/macrodefs
|
||||
|
||||
\define tiddler(t)
|
||||
{{$t$}}
|
||||
\end
|
||||
|
||||
\define slider(chkUniqueCookieName tiddler label tooltip)
|
||||
<span title=$tooltip$><$button popup="$chkUniqueCookieName$" class="btn-invisible tw-slider">$label$</$button>
|
||||
<$reveal type="nomatch" text="" default="" state="$chkUniqueCookieName$" animate="yes">
|
||||
{{$tiddler$}}
|
||||
</$reveal></span>
|
||||
\end
|
||||
8
plugins/tiddlywiki/tw2parser/plugin.info
Normal file
8
plugins/tiddlywiki/tw2parser/plugin.info
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"title": "$:/plugins/tiddlywiki/tw2parser",
|
||||
"description": "legacy parser",
|
||||
"author": "JeremyRuston, JeffreyWilkinson",
|
||||
"version": "0.0.1",
|
||||
"core-version": ">=5.0.0",
|
||||
"plugin-type": "plugin"
|
||||
}
|
||||
193
plugins/tiddlywiki/tw2parser/wikitextparser.js
Normal file
193
plugins/tiddlywiki/tw2parser/wikitextparser.js
Normal file
@@ -0,0 +1,193 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/tw2parser/wikitextparser.js
|
||||
type: application/javascript
|
||||
module-type: parser
|
||||
|
||||
Parses a block of tiddlywiki-format wiki text into a parse tree object. This is a transliterated version of the old TiddlyWiki code. The plan is to replace it with a new, mostly backwards compatible parser built in PEGJS.
|
||||
|
||||
A wikitext parse tree is an array of objects with a `type` field that can be `text`,`macro` or the name of an HTML element.
|
||||
|
||||
Text nodes are represented as `{type: "text", value: "A string of text"}`.
|
||||
|
||||
Macro nodes look like this:
|
||||
`
|
||||
{type: "macro", name: "view", params: {
|
||||
one: {type: "eval", value: "2+2"},
|
||||
two: {type: "string", value: "twenty two"}
|
||||
}}
|
||||
`
|
||||
HTML nodes look like this:
|
||||
`
|
||||
{type: "div", attributes: {
|
||||
src: "one"
|
||||
styles: {
|
||||
"background-color": "#fff",
|
||||
"color": "#000"
|
||||
}
|
||||
}}
|
||||
`
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Creates a new instance of the wiki text parser with the specified options. The
|
||||
options are a hashmap of mandatory members as follows:
|
||||
|
||||
wiki: The wiki object to use to parse any cascaded content (eg transclusion)
|
||||
|
||||
Planned:
|
||||
|
||||
enableRules: An array of names of wiki text rules to enable. If not specified, all rules are available
|
||||
extraRules: An array of additional rule handlers to add
|
||||
enableMacros: An array of names of macros to enable. If not specified, all macros are available
|
||||
extraMacros: An array of additional macro handlers to add
|
||||
*/
|
||||
|
||||
var WikiTextParser = function(type,text,options) {
|
||||
this.wiki = options.wiki;
|
||||
this.autoLinkWikiWords = true;
|
||||
this.installRules();
|
||||
text = text || "no text";
|
||||
this.source = text;
|
||||
this.nextMatch = 0;
|
||||
this.children = [];
|
||||
//this.children.push({type: "text",text:"hello to the queen"});
|
||||
this.tree =[];
|
||||
this.output = null;
|
||||
this.subWikify(this.children);
|
||||
var parser = $tw.wiki.old_parseTiddler("$:/plugins/tiddlywiki/tw2parser/macrodefs",{parseAsInline:false});
|
||||
this.tree = [{
|
||||
type: "element",
|
||||
tag: "div",
|
||||
children:this.children
|
||||
}];
|
||||
Array.prototype.push.apply(parser.tree,this.tree);
|
||||
this.tree = parser.tree;
|
||||
};
|
||||
|
||||
|
||||
WikiTextParser.prototype.installRules = function() {
|
||||
var rules = require("./wikitextrules.js").rules,
|
||||
pattern = [];
|
||||
for(var n=0; n<rules.length; n++) {
|
||||
pattern.push("(" + rules[n].match + ")");
|
||||
}
|
||||
this.rules = rules;
|
||||
this.rulesRegExp = new RegExp(pattern.join("|"),"mg");
|
||||
};
|
||||
|
||||
|
||||
WikiTextParser.prototype.outputText = function(place,startPos,endPos) {
|
||||
if(startPos < endPos) {
|
||||
place.push({type: "text",text:this.source.substring(startPos,endPos)});
|
||||
}
|
||||
};
|
||||
|
||||
WikiTextParser.prototype.subWikify = function(output,terminator) {
|
||||
// Handle the terminated and unterminated cases separately, this speeds up wikifikation by about 30%
|
||||
if(terminator)
|
||||
this.subWikifyTerm(output,new RegExp("(" + terminator + ")","mg"));
|
||||
else
|
||||
this.subWikifyUnterm(output);
|
||||
};
|
||||
|
||||
WikiTextParser.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.rulesRegExp.lastIndex = this.nextMatch;
|
||||
var ruleMatch = this.rulesRegExp.exec(this.source);
|
||||
while(ruleMatch) {
|
||||
// Output any text before the match
|
||||
if(ruleMatch.index > this.nextMatch)
|
||||
this.outputText(this.output,this.nextMatch,ruleMatch.index);
|
||||
// Set the match parameters for the handler
|
||||
this.matchStart = ruleMatch.index;
|
||||
this.matchLength = ruleMatch[0].length;
|
||||
this.matchText = ruleMatch[0];
|
||||
this.nextMatch = this.rulesRegExp.lastIndex;
|
||||
// Figure out which rule matched and call its handler
|
||||
var t;
|
||||
for(t=1; t<ruleMatch.length; t++) {
|
||||
if(ruleMatch[t]) {
|
||||
this.rules[t-1].handler(this);
|
||||
this.rulesRegExp.lastIndex = this.nextMatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Get the next match
|
||||
ruleMatch = this.rulesRegExp.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;
|
||||
};
|
||||
|
||||
WikiTextParser.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 rule and terminator RegExps
|
||||
terminatorRegExp.lastIndex = this.nextMatch;
|
||||
var terminatorMatch = terminatorRegExp.exec(this.source);
|
||||
this.rulesRegExp.lastIndex = this.nextMatch;
|
||||
var ruleMatch = this.rulesRegExp.exec(terminatorMatch ? this.source.substr(0,terminatorMatch.index) : this.source);
|
||||
while(terminatorMatch || ruleMatch) {
|
||||
// Check for a terminator match before the next rule match
|
||||
if(terminatorMatch && (!ruleMatch || terminatorMatch.index <= ruleMatch.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 rule match; output any text before the match
|
||||
if(ruleMatch.index > this.nextMatch)
|
||||
this.outputText(this.output,this.nextMatch,ruleMatch.index);
|
||||
// Set the match parameters
|
||||
this.matchStart = ruleMatch.index;
|
||||
this.matchLength = ruleMatch[0].length;
|
||||
this.matchText = ruleMatch[0];
|
||||
this.nextMatch = this.rulesRegExp.lastIndex;
|
||||
// Figure out which rule matched and call its handler
|
||||
var t;
|
||||
for(t=1; t<ruleMatch.length; t++) {
|
||||
if(ruleMatch[t]) {
|
||||
this.rules[t-1].handler(this);
|
||||
this.rulesRegExp.lastIndex = this.nextMatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Get the next match
|
||||
terminatorRegExp.lastIndex = this.nextMatch;
|
||||
terminatorMatch = terminatorRegExp.exec(this.source);
|
||||
ruleMatch = this.rulesRegExp.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;
|
||||
};
|
||||
|
||||
exports["text/x-tiddlywiki"] = WikiTextParser;
|
||||
|
||||
})();
|
||||
802
plugins/tiddlywiki/tw2parser/wikitextrules.js
Executable file
802
plugins/tiddlywiki/tw2parser/wikitextrules.js
Executable file
@@ -0,0 +1,802 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/tw2parser/wikitextrules.js
|
||||
type: application/javascript
|
||||
module-type: module
|
||||
|
||||
Rule modules for the wikitext parser
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
var textPrimitives = {
|
||||
upperLetter: "[A-Z\u00c0-\u00de\u0150\u0170]",
|
||||
lowerLetter: "[a-z0-9_\\-\u00df-\u00ff\u0151\u0171]",
|
||||
anyLetter: "[A-Za-z0-9_\\-\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]",
|
||||
anyLetterStrict: "[A-Za-z0-9\u00c0-\u00de\u00df-\u00ff\u0150\u0170\u0151\u0171]",
|
||||
sliceSeparator: "::",
|
||||
sectionSeparator: "##",
|
||||
urlPattern: "(?:file|http|https|mailto|ftp|irc|news|data):[^\\s'\"]+(?:/|\\b)",
|
||||
unWikiLink: "~",
|
||||
brackettedLink: "\\[\\[([^\\]]+)\\]\\]",
|
||||
titledBrackettedLink: "\\[\\[([^\\[\\]\\|]+)\\|([^\\[\\]\\|]+)\\]\\]"
|
||||
};
|
||||
|
||||
textPrimitives.wikiLink = "(?:(?:" + textPrimitives.upperLetter + "+" +
|
||||
textPrimitives.lowerLetter + "+" +
|
||||
textPrimitives.upperLetter +
|
||||
textPrimitives.anyLetter + "*)|(?:" +
|
||||
textPrimitives.upperLetter + "{2,}" +
|
||||
textPrimitives.lowerLetter + "+))";
|
||||
|
||||
textPrimitives.cssLookahead = "(?:(" + textPrimitives.anyLetter +
|
||||
"+)\\(([^\\)\\|\\n]+)(?:\\):))|(?:(" + textPrimitives.anyLetter + "+):([^;\\|\\n]+);)";
|
||||
|
||||
textPrimitives.cssLookaheadRegExp = new RegExp(textPrimitives.cssLookahead,"mg");
|
||||
|
||||
textPrimitives.tiddlerForcedLinkRegExp = new RegExp("(?:" + textPrimitives.titledBrackettedLink + ")|(?:" +
|
||||
textPrimitives.brackettedLink + ")|(?:" +
|
||||
textPrimitives.urlPattern + ")","mg");
|
||||
|
||||
textPrimitives.tiddlerAnyLinkRegExp = new RegExp("("+ textPrimitives.wikiLink + ")|(?:" +
|
||||
textPrimitives.titledBrackettedLink + ")|(?:" +
|
||||
textPrimitives.brackettedLink + ")|(?:" +
|
||||
textPrimitives.urlPattern + ")","mg");
|
||||
|
||||
// Helper to add an attribute to an HTML node
|
||||
var setAttr = function(node,attr,value) {
|
||||
if(!node.attributes) {
|
||||
node.attributes = {};
|
||||
}
|
||||
node.attributes[attr] ={type: "string", value:value} ;
|
||||
};
|
||||
|
||||
var inlineCssHelper = function(w) {
|
||||
var styles = [];
|
||||
textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
|
||||
var lookaheadMatch = textPrimitives.cssLookaheadRegExp.exec(w.source);
|
||||
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
|
||||
var s,v;
|
||||
if(lookaheadMatch[1]) {
|
||||
s = lookaheadMatch[1];
|
||||
v = lookaheadMatch[2];
|
||||
} else {
|
||||
s = lookaheadMatch[3];
|
||||
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;
|
||||
textPrimitives.cssLookaheadRegExp.lastIndex = w.nextMatch;
|
||||
lookaheadMatch = textPrimitives.cssLookaheadRegExp.exec(w.source);
|
||||
}
|
||||
return styles;
|
||||
};
|
||||
|
||||
var applyCssHelper = function(e,styles) {
|
||||
|
||||
if(styles.length > 0) {
|
||||
|
||||
for(var t=0; t< styles.length; t++) {
|
||||
$tw.utils.addStyleToParseTreeNode(e,$tw.utils.roundTripPropertyName(styles[t].style),styles[t].value);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var 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];
|
||||
w.output.push({type:"element",tag:this.element,
|
||||
children:[{type: "text",text: lookaheadMatch[1]}]});
|
||||
w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
|
||||
}
|
||||
};
|
||||
|
||||
var insertMacroCall = function(w,output,macroName,paramString) {
|
||||
var params = [],
|
||||
reParam = /\s*(?:([A-Za-z0-9\-_]+)\s*:)?(?:\s*(?:"([^"]*)"|'([^']*)'|\[\[([^\]]*)\]\]|([^"'\s]+)))/mg,
|
||||
paramMatch = reParam.exec(paramString);
|
||||
while(paramMatch) {
|
||||
// Process this parameter
|
||||
var paramInfo = {
|
||||
value: paramMatch[2] || paramMatch[3] || paramMatch[4] || paramMatch[5]
|
||||
};
|
||||
if(paramMatch[1]) {
|
||||
paramInfo.name = paramMatch[1];
|
||||
}
|
||||
params.push(paramInfo);
|
||||
// Find the next match
|
||||
paramMatch = reParam.exec(paramString);
|
||||
}
|
||||
output.push({
|
||||
type: "macrocall",
|
||||
name: macroName,
|
||||
params: params,
|
||||
isBlock: true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var isLinkExternal = function(to) {
|
||||
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data|skype):[^\s'"]+(?:\/|\b)/i;
|
||||
return externalRegExp.test(to);
|
||||
};
|
||||
var rules = [
|
||||
{
|
||||
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 = {type:"element",tag:"table",attributes: {"class": {type: "string", value:"table"}},
|
||||
children: []};
|
||||
|
||||
w.output.push(table);
|
||||
var prevColumns = [];
|
||||
var currRowType = null;
|
||||
var rowContainer;
|
||||
var rowCount = 0;
|
||||
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.attributes["class"] = lookaheadMatch[1];
|
||||
w.nextMatch += lookaheadMatch[0].length+1;
|
||||
} else {
|
||||
if(nextRowType != currRowType) {
|
||||
rowContainer = {type:"element",tag:this.rowTypes[nextRowType],children: []};
|
||||
table.children.push(rowContainer);
|
||||
currRowType = nextRowType;
|
||||
}
|
||||
if(currRowType == "c") {
|
||||
// Caption
|
||||
w.nextMatch++;
|
||||
// Move the caption to the first row if it isn't already
|
||||
if(table.children.length !== 1) {
|
||||
table.children.pop(); // Take rowContainer out of the children array
|
||||
table.children.splice(0,0,rowContainer); // Insert it at the bottom
|
||||
}
|
||||
rowContainer.attributes={};
|
||||
rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
|
||||
w.subWikifyTerm(rowContainer.children,this.rowTermRegExp);
|
||||
} else {
|
||||
var theRow = {type:"element",tag:"tr",
|
||||
attributes: {"class": {type: "string", value:rowCount%2 ? "oddRow" : "evenRow"}},
|
||||
children: []};
|
||||
|
||||
rowContainer.children.push(theRow);
|
||||
this.rowHandler(w,theRow.children,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++;
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"rowspan",last.rowSpanCount);
|
||||
var vAlign = $tw.utils.getAttributeValueFromParseTreeNode(last.element,"valign","center");
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"valign",vAlign);
|
||||
if(colSpanCount > 1) {
|
||||
$tw.utils.addAttributeToParseTreeNode(last.element,"colspan",colSpanCount);
|
||||
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.attributes.colspan = colSpanCount;
|
||||
}
|
||||
w.nextMatch = this.cellRegExp.lastIndex;
|
||||
break;
|
||||
} else {
|
||||
// Cell
|
||||
w.nextMatch++;
|
||||
var styles = 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 = {type:"element",tag:"th",children: []};
|
||||
e.push(cell);
|
||||
w.nextMatch++;
|
||||
} else {
|
||||
cell = {type:"element",tag:"td",children: []};
|
||||
e.push(cell);
|
||||
}
|
||||
prevCell = cell;
|
||||
prevColumns[col] = {rowSpanCount:1,element:cell};
|
||||
if(colSpanCount > 1) {
|
||||
$tw.utils.addAttributeToParseTreeNode(cell,"colspan",colSpanCount);
|
||||
colSpanCount = 1;
|
||||
}
|
||||
applyCssHelper(cell,styles);
|
||||
w.subWikifyTerm(cell.children,this.cellTermRegExp);
|
||||
if (!cell.attributes) cell.attributes ={};
|
||||
if(w.matchText.substr(w.matchText.length-2,1) == " ") // spaceRight
|
||||
$tw.utils.addAttributeToParseTreeNode(cell,"align",spaceLeft ? "center" : "left");
|
||||
else if(spaceLeft)
|
||||
$tw.utils.addAttributeToParseTreeNode(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)
|
||||
{
|
||||
var e = {type:"element",tag:"h" + w.matchLength,children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,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,e;
|
||||
if(listLevel > currLevel) {
|
||||
for(t=currLevel; t<listLevel; t++) {
|
||||
var target = stack[stack.length-1];
|
||||
if(currLevel !== 0 && target.children) {
|
||||
target = target.children[target.children.length-1];
|
||||
}
|
||||
e = {type:"element",tag:listType,children: []};
|
||||
target.push(e);
|
||||
stack.push(e.children);
|
||||
}
|
||||
} 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();
|
||||
e = {type:"element",tag:listType,children: []};
|
||||
stack[stack.length-1].push(e);
|
||||
stack.push(e.children);
|
||||
}
|
||||
currLevel = listLevel;
|
||||
currType = listType;
|
||||
e = {type:"element",tag:itemType,children: []};
|
||||
stack[stack.length-1].push(e);
|
||||
w.subWikifyTerm(e.children,this.termRegExp);
|
||||
this.lookaheadRegExp.lastIndex = w.nextMatch;
|
||||
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "quoteByBlock",
|
||||
match: "^<<<\\n",
|
||||
termRegExp: /(^<<<(\n|$))/mg,
|
||||
element: "blockquote",
|
||||
handler: function(w) {
|
||||
var e = {type:"element",tag:this.element,children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,this.termRegExp);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "quoteByLine",
|
||||
match: "^>+",
|
||||
lookaheadRegExp: /^>+/mg,
|
||||
termRegExp: /(\n)/mg,
|
||||
element: "blockquote",
|
||||
handler: function(w)
|
||||
{
|
||||
var stack = [];
|
||||
var currLevel = 0;
|
||||
var newLevel = w.matchLength;
|
||||
var t,matched,e;
|
||||
do {
|
||||
if(newLevel > currLevel) {
|
||||
for(t=currLevel; t<newLevel; t++) {
|
||||
var f = stack[stack.length-1];
|
||||
e = {type:"element",tag:this.element,children: []};
|
||||
stack.push(e);
|
||||
if (t ===0){
|
||||
w.output.push(e);
|
||||
}else {
|
||||
f.children.push(e);
|
||||
|
||||
}
|
||||
}
|
||||
} else if(newLevel < currLevel) {
|
||||
for(t=currLevel; t>newLevel; t--)
|
||||
stack.pop();
|
||||
}
|
||||
currLevel = newLevel;
|
||||
w.subWikifyTerm(stack[stack.length-1].children,this.termRegExp);
|
||||
stack[stack.length-1].children.push({type:"element",tag:"br"});
|
||||
//e.push({type:"element",tag:"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)
|
||||
{
|
||||
w.output.push({type:"element",tag:"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;
|
||||
}
|
||||
enclosedTextHelper.call(this,w);
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "typedBlock",
|
||||
match: "^\\$\\$\\$(?:[^ >\\r\\n]*)\\r?\\n",
|
||||
lookaheadRegExp: /^\$\$\$([^ >\r\n]*)\n((?:^[^\n]*\r?\n)+?)(^\f*\$\$\$\r?\n?)/mg,
|
||||
//match: "^\\$\\$\\$(?:[^ >\\r\\n]*)(?: *> *([^ \\r\\n]+))?\\r?\\n",
|
||||
//lookaheadRegExp: /^\$\$\$([^ >\r\n]*)(?: *> *([^ \r\n]+))\n((?:^[^\n]*\n)+?)(^\f*\$\$\$$\n?)/mg,
|
||||
handler: function(w)
|
||||
{
|
||||
this.lookaheadRegExp.lastIndex = w.matchStart;
|
||||
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
|
||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||
// The wikitext parsing infrastructure is horribly unre-entrant
|
||||
var parseType = lookaheadMatch[1],
|
||||
renderType ,//= this.match[2],
|
||||
text = lookaheadMatch[2],
|
||||
oldOutput = w.output,
|
||||
oldSource = w.source,
|
||||
oldNextMatch = w.nextMatch,
|
||||
oldChildren = w.children;
|
||||
// Parse the block according to the specified type
|
||||
var parser = $tw.wiki.parseText(parseType,text.toString(),{defaultType: "text/plain"});
|
||||
|
||||
w.output = oldOutput;
|
||||
w.source = oldSource;
|
||||
w.nextMatch = oldNextMatch;
|
||||
w.children = oldChildren;
|
||||
for (var i=0; i<parser.tree.length; i++) {
|
||||
w.output.push(parser.tree[i]);
|
||||
}
|
||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
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),
|
||||
name;
|
||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||
name = lookaheadMatch[1] || lookaheadMatch[2];
|
||||
if (name) {
|
||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||
insertMacroCall(w,w.output,name,lookaheadMatch[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
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 text = lookaheadMatch[1],
|
||||
link = text;
|
||||
if(lookaheadMatch[3]) {
|
||||
// Pretty bracketted link
|
||||
link = lookaheadMatch[3];
|
||||
}
|
||||
if(isLinkExternal(link)) {
|
||||
w.output.push({
|
||||
type: "element",
|
||||
tag: "a",
|
||||
attributes: {
|
||||
href: {type: "string", value: link},
|
||||
"class": {type: "string", value: "tw-tiddlylink-external"},
|
||||
target: {type: "string", value: "_blank"}
|
||||
},
|
||||
children: [{
|
||||
type: "text", text: text
|
||||
}]
|
||||
});
|
||||
} else {
|
||||
w.output.push({
|
||||
type: "element",
|
||||
tag: "$link",
|
||||
attributes: {
|
||||
to: {type: "string", value: link}
|
||||
},
|
||||
children: [{
|
||||
type: "text", text: text
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "wikiLink",
|
||||
match: textPrimitives.unWikiLink+"?"+textPrimitives.wikiLink,
|
||||
handler: function(w)
|
||||
{
|
||||
if(w.matchText.substr(0,1) == textPrimitives.unWikiLink) {
|
||||
w.outputText(w.output,w.matchStart+1,w.nextMatch);
|
||||
return;
|
||||
}
|
||||
if(w.matchStart > 0) {
|
||||
var preRegExp = new RegExp(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) {
|
||||
w.output.push({
|
||||
type: "element",
|
||||
tag: "$link",
|
||||
attributes: {
|
||||
to: {type: "string", value: w.matchText}
|
||||
},
|
||||
children: [{
|
||||
type: "text",
|
||||
text: w.source.substring(w.matchStart,w.nextMatch)
|
||||
}]
|
||||
});
|
||||
} else {
|
||||
w.outputText(w.output,w.matchStart,w.nextMatch);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "urlLink",
|
||||
match: textPrimitives.urlPattern,
|
||||
handler: function(w)
|
||||
{
|
||||
w.output.push({
|
||||
type: "element",
|
||||
tag: "a",
|
||||
attributes: {
|
||||
href: {type: "string", value: w.matchText},
|
||||
"class": {type: "string", value: "tw-tiddlylink-external"},
|
||||
target: {type: "string", value: "_blank"}
|
||||
},
|
||||
children: [{
|
||||
type: "text", text: w.source.substring(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),
|
||||
imageParams = {},
|
||||
linkParams = {};
|
||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||
if(lookaheadMatch[1]) {
|
||||
imageParams.alignment = "left";
|
||||
} else if(lookaheadMatch[2]) {
|
||||
imageParams.alignment = "right";
|
||||
}
|
||||
if(lookaheadMatch[3]) {
|
||||
imageParams.text = lookaheadMatch[3];
|
||||
}
|
||||
imageParams.src = lookaheadMatch[4];
|
||||
if(lookaheadMatch[5]) {
|
||||
linkParams.target = lookaheadMatch[5];
|
||||
var linkChildren = [];
|
||||
insertMacroCall(w,w.output,"link",linkParams,linkChildren);
|
||||
insertMacroCall(w,linkChildren,"image",imageParams);
|
||||
} else {
|
||||
insertMacroCall(w,w.output,"image",imageParams);
|
||||
}
|
||||
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) {
|
||||
w.output.push({ type:"raw", html: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)
|
||||
{
|
||||
var e,lookaheadRegExp,lookaheadMatch;
|
||||
switch(w.matchText) {
|
||||
case "''":
|
||||
e = {type:"element",tag:"strong",children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/('')/mg);
|
||||
break;
|
||||
case "//":
|
||||
e = {type:"element",tag:"em",children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(\/\/)/mg);
|
||||
break;
|
||||
case "__":
|
||||
e = {type:"element",tag:"u",children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(__)/mg);
|
||||
break;
|
||||
case "^^":
|
||||
e = {type:"element",tag:"sup",children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(\^\^)/mg);
|
||||
break;
|
||||
case "~~":
|
||||
e = {type:"element",tag:"sub",children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(~~)/mg);
|
||||
break;
|
||||
case "--":
|
||||
e = {type:"element",tag:"strike",children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(--)/mg);
|
||||
break;
|
||||
case "`":
|
||||
lookaheadRegExp = /`((?:.|\n)*?)`/mg;
|
||||
lookaheadRegExp.lastIndex = w.matchStart;
|
||||
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||
w.output.push({type:"element",tag:"code",
|
||||
children:[{type: "text",text: lookaheadMatch[1]}]});
|
||||
}
|
||||
break;
|
||||
case "{{{":
|
||||
lookaheadRegExp = /\{\{\{((?:.|\n)*?)\}\}\}/mg;
|
||||
lookaheadRegExp.lastIndex = w.matchStart;
|
||||
lookaheadMatch = lookaheadRegExp.exec(w.source);
|
||||
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
|
||||
w.output.push({type:"element",tag:"code",
|
||||
children:[{type: "text",text: lookaheadMatch[1]}]});
|
||||
w.nextMatch = lookaheadRegExp.lastIndex;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "customFormat",
|
||||
match: "@@|\\{\\{",
|
||||
handler: function(w)
|
||||
{
|
||||
switch(w.matchText) {
|
||||
case "@@":
|
||||
var e = {type:"element",tag:"span",children: []};
|
||||
w.output.push(e);
|
||||
var styles = inlineCssHelper(w);
|
||||
if(styles.length === 0)
|
||||
setAttr(e,"class","marked");
|
||||
else
|
||||
applyCssHelper(e,styles);
|
||||
w.subWikifyTerm(e.children,/(@@)/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 = {type:"element",tag:lookaheadMatch[2] == "\n" ? "div" : "span",
|
||||
attributes: {"class": {type: "string", value:lookaheadMatch[1]}},children: []};
|
||||
w.output.push(e);
|
||||
w.subWikifyTerm(e.children,/(\}\}\})/mg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "mdash",
|
||||
match: "--",
|
||||
handler: function(w)
|
||||
{
|
||||
w.output.push({type: "entity", entity: "—"});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "lineBreak",
|
||||
match: "\\n|<br ?/?>",
|
||||
handler: function(w)
|
||||
{
|
||||
w.output.push({type:"element",tag:"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) {
|
||||
w.output.push({type: "text",text: lookaheadMatch[1]
|
||||
});
|
||||
w.nextMatch = this.lookaheadRegExp.lastIndex;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "htmlEntitiesEncoding",
|
||||
match: "&#?[a-zA-Z0-9]{2,8};",
|
||||
handler: function(w)
|
||||
{
|
||||
w.output.push({type: "entity", entity: w.matchText});
|
||||
}
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
exports.rules = rules;
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user