hedera-web/js/vn/builder.js

169 lines
3.7 KiB
JavaScript
Raw Permalink Normal View History

2022-05-24 21:11:12 +00:00
const VnObject = require('./object');
const Scope = require('./scope');
const kebabToCamel = require('./string-util').kebabToCamel;
2016-09-26 09:28:47 +00:00
2022-06-18 21:04:34 +00:00
const CompilerObject = require('./compiler-object');
const CompilerElement = require('./compiler-element');
const CompilerText = require('./compiler-text');
const regCompilers = [
CompilerText,
CompilerObject,
CompilerElement
];
/**
2015-03-06 23:33:54 +00:00
* Creates a object from a XML specification.
2022-05-24 10:18:44 +00:00
*/
module.exports = new Class({
2022-05-24 21:11:12 +00:00
Extends: VnObject
/**
* Compiles an XML file.
*
2022-05-24 21:11:12 +00:00
* @param {String} path The XML path
* @return {Boolean} %true on success, %false othersise
2022-05-24 10:18:44 +00:00
*/
2022-11-16 01:46:44 +00:00
,compileFile(path) {
2016-09-26 09:28:47 +00:00
this._path = path;
2022-05-24 21:11:12 +00:00
return this.compileDocument(Vn.getXml(path));
}
/**
* Compiles an XML string.
*
* @param {String} xmlString The XML string
* @return {Boolean} %true on success, %false othersise
*/
2022-11-16 01:46:44 +00:00
,compileString(xmlString) {
2022-06-18 21:04:34 +00:00
const parser = new DOMParser();
const doc = parser.parseFromString(xmlString, 'text/xml');
2022-05-24 21:11:12 +00:00
return this.compileDocument(doc);
}
2015-03-06 23:33:54 +00:00
2022-05-24 21:11:12 +00:00
/**
* Compiles a XML document.
*
* @param {Document} doc The DOM document
* @return {Boolean} %true on success, %false othersise
*/
2022-11-16 01:46:44 +00:00
,compileDocument(doc) {
2022-05-24 21:11:12 +00:00
if (!doc)
return false;
2022-06-18 21:04:34 +00:00
this._preCompile();
const docElement = doc.documentElement;
2015-03-06 23:33:54 +00:00
2022-05-24 10:18:44 +00:00
if (docElement.tagName !== 'vn') {
2022-05-24 21:11:12 +00:00
this.showError('The toplevel tag should be named \'vn\'');
this._contexts = null;
2015-03-06 23:33:54 +00:00
return false;
}
2022-06-18 21:04:34 +00:00
const childs = docElement.childNodes;
2015-03-06 23:33:54 +00:00
if (childs)
2022-06-18 21:04:34 +00:00
for (let i = 0; i < childs.length; i++)
2022-05-24 21:11:12 +00:00
this._compile(childs[i]);
2015-03-06 23:33:54 +00:00
2022-05-24 21:11:12 +00:00
this._postCompile();
2015-03-06 23:33:54 +00:00
return true;
}
2015-03-09 08:36:54 +00:00
/**
* Compiles a single DOM node.
*
* @path Node The DOM node
* @return %true on success, %false othersise
2022-05-24 10:18:44 +00:00
*/
2022-11-16 01:46:44 +00:00
,compileNode(node) {
2022-06-18 21:04:34 +00:00
this._preCompile();
2022-05-24 21:11:12 +00:00
this._mainContext = this._compile(node).id;
this._postCompile();
return true;
2015-03-09 08:36:54 +00:00
}
2022-05-24 21:11:12 +00:00
/**
* Called before starting to compile nodes.
*/
2022-11-16 01:46:44 +00:00
,_preCompile() {
2022-05-24 21:11:12 +00:00
this._path = null;
this._tags = {};
this._contexts = [];
2022-06-18 21:04:34 +00:00
this._exprContexts = [];
2022-05-24 21:11:12 +00:00
this._contextMap = {};
this._links = [];
this._mainContext = null;
2022-06-18 21:04:34 +00:00
this._compilers = [];
for (regCompiler of regCompilers)
this._compilers.push(new regCompiler(this));
2022-05-24 21:11:12 +00:00
}
2015-03-09 08:36:54 +00:00
2022-05-24 21:11:12 +00:00
/**
* Called after all nodes have been compiled.
*/
2022-11-16 01:46:44 +00:00
,_postCompile() {
2022-06-18 21:04:34 +00:00
for (const compiler of this._compilers)
compiler.postCompile(this._contextMap);
}
2022-05-24 21:11:12 +00:00
/**
* Compiles a node.
*/
2022-11-16 01:46:44 +00:00
,_compile(node) {
2022-05-24 21:11:12 +00:00
let context = null;
let tagName = null;
const isElement = node.nodeType === Node.ELEMENT_NODE;
if (isElement)
tagName = node.tagName.toLowerCase();
else if (node.nodeType !== Node.TEXT_NODE
|| /^[\n\r\t]*$/.test(node.textContent))
return null;
2022-06-18 21:04:34 +00:00
let i;
const compilers = this._compilers;
for (i = 0; i < compilers.length && context === null; i++)
context = compilers[i].compile(this, node, tagName);
2022-05-24 21:11:12 +00:00
context.id = this._contexts.length;
2022-06-18 21:04:34 +00:00
context.compiler = compilers[i - 1];
2022-05-24 21:11:12 +00:00
if (isElement) {
2022-06-18 21:04:34 +00:00
const nodeId = node.getAttribute('id');
2022-05-28 19:27:36 +00:00
if (nodeId) {
2022-05-24 21:11:12 +00:00
this._contextMap[kebabToCamel(nodeId)] = context.id;
2022-05-28 19:27:36 +00:00
context.nodeId = nodeId;
}
2022-05-24 21:11:12 +00:00
2022-06-18 21:04:34 +00:00
let tags = this._tags[tagName];
2022-05-24 21:11:12 +00:00
if (!tags)
this._tags[tagName] = tags = [];
tags.push(context.id);
}
this._contexts.push(context);
return context;
}
2022-11-16 01:46:44 +00:00
,load(dstDocument, thisArg, parentScope) {
2022-06-18 21:04:34 +00:00
if (!this._contexts) return null;
2022-05-28 19:27:36 +00:00
const doc = dstDocument ? dstDocument : document;
2022-06-18 21:04:34 +00:00
const objects = new Array(this._contexts.length);
const exprValues = new Array(this._exprContexts.length);
return new Scope(this, doc, objects, exprValues, thisArg, parentScope);
2022-05-24 10:18:44 +00:00
}
2022-11-16 01:46:44 +00:00
,showError(error) {
2022-06-18 21:04:34 +00:00
const path = this._path ? this._path : 'Node';
const logArgs = ['Vn.Builder: %s: '+ error, path];
2022-05-24 21:11:12 +00:00
2022-06-18 21:04:34 +00:00
for (let i = 1; i < arguments.length; i++)
2022-05-24 21:11:12 +00:00
logArgs.push(arguments[i]);
console.warn.apply(null, logArgs);
}
});