2012-12-15 11:38:59 +00:00
|
|
|
/*\
|
|
|
|
title: $:/core/modules/utils/parsetree.js
|
|
|
|
type: application/javascript
|
|
|
|
module-type: utils
|
|
|
|
|
|
|
|
Parse tree utility functions.
|
|
|
|
|
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
/*global $tw: false */
|
|
|
|
"use strict";
|
|
|
|
|
2022-09-24 13:07:42 +00:00
|
|
|
/*
|
|
|
|
Add attribute to parse tree node
|
|
|
|
Can be invoked as (node,name,value) or (node,attr)
|
|
|
|
*/
|
2012-12-15 11:38:59 +00:00
|
|
|
exports.addAttributeToParseTreeNode = function(node,name,value) {
|
2022-09-24 13:07:42 +00:00
|
|
|
var attribute = typeof name === "object" ? name : {name: name, type: "string", value: value};
|
|
|
|
name = attribute.name;
|
2014-05-14 07:51:08 +00:00
|
|
|
node.attributes = node.attributes || {};
|
2022-09-24 13:07:42 +00:00
|
|
|
node.orderedAttributes = node.orderedAttributes || [];
|
2022-04-06 07:33:38 +00:00
|
|
|
node.attributes[name] = attribute;
|
2022-09-24 13:07:42 +00:00
|
|
|
var foundIndex = -1;
|
|
|
|
$tw.utils.each(node.orderedAttributes,function(attr,index) {
|
|
|
|
if(attr.name === name) {
|
|
|
|
foundIndex = index;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if(foundIndex === -1) {
|
2022-04-06 07:33:38 +00:00
|
|
|
node.orderedAttributes.push(attribute);
|
2022-09-24 13:07:42 +00:00
|
|
|
} else {
|
|
|
|
node.orderedAttributes[foundIndex] = attribute;
|
2022-04-06 07:33:38 +00:00
|
|
|
}
|
2012-12-15 11:38:59 +00:00
|
|
|
};
|
|
|
|
|
2022-04-26 13:02:31 +00:00
|
|
|
exports.getOrderedAttributesFromParseTreeNode = function(node) {
|
|
|
|
if(node.orderedAttributes) {
|
|
|
|
return node.orderedAttributes;
|
|
|
|
} else {
|
|
|
|
var attributes = [];
|
|
|
|
$tw.utils.each(node.attributes,function(attribute) {
|
|
|
|
attributes.push(attribute);
|
|
|
|
});
|
|
|
|
return attributes.sort(function(a,b) {
|
|
|
|
return a.name < b.name ? -1 : (a.name > b.name ? 1 : 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-01-03 10:39:55 +00:00
|
|
|
exports.getAttributeValueFromParseTreeNode = function(node,name,defaultValue) {
|
2014-05-14 07:51:08 +00:00
|
|
|
if(node.attributes && node.attributes[name] && node.attributes[name].value !== undefined) {
|
2014-01-03 10:39:55 +00:00
|
|
|
return node.attributes[name].value;
|
|
|
|
}
|
|
|
|
return defaultValue;
|
|
|
|
};
|
|
|
|
|
2012-12-15 11:38:59 +00:00
|
|
|
exports.addClassToParseTreeNode = function(node,classString) {
|
2022-04-06 07:33:38 +00:00
|
|
|
var classes = [],
|
|
|
|
attribute;
|
2014-05-14 07:51:08 +00:00
|
|
|
node.attributes = node.attributes || {};
|
2022-04-06 07:33:38 +00:00
|
|
|
attribute = node.attributes["class"];
|
|
|
|
if(!attribute) {
|
|
|
|
// If the class attribute does not exist, we must create it first.
|
|
|
|
attribute = {name: "class", type: "string", value: ""};
|
|
|
|
node.attributes["class"] = attribute;
|
2022-10-16 16:27:46 +00:00
|
|
|
node.orderedAttributes = node.orderedAttributes || [];
|
|
|
|
node.orderedAttributes.push(attribute);
|
2022-04-06 07:33:38 +00:00
|
|
|
}
|
|
|
|
if(attribute.type === "string") {
|
|
|
|
if(attribute.value !== "") {
|
|
|
|
classes = attribute.value.split(" ");
|
2012-12-15 11:38:59 +00:00
|
|
|
}
|
2014-05-14 07:51:08 +00:00
|
|
|
if(classString !== "") {
|
|
|
|
$tw.utils.pushTop(classes,classString.split(" "));
|
|
|
|
}
|
2022-04-06 07:33:38 +00:00
|
|
|
attribute.value = classes.join(" ");
|
2012-12-15 11:38:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-12-20 09:21:58 +00:00
|
|
|
exports.addStyleToParseTreeNode = function(node,name,value) {
|
2022-04-06 07:33:38 +00:00
|
|
|
var attribute;
|
|
|
|
node.attributes = node.attributes || {};
|
|
|
|
attribute = node.attributes.style;
|
|
|
|
if(!attribute) {
|
|
|
|
attribute = {name: "style", type: "string", value: ""};
|
|
|
|
node.attributes.style = attribute;
|
2022-10-16 16:27:46 +00:00
|
|
|
node.orderedAttributes = node.orderedAttributes || [];
|
|
|
|
node.orderedAttributes.push(attribute);
|
2022-04-06 07:33:38 +00:00
|
|
|
}
|
|
|
|
if(attribute.type === "string") {
|
|
|
|
attribute.value += name + ":" + value + ";";
|
|
|
|
}
|
2012-12-20 09:21:58 +00:00
|
|
|
};
|
|
|
|
|
2012-12-30 17:23:44 +00:00
|
|
|
exports.findParseTreeNode = function(nodeArray,search) {
|
|
|
|
for(var t=0; t<nodeArray.length; t++) {
|
|
|
|
if(nodeArray[t].type === search.type && nodeArray[t].tag === search.tag) {
|
|
|
|
return nodeArray[t];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
};
|
|
|
|
|
2015-08-01 12:14:32 +00:00
|
|
|
/*
|
|
|
|
Helper to get the text of a parse tree node or array of nodes
|
|
|
|
*/
|
2024-06-12 17:29:22 +00:00
|
|
|
exports.getParseTreeText = function getParseTreeText(tree) {
|
2015-08-01 12:14:32 +00:00
|
|
|
var output = [];
|
|
|
|
if($tw.utils.isArray(tree)) {
|
|
|
|
$tw.utils.each(tree,function(node) {
|
|
|
|
output.push(getParseTreeText(node));
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if(tree.type === "text") {
|
|
|
|
output.push(tree.text);
|
|
|
|
}
|
|
|
|
if(tree.children) {
|
|
|
|
return getParseTreeText(tree.children);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output.join("");
|
|
|
|
};
|
|
|
|
|
2024-06-12 17:31:13 +00:00
|
|
|
/*
|
2024-07-29 16:43:55 +00:00
|
|
|
Utility to get the (similarly but not 1:1 equal) original wikitext of a parse tree node or array of nodes.
|
|
|
|
Based on `node.rule` metadata added in `wikiparser.js`.
|
2024-06-12 17:31:13 +00:00
|
|
|
*/
|
2024-07-29 16:43:55 +00:00
|
|
|
exports.serializeParseTree = function serializeParseTree(tree,tiddlerType) {
|
2024-06-12 17:31:13 +00:00
|
|
|
var output = [];
|
|
|
|
if($tw.utils.isArray(tree)) {
|
|
|
|
$tw.utils.each(tree,function(node) {
|
2024-07-29 16:56:28 +00:00
|
|
|
output.push(serializeParseTree(node,tiddlerType));
|
2024-06-12 17:31:13 +00:00
|
|
|
});
|
2024-08-03 16:48:29 +00:00
|
|
|
} else if(tree) {
|
2024-08-02 17:19:05 +00:00
|
|
|
if(tree.type === "text" && !tree.rule) {
|
2024-06-12 17:31:13 +00:00
|
|
|
output.push(tree.text);
|
|
|
|
} else {
|
|
|
|
var Parser = $tw.wiki.getParser(tiddlerType);
|
2024-06-12 17:34:18 +00:00
|
|
|
var Rule = Parser.prototype.blockRuleClasses[tree.rule] ||
|
|
|
|
Parser.prototype.inlineRuleClasses[tree.rule] ||
|
|
|
|
Parser.prototype.pragmaRuleClasses[tree.rule];
|
|
|
|
if(Rule && Rule.prototype.serialize) {
|
2024-07-29 16:43:55 +00:00
|
|
|
output.push(Rule.prototype.serialize(tree,serializeParseTree));
|
|
|
|
} else if(tree.rule === "parseBlock") {
|
|
|
|
output.push(serializeParseTree(tree.children,tiddlerType),"\n\n");
|
2024-08-02 17:19:05 +00:00
|
|
|
} else {
|
|
|
|
// when no rule is found, just serialize the children
|
|
|
|
output.push(serializeParseTree(tree.children,tiddlerType));
|
2024-06-12 17:31:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return output.join("");
|
|
|
|
};
|
|
|
|
|
2012-12-15 11:38:59 +00:00
|
|
|
})();
|