1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-06-13 09:09:25 +00:00
TiddlyWiki5/core/modules/parsers/old/wikitextparser/rules/table.js

160 lines
4.6 KiB
JavaScript

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