1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-23 18:17:20 +00:00

Added more parse rules

This commit is contained in:
Jeremy Ruston 2012-12-15 11:39:58 +00:00
parent 817e6f5471
commit e3462e5606
8 changed files with 530 additions and 0 deletions

View File

@ -0,0 +1,49 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/block/classblock.js
type: application/javascript
module-type: wikiblockrule
Wiki text block rule for assigning classes to paragraphs and other blocks. For example:
{{{
{{myClass{
This paragraph will have the CSS class `myClass`.
* The `<ul>` around this list will also have the class `myClass`
* List item 2
}}}
}}}
Note that the opening and closing braces both must be immediately followed by a newline.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "classblock";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\{\{([^\{\r\n]+)\{\r?\n/mg;
};
exports.parse = function() {
var reEndString = "(\\}\\}\\}$(?:\\r?\\n)?)";
// Get the class
var classString = this.match[1];
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
// Parse the body
var tree = this.parser.parseBlocks(reEndString);
for(var t=0; t<tree.length; t++) {
$tw.utils.addClassToParseTreeNode(tree[t],classString);
}
return tree;
};
})();

View File

@ -0,0 +1,58 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/block/codeblock.js
type: application/javascript
module-type: wikiblockrule
Wiki text rule for code blocks. For example:
{{{
{{{
This text will not be //wikified//
}}}
}}}
Note that the opening curly braces and the closing curly braces must each be on a line of their own, and not be preceded or followed by white space.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "codeblock";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\{\{\{\r?\n/mg;
};
exports.parse = function(match,isBlock) {
var reEnd = /(\r?\n\}\}\}$)/mg;
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
// Look for the end of the block
reEnd.lastIndex = this.parser.pos;
var match = reEnd.exec(this.parser.source),
text;
// Process the block
if(match) {
text = this.parser.source.substring(this.parser.pos,match.index);
this.parser.pos = match.index + match[0].length;
} else {
text = this.parser.source.substr(this.parser.pos);
this.parser.pos = this.parser.sourceLength;
}
// Return the pre element
return [{
type: "element",
tag: "pre",
children: [{
type: "text",
text: text
}]
}];
};
})();

View File

@ -0,0 +1,161 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/block/table.js
type: application/javascript
module-type: wikiblockrule
Wiki text block rule for tables.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "table";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\|(?:[^\n]*)\|(?:[fhck]?)\r?\n/mg;
};
var processRow = function(prevColumns) {
var cellRegExp = /(?:\|([^\n\|]*)\|)|(\|[fhck]?\r?\n)/mg,
cellTermRegExp = /((?:\x20*)\|)/mg,
tree = [],
col = 0,
colSpanCount = 1,
prevCell;
// Match a single cell
cellRegExp.lastIndex = this.parser.pos;
var cellMatch = cellRegExp.exec(this.parser.source);
while(cellMatch && cellMatch.index === this.parser.pos) {
if(cellMatch[1] === "~") {
// Rowspan
var last = prevColumns[col];
if(last) {
last.rowSpanCount++;
$tw.utils.addAttributeToParseTreeNode(last.element,"rowspan",last.rowSpanCount);
$tw.utils.addAttributeToParseTreeNode(last.element,"valign","center");
if(colSpanCount > 1) {
$tw.utils.addAttributeToParseTreeNode(last.element,"colspan",colSpanCount);
colSpanCount = 1;
}
}
// Move to just before the `|` terminating the cell
this.parser.pos = cellRegExp.lastIndex - 1;
} else if(cellMatch[1] === ">") {
// Colspan
colSpanCount++;
// Move to just before the `|` terminating the cell
this.parser.pos = cellRegExp.lastIndex - 1;
} else if(cellMatch[2]) {
// End of row
if(prevCell && colSpanCount > 1) {
$tw.utils.addAttributeToParseTreeNode(prevCell,"colspan",colSpanCount);
}
this.parser.pos = cellRegExp.lastIndex - 1;
break;
} else {
// For ordinary cells, step beyond the opening `|`
this.parser.pos++;
// Look for a space at the start of the cell
var spaceLeft = false,
chr = this.parser.source.substr(this.parser.pos,1);
while(chr === " ") {
spaceLeft = true;
this.parser.pos++;
chr = this.parser.source.substr(this.parser.pos,1);
}
// Check whether this is a heading cell
var cell;
if(chr === "!") {
this.parser.pos++;
cell = {type: "element", tag: "th", children: []};
} else {
cell = {type: "element", tag: "td", children: []};
}
tree.push(cell);
// Record information about this cell
prevCell = cell;
prevColumns[col] = {rowSpanCount:1,element:cell};
// Check for a colspan
if(colSpanCount > 1) {
$tw.utils.addAttributeToParseTreeNode(cell,"colspan",colSpanCount);
colSpanCount = 1;
}
// Parse the cell
cell.children = this.parser.parseRun(cellTermRegExp,{eatTerminator: true});
// Set the alignment for the cell
if(cellMatch[1].substr(cellMatch[1].length-1,1) === " ") { // spaceRight
$tw.utils.addAttributeToParseTreeNode(cell,"align",spaceLeft ? "center" : "left");
} else if(spaceLeft) {
$tw.utils.addAttributeToParseTreeNode(cell,"align","right");
}
// Move back to the closing `|`
this.parser.pos--;
}
col++;
cellRegExp.lastIndex = this.parser.pos;
cellMatch = cellRegExp.exec(this.parser.source);
}
return tree;
};
exports.parse = function() {
var rowContainerTypes = {"c":"caption", "h":"thead", "":"tbody", "f":"tfoot"},
table = {type: "element", tag: "table", children: []},
rowRegExp = /^\|([^\n]*)\|([fhck]?)\r?\n/mg,
rowTermRegExp = /(\|(?:[fhck]?)\r?\n)/mg,
prevColumns = [],
currRowType,
rowContainer,
rowCount = 0;
// Match the row
rowRegExp.lastIndex = this.parser.pos;
var rowMatch = rowRegExp.exec(this.parser.source);
while(rowMatch && rowMatch.index === this.parser.pos) {
var rowType = rowMatch[2];
// Check if it is a class assignment
if(rowType === "k") {
$tw.utils.addClassToParseTreeNode(table,rowMatch[1]);
this.parser.pos = rowMatch.index + rowMatch[0].length;
} else {
// Otherwise, create a new row if this one is of a different type
if(rowType != currRowType) {
rowContainer = {type: "element", tag: rowContainerTypes[rowType], children: []};
table.children.push(rowContainer);
currRowType = rowType;
}
// Is this a caption row?
if(currRowType === "c") {
// If so, move past the opening `|` of the row
this.parser.pos++;
// 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
}
// Set the alignment - TODO: figure out why TW did this
// rowContainer.attributes.align = rowCount === 0 ? "top" : "bottom";
// Parse the caption
rowContainer.children = this.parser.parseRun(rowTermRegExp,{eatTerminator: true});
} else {
// Create the row
var theRow = {type: "element", tag: "tr", children: []};
$tw.utils.addClassToParseTreeNode(theRow,rowCount%2 ? "oddRow" : "evenRow");
rowContainer.children.push(theRow);
// Process the row
theRow.children = processRow.call(this,prevColumns);
this.parser.pos = rowMatch.index + rowMatch[0].length;
// Increment the row count
rowCount++;
}
}
rowMatch = rowRegExp.exec(this.parser.source);
}
return [table];
};
})();

View File

@ -0,0 +1,51 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/run/classrun.js
type: application/javascript
module-type: wikirunrule
Wiki text run rule for assigning classes to runs of text. For example:
{{{
{{myClass{This text will have the CSS class `myClass`.
* This will not be recognised as a list
List item 2}}}
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "classrun";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /\{\{([^\{\r\n]+)\{/mg;
};
exports.parse = function() {
var reEnd = /(\}\}\})/g;
// Get the class
var classString = this.match[1];
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
// Parse the run up to the terminator
var tree = this.parser.parseRun(reEnd,{eatTerminator: true});
// Return the classed span
return [{
type: "element",
tag: "span",
attributes: {
"class": {type: "string", value: classString}
},
children: tree
}];
};
})();

View File

@ -0,0 +1,58 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/run/coderun.js
type: application/javascript
module-type: wikirunrule
Wiki text run rule for code runs. For example:
{{{
This is a {{{code run}}} and `so is this`.
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "coderun";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /(\{\{\{)|(`)/mg;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
var reEnd;
if(this.match[0] === "{{{") {
reEnd = /(\}\}\})/mg;
} else {
reEnd = /(`)/mg;
}
// Look for the end marker
reEnd.lastIndex = this.parser.pos;
var match = reEnd.exec(this.parser.source),
text;
// Process the text
if(match) {
text = this.parser.source.substring(this.parser.pos,match.index);
this.parser.pos = match.index + match[0].length;
} else {
text = this.parser.source.substr(this.parser.pos);
this.parser.pos = this.parser.sourceLength;
}
return [{
type: "element",
tag: "code",
children: [{
type: "text",
text: text
}]
}];
};
})();

View File

@ -0,0 +1,34 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/run/comment.js
type: application/javascript
module-type: wikirunrule
Wiki text run rule for HTML comments. For example:
{{{
<!-- This is a comment -->
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "comment";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match - HTML comment regexp by Stephen Ostermiller, http://ostermiller.org/findhtmlcomment.html
this.matchRegExp = /\<![ \r\n\t]*(?:--(?:[^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/mg;
};
exports.parse = function(match,isBlock) {
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
// Don't return any elements
return [];
};
})();

View File

@ -0,0 +1,41 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/run/dash.js
type: application/javascript
module-type: wikirunrule
Wiki text run rule for dashes. For example:
{{{
This is an en-dash: --
This is an em-dash: ---
}}}
Dashes must be followed by whitespace in order to be distinguished from strikethrough notation (`--strikethrough--`).
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "dash";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /-{2,3}(?=\s)/mg;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
var dash = this.match[0].length === 2 ? "&ndash;" : "&mdash;";
return [{
type: "entity",
entity: dash
}];
};
})();

View File

@ -0,0 +1,78 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/run/emphasis.js
type: application/javascript
module-type: wikirunrule
Wiki text run rule for emphasis. For example:
{{{
This is ''bold'' text
This is //italic// text
This is __underlined__ text
This is ^^superscript^^ text
This is ,,subscript,, text
This is ~~strikethrough~~ text
}}}
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "emphasis";
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /''|\/\/|__|\^\^|,,|~~/mg;
};
exports.parse = function() {
// Move past the match
this.parser.pos = this.matchRegExp.lastIndex;
// Figure out which element and closing regexp to use
var tag,reEnd;
switch(this.match[0]) {
case "''": // Bold
tag = "strong";
reEnd = /''/mg;
break;
case "//": // Italics
tag = "em";
reEnd = /\/\//mg;
break;
case "__": // Underline
tag = "u";
reEnd = /__/mg;
break;
case "^^": // Superscript
tag = "sup";
reEnd = /\^\^/mg;
break;
case ",,": // Subscript
tag = "sub";
reEnd = /,,/mg;
break;
case "~~": // Strikethrough
tag = "strike";
reEnd = /~~/mg;
break;
}
// Parse the run including the terminator
var tree = this.parser.parseRun(reEnd,{eatTerminator: true});
// Return the classed span
return [{
type: "element",
tag: tag,
children: tree
}];
};
})();