mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Refactored out core taglibs into separate modules and cleaned up code
This commit is contained in:
parent
d857d4b6a2
commit
64be29ca79
16
README.md
16
README.md
@ -5,8 +5,10 @@ Raptor Templates is an extensible, streaming, asynchronous, [high performance](h
|
|||||||
|
|
||||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||||
|
|
||||||
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
|
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
|
||||||
|
|
||||||
|
- [Design Philosophy](#design-philosophy)
|
||||||
- [Sample](#sample)
|
- [Sample](#sample)
|
||||||
- [Installation](#installation)
|
- [Installation](#installation)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
@ -63,6 +65,20 @@ Raptor Templates is an extensible, streaming, asynchronous, [high performance](h
|
|||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
|
|
||||||
|
# Design Philosophy
|
||||||
|
|
||||||
|
- __Readable:__ Templates should be as close to the output HTML as possible to keep templates readable. Cryptic syntax and symbols should be avoided.
|
||||||
|
- __Simple:__ The number of new concepts should be minimized to reduce the learning curve and complexity.
|
||||||
|
- __Extensible:__ The template engine should be easily extensible at both compile time and runtime.
|
||||||
|
- __High Performance:__ Runtime and compiled output should be optimized for low CPU and memory usage and have a small footprint. All expressions should be native JavaScript to avoid runtime interpretation.
|
||||||
|
- __Asynchronous and Streaming Output:__ It should be possible to render HTML out-of-order, but the output HTML should be streamed out in the correct order. This minimizes idle time and reduces the time to first byte.
|
||||||
|
- __Intuitive:__ The templating engine should introduce as few surprises as possible.
|
||||||
|
- __Browser and Server Compatibility:__ Templates should compile down to JavaScript that can be executed on both the server and the client.
|
||||||
|
- __Debuggable:__ Compiled JavaScript should be debuggable and readable.
|
||||||
|
- __Compile-Time Checks:__ Syntax, custom tags and custom attributes should be validated at compile-time.
|
||||||
|
- __Tools Support:__ Tools should be enabled to offer auto-completion and validation for improved productivity and safety.
|
||||||
|
- __Modular:__ Runtime and compiled templates should be based on CommonJS modules for improved dependency management. Template dependencies (such as custom tags) should resolved based on a template's file system path instead of relying on a shared registry.
|
||||||
|
|
||||||
# Sample
|
# Sample
|
||||||
|
|
||||||
A basic template with text replacement, looping and conditionals is shown below:
|
A basic template with text replacement, looping and conditionals is shown below:
|
||||||
|
|||||||
@ -20,7 +20,6 @@ var objects = require('raptor-objects');
|
|||||||
var escapeXmlAttr = require('raptor-xml/util').escapeXmlAttr;
|
var escapeXmlAttr = require('raptor-xml/util').escapeXmlAttr;
|
||||||
var XML_URI = 'http://www.w3.org/XML/1998/namespace';
|
var XML_URI = 'http://www.w3.org/XML/1998/namespace';
|
||||||
var XML_URI_ALT = 'http://www.w3.org/XML/1998/namespace';
|
var XML_URI_ALT = 'http://www.w3.org/XML/1998/namespace';
|
||||||
var ExpressionParser = require('./ExpressionParser');
|
|
||||||
var forEachEntry = require('raptor-util').forEachEntry;
|
var forEachEntry = require('raptor-util').forEachEntry;
|
||||||
|
|
||||||
function ElementNode(localName, namespace, prefix) {
|
function ElementNode(localName, namespace, prefix) {
|
||||||
@ -209,7 +208,7 @@ ElementNode.prototype = {
|
|||||||
var attrParts = [];
|
var attrParts = [];
|
||||||
var hasExpression = false;
|
var hasExpression = false;
|
||||||
var invalidAttr = false;
|
var invalidAttr = false;
|
||||||
ExpressionParser.parse(attr.value, {
|
template.parseExpression(attr.value, {
|
||||||
text: function (text, escapeXml) {
|
text: function (text, escapeXml) {
|
||||||
attrParts.push({
|
attrParts.push({
|
||||||
text: text,
|
text: text,
|
||||||
@ -228,6 +227,7 @@ ElementNode.prototype = {
|
|||||||
this.addError('Invalid expression found in attribute "' + name + '". ' + message);
|
this.addError('Invalid expression found in attribute "' + name + '". ' + message);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
if (invalidAttr) {
|
if (invalidAttr) {
|
||||||
template.text(name + '="' + escapeXmlAttr(attr.value) + '"');
|
template.text(name + '="' + escapeXmlAttr(attr.value) + '"');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
module.exports = require('raptor-util').makeEnum([
|
module.exports = {
|
||||||
'Element',
|
'ELEMENT': 'ELEMENT',
|
||||||
'Attribute'
|
'ATTRIBUTE': 'ATTRIBUTE'
|
||||||
]);
|
};
|
||||||
@ -17,9 +17,9 @@
|
|||||||
var createError = require('raptor-util').createError;
|
var createError = require('raptor-util').createError;
|
||||||
var forEachEntry = require('raptor-util').forEachEntry;
|
var forEachEntry = require('raptor-util').forEachEntry;
|
||||||
var extend = require('raptor-util').extend;
|
var extend = require('raptor-util').extend;
|
||||||
|
|
||||||
var isArray = Array.isArray;
|
var isArray = Array.isArray;
|
||||||
var isEmpty = require('raptor-objects').isEmpty;
|
var EscapeXmlContext = require('./EscapeXmlContext');
|
||||||
|
|
||||||
function Node(nodeType) {
|
function Node(nodeType) {
|
||||||
if (!this.nodeType) {
|
if (!this.nodeType) {
|
||||||
this._isRoot = false;
|
this._isRoot = false;
|
||||||
@ -39,7 +39,13 @@ function Node(nodeType) {
|
|||||||
this.properties = {};
|
this.properties = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node.isNode = function(node) {
|
||||||
|
return node.__NODE === true;
|
||||||
|
};
|
||||||
|
|
||||||
Node.prototype = {
|
Node.prototype = {
|
||||||
|
|
||||||
setRoot: function (isRoot) {
|
setRoot: function (isRoot) {
|
||||||
this._isRoot = isRoot;
|
this._isRoot = isRoot;
|
||||||
},
|
},
|
||||||
@ -343,6 +349,7 @@ Node.prototype = {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
__NODE: true,
|
||||||
isTextNode: function () {
|
isTextNode: function () {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
@ -436,7 +443,7 @@ Node.prototype = {
|
|||||||
childNode.setEscapeXmlBodyText(this.isEscapeXmlBodyText() !== false);
|
childNode.setEscapeXmlBodyText(this.isEscapeXmlBodyText() !== false);
|
||||||
}
|
}
|
||||||
if (childNode.getEscapeXmlContext() == null) {
|
if (childNode.getEscapeXmlContext() == null) {
|
||||||
childNode.setEscapeXmlContext(this.getEscapeXmlContext() || require('./EscapeXmlContext').Element);
|
childNode.setEscapeXmlContext(this.getEscapeXmlContext() || require('./EscapeXmlContext').ELEMENT);
|
||||||
}
|
}
|
||||||
childNode.generateCode(template);
|
childNode.generateCode(template);
|
||||||
}, this);
|
}, this);
|
||||||
@ -489,6 +496,10 @@ Node.prototype = {
|
|||||||
return this.escapeXmlBodyText;
|
return this.escapeXmlBodyText;
|
||||||
},
|
},
|
||||||
setEscapeXmlContext: function (escapeXmlContext) {
|
setEscapeXmlContext: function (escapeXmlContext) {
|
||||||
|
if (typeof escapeXmlContext === 'string') {
|
||||||
|
escapeXmlContext = EscapeXmlContext[escapeXmlContext.toUpperCase()];
|
||||||
|
}
|
||||||
|
|
||||||
this.escapeXmlContext = escapeXmlContext;
|
this.escapeXmlContext = escapeXmlContext;
|
||||||
},
|
},
|
||||||
getEscapeXmlContext: function () {
|
getEscapeXmlContext: function () {
|
||||||
|
|||||||
@ -1,257 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
var forEachEntry = require('raptor-util').forEachEntry;
|
|
||||||
var ok = require('assert').ok;
|
|
||||||
var makeClass = require('raptor-util').makeClass;
|
|
||||||
|
|
||||||
function Taglib(id) {
|
|
||||||
ok(id, '"id" expected');
|
|
||||||
this.id = id;
|
|
||||||
this.dirname = null;
|
|
||||||
this.tags = {};
|
|
||||||
this.textTransformers = [];
|
|
||||||
this.attributes = {};
|
|
||||||
this.patternAttributes = [];
|
|
||||||
this.inputFilesLookup = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Taglib.prototype = {
|
|
||||||
|
|
||||||
addInputFile: function(path) {
|
|
||||||
this.inputFilesLookup[path] = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
getInputFiles: function() {
|
|
||||||
return Object.keys(this.inputFilesLookup);
|
|
||||||
},
|
|
||||||
|
|
||||||
addAttribute: function (attribute) {
|
|
||||||
if (attribute.pattern) {
|
|
||||||
this.patternAttributes.push(attribute);
|
|
||||||
} else if (attribute.name) {
|
|
||||||
this.attributes[attribute.name] = attribute;
|
|
||||||
} else {
|
|
||||||
throw new Error('Invalid attribute: ' + require('util').inspect(attribute));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getAttribute: function (name) {
|
|
||||||
var attribute = this.attributes[name];
|
|
||||||
if (!attribute) {
|
|
||||||
for (var i = 0, len = this.patternAttributes.length; i < len; i++) {
|
|
||||||
var patternAttribute = this.patternAttributes[i];
|
|
||||||
if (patternAttribute.pattern.test(name)) {
|
|
||||||
attribute = patternAttribute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return attribute;
|
|
||||||
},
|
|
||||||
addTag: function (tag) {
|
|
||||||
ok(arguments.length === 1, 'Invalid args');
|
|
||||||
ok(tag.name, '"tag.name" is required');
|
|
||||||
this.tags[tag.name] = tag;
|
|
||||||
tag.taglibId = this.id;
|
|
||||||
},
|
|
||||||
addTextTransformer: function (transformer) {
|
|
||||||
this.textTransformers.push(transformer);
|
|
||||||
},
|
|
||||||
forEachTag: function (callback, thisObj) {
|
|
||||||
forEachEntry(this.tags, function (key, tag) {
|
|
||||||
callback.call(thisObj, tag);
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Taglib.Tag = makeClass({
|
|
||||||
$init: function(taglib) {
|
|
||||||
this.taglibId = taglib ? taglib.id : null;
|
|
||||||
this.renderer = null;
|
|
||||||
this.nodeClass = null;
|
|
||||||
this.template = null;
|
|
||||||
this.attributes = {};
|
|
||||||
this.transformers = {};
|
|
||||||
this.nestedVariables = {};
|
|
||||||
this.importedVariables = {};
|
|
||||||
this.patternAttributes = [];
|
|
||||||
},
|
|
||||||
inheritFrom: function (superTag) {
|
|
||||||
var subTag = this;
|
|
||||||
/*
|
|
||||||
* Have the sub tag inherit any properties from the super tag that are not in the sub tag
|
|
||||||
*/
|
|
||||||
forEachEntry(superTag, function (k, v) {
|
|
||||||
if (subTag[k] === undefined) {
|
|
||||||
subTag[k] = v;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function inheritProps(sub, sup) {
|
|
||||||
forEachEntry(sup, function (k, v) {
|
|
||||||
if (!sub[k]) {
|
|
||||||
sub[k] = v;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
[
|
|
||||||
'attributes',
|
|
||||||
'transformers',
|
|
||||||
'nestedVariables',
|
|
||||||
'importedVariables'
|
|
||||||
].forEach(function (propName) {
|
|
||||||
inheritProps(subTag[propName], superTag[propName]);
|
|
||||||
});
|
|
||||||
subTag.patternAttributes = superTag.patternAttributes.concat(subTag.patternAttributes);
|
|
||||||
},
|
|
||||||
forEachVariable: function (callback, thisObj) {
|
|
||||||
forEachEntry(this.nestedVariables, function (key, variable) {
|
|
||||||
callback.call(thisObj, variable);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
forEachImportedVariable: function (callback, thisObj) {
|
|
||||||
forEachEntry(this.importedVariables, function (key, importedVariable) {
|
|
||||||
callback.call(thisObj, importedVariable);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
forEachTransformer: function (callback, thisObj) {
|
|
||||||
forEachEntry(this.transformers, function (key, transformer) {
|
|
||||||
callback.call(thisObj, transformer);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
hasTransformers: function () {
|
|
||||||
/*jshint unused:false */
|
|
||||||
for (var k in this.transformers) {
|
|
||||||
if (this.transformers.hasOwnProperty(k)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
addAttribute: function (attr) {
|
|
||||||
if (attr.pattern) {
|
|
||||||
this.patternAttributes.push(attr);
|
|
||||||
} else {
|
|
||||||
if (attr.name === '*') {
|
|
||||||
attr.dynamicAttribute = true;
|
|
||||||
|
|
||||||
if (attr.targetProperty === null || attr.targetProperty === '') {
|
|
||||||
attr.targetProperty = null;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (!attr.targetProperty) {
|
|
||||||
attr.targetProperty = '*';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.attributes[attr.name] = attr;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toString: function () {
|
|
||||||
return '[Tag: <' + this.name + '@' + this.taglibId + '>]';
|
|
||||||
},
|
|
||||||
forEachAttribute: function (callback, thisObj) {
|
|
||||||
for (var attrName in this.attributes) {
|
|
||||||
if (this.attributes.hasOwnProperty(attrName)) {
|
|
||||||
callback.call(thisObj, this.attributes[attrName]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
addNestedVariable: function (nestedVariable) {
|
|
||||||
var key = nestedVariable.nameFromAttribute ? 'attr:' + nestedVariable.nameFromAttribute : nestedVariable.name;
|
|
||||||
this.nestedVariables[key] = nestedVariable;
|
|
||||||
},
|
|
||||||
addImportedVariable: function (importedVariable) {
|
|
||||||
var key = importedVariable.targetProperty;
|
|
||||||
this.importedVariables[key] = importedVariable;
|
|
||||||
},
|
|
||||||
addTransformer: function (transformer) {
|
|
||||||
var key = transformer.path;
|
|
||||||
transformer.taglibId = this.taglibId;
|
|
||||||
this.transformers[key] = transformer;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Taglib.Attribute = makeClass({
|
|
||||||
$init: function(name) {
|
|
||||||
this.name = name;
|
|
||||||
this.type = null;
|
|
||||||
this.required = false;
|
|
||||||
this.type = 'string';
|
|
||||||
this.allowExpressions = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Taglib.Property = makeClass({
|
|
||||||
$init: function() {
|
|
||||||
this.name = null;
|
|
||||||
this.type = 'string';
|
|
||||||
this.value = undefined;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Taglib.NestedVariable = makeClass({
|
|
||||||
$init: function() {
|
|
||||||
this.name = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Taglib.ImportedVariable = makeClass({
|
|
||||||
$init: function() {
|
|
||||||
this.targetProperty = null;
|
|
||||||
this.expression = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var nextTransformerId = 0;
|
|
||||||
|
|
||||||
Taglib.Transformer = makeClass({
|
|
||||||
$init: function() {
|
|
||||||
this.id = nextTransformerId++;
|
|
||||||
this.name = null;
|
|
||||||
this.tag = null;
|
|
||||||
this.path = null;
|
|
||||||
this.priority = null;
|
|
||||||
this.instance = null;
|
|
||||||
this.properties = {};
|
|
||||||
},
|
|
||||||
|
|
||||||
getInstance: function () {
|
|
||||||
if (!this.path) {
|
|
||||||
throw new Error('Transformer class not defined for tag transformer (tag=' + this.tag + ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.instance) {
|
|
||||||
var Clazz = require(this.path);
|
|
||||||
if (Clazz.process) {
|
|
||||||
return Clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Clazz !== 'function') {
|
|
||||||
console.error('Invalid transformer: ', Clazz);
|
|
||||||
throw new Error('Invalid transformer at path "' + this.path + '": ' + Clazz);
|
|
||||||
}
|
|
||||||
this.instance = new Clazz();
|
|
||||||
this.instance.id = this.id;
|
|
||||||
}
|
|
||||||
return this.instance;
|
|
||||||
},
|
|
||||||
toString: function () {
|
|
||||||
return '[Taglib.Transformer: ' + this.path + ']';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = Taglib;
|
|
||||||
@ -1,236 +0,0 @@
|
|||||||
var ok = require('assert').ok;
|
|
||||||
var createError = require('raptor-util').createError;
|
|
||||||
|
|
||||||
function transformerComparator(a, b) {
|
|
||||||
a = a.priority;
|
|
||||||
b = b.priority;
|
|
||||||
|
|
||||||
if (a == null) {
|
|
||||||
a = Number.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b == null) {
|
|
||||||
b = Number.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a - b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function merge(target, source) {
|
|
||||||
for (var k in source) {
|
|
||||||
if (source.hasOwnProperty(k)) {
|
|
||||||
if (target[k] && typeof target[k] === 'object' &&
|
|
||||||
source[k] && typeof source[k] === 'object') {
|
|
||||||
|
|
||||||
if (Array.isArray(target[k]) || Array.isArray(source[k])) {
|
|
||||||
|
|
||||||
var targetArray = target[k];
|
|
||||||
var sourceArray = source[k];
|
|
||||||
|
|
||||||
|
|
||||||
if (!Array.isArray(targetArray)) {
|
|
||||||
targetArray = [targetArray];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(sourceArray)) {
|
|
||||||
sourceArray = [sourceArray];
|
|
||||||
}
|
|
||||||
|
|
||||||
target[k] = [].concat(targetArray).concat(sourceArray);
|
|
||||||
} else {
|
|
||||||
var Ctor = target[k].constructor;
|
|
||||||
var newTarget = new Ctor();
|
|
||||||
merge(newTarget, target[k]);
|
|
||||||
merge(newTarget, source[k]);
|
|
||||||
target[k] = newTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
target[k] = source[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
function TaglibLookup() {
|
|
||||||
this.merged = {};
|
|
||||||
this.taglibsById = {};
|
|
||||||
this._inputFiles = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
TaglibLookup.prototype = {
|
|
||||||
|
|
||||||
|
|
||||||
addTaglib: function (taglib) {
|
|
||||||
ok(taglib, '"taglib" is required');
|
|
||||||
ok(taglib.id, '"taglib.id" expected');
|
|
||||||
|
|
||||||
if (this.taglibsById.hasOwnProperty(taglib.id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.taglibsById[taglib.id] = taglib;
|
|
||||||
|
|
||||||
merge(this.merged, taglib);
|
|
||||||
},
|
|
||||||
|
|
||||||
getTag: function (element) {
|
|
||||||
if (typeof element === 'string') {
|
|
||||||
element = {
|
|
||||||
localName: element
|
|
||||||
};
|
|
||||||
}
|
|
||||||
var tags = this.merged.tags;
|
|
||||||
if (!tags) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tagKey = element.namespace ? element.namespace + ':' + element.localName : element.localName;
|
|
||||||
return tags[tagKey];
|
|
||||||
},
|
|
||||||
|
|
||||||
getAttribute: function (element, attr) {
|
|
||||||
|
|
||||||
if (typeof element === 'string') {
|
|
||||||
element = {
|
|
||||||
localName: element
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof attr === 'string') {
|
|
||||||
attr = {
|
|
||||||
localName: attr
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var tags = this.merged.tags;
|
|
||||||
if (!tags) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tagKey = element.namespace ? element.namespace + ':' + element.localName : element.localName;
|
|
||||||
|
|
||||||
var tag = tags[tagKey];
|
|
||||||
if (!tag) {
|
|
||||||
tag = tags['*'];
|
|
||||||
|
|
||||||
if (!tag) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var attrKey = attr.namespace ? attr.namespace + ':' + attr.localName : attr.localName;
|
|
||||||
|
|
||||||
function findAttribute(attributes) {
|
|
||||||
var attribute = attributes[attrKey];
|
|
||||||
if (attribute === undefined) {
|
|
||||||
if (tag.patternAttributes) {
|
|
||||||
for (var i = 0, len = tag.patternAttributes.length; i < len; i++) {
|
|
||||||
var patternAttribute = tag.patternAttributes[i];
|
|
||||||
if (patternAttribute.pattern.test(attrKey)) {
|
|
||||||
attribute = patternAttribute;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attribute === undefined) {
|
|
||||||
attribute = tag.attributes['*'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return attribute;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var attribute = findAttribute(tag.attributes);
|
|
||||||
|
|
||||||
if (attribute === null) {
|
|
||||||
// This is an imported attribute
|
|
||||||
attribute = findAttribute(this.merged.attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
return attribute;
|
|
||||||
},
|
|
||||||
forEachNodeTransformer: function (node, callback, thisObj) {
|
|
||||||
/*
|
|
||||||
* Based on the type of node we have to choose how to transform it
|
|
||||||
*/
|
|
||||||
if (node.isElementNode()) {
|
|
||||||
this.forEachTagTransformer(node, callback, thisObj);
|
|
||||||
} else if (node.isTextNode()) {
|
|
||||||
this.forEachTextTransformer(callback, thisObj);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
forEachTagTransformer: function (element, callback, thisObj) {
|
|
||||||
if (typeof element === 'string') {
|
|
||||||
element = {
|
|
||||||
localName: element
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var tagKey = element.namespace ? element.namespace + ':' + element.localName : element.localName;
|
|
||||||
/*
|
|
||||||
* If the node is an element node then we need to find all matching
|
|
||||||
* transformers based on the URI and the local name of the element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var transformers = [];
|
|
||||||
|
|
||||||
function addTransformer(transformer) {
|
|
||||||
if (!transformer || !transformer.getInstance) {
|
|
||||||
throw createError(new Error('Invalid transformer'));
|
|
||||||
}
|
|
||||||
|
|
||||||
transformers.push(transformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle all of the transformers for all possible matching transformers.
|
|
||||||
*
|
|
||||||
* Start with the least specific and end with the most specific.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (this.merged.tags[tagKey]) {
|
|
||||||
this.merged.tags[tagKey].forEachTransformer(addTransformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.merged.tags['*']) {
|
|
||||||
this.merged.tags['*'].forEachTransformer(addTransformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
transformers.sort(transformerComparator);
|
|
||||||
|
|
||||||
transformers.forEach(callback, thisObj);
|
|
||||||
},
|
|
||||||
forEachTextTransformer: function (callback, thisObj) {
|
|
||||||
this.merged.textTransformers.sort(transformerComparator);
|
|
||||||
this.merged.textTransformers.forEach(callback, thisObj);
|
|
||||||
},
|
|
||||||
getInputFiles: function() {
|
|
||||||
if (!this._inputFiles) {
|
|
||||||
var inputFilesSet = {};
|
|
||||||
|
|
||||||
for (var taglibId in this.taglibsById) {
|
|
||||||
if (this.taglibsById.hasOwnProperty(taglibId)) {
|
|
||||||
|
|
||||||
var taglibInputFiles = this.taglibsById[taglibId].getInputFiles();
|
|
||||||
var len = taglibInputFiles.length;
|
|
||||||
if (len) {
|
|
||||||
for (var i=0; i<len; i++) {
|
|
||||||
inputFilesSet[taglibInputFiles[i]] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._inputFiles = Object.keys(inputFilesSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._inputFiles;
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
module.exports = TaglibLookup;
|
|
||||||
@ -334,9 +334,15 @@ TemplateBuilder.prototype = {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
include: function (templateName, dataExpression) {
|
include: function (templatePath, dataExpression) {
|
||||||
if (!this.hasErrors()) {
|
if (!this.hasErrors()) {
|
||||||
this.contextHelperMethodCall('i', templateName, dataExpression, new Expression('require'));
|
this.contextHelperMethodCall('i', new Expression('require.resolve(' + templatePath + ')'), dataExpression);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
load: function (templatePath) {
|
||||||
|
if (!this.hasErrors()) {
|
||||||
|
this.contextHelperMethodCall('l', new Expression('require.resolve(' + templatePath + ')'));
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
@ -431,14 +437,16 @@ TemplateBuilder.prototype = {
|
|||||||
this.templateName = templateName;
|
this.templateName = templateName;
|
||||||
},
|
},
|
||||||
makeExpression: function (expression) {
|
makeExpression: function (expression) {
|
||||||
if (expression instanceof Expression) {
|
return this.compiler.makeExpression(expression);
|
||||||
return expression;
|
|
||||||
} else {
|
|
||||||
return new Expression(expression);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
isExpression: function (expression) {
|
isExpression: function (expression) {
|
||||||
return expression instanceof Expression;
|
return this.compiler.isExpression(expression);
|
||||||
|
},
|
||||||
|
parseExpression: function(str, listeners, options) {
|
||||||
|
return this.compiler.parseExpression(str, listeners, options);
|
||||||
|
},
|
||||||
|
parseAttribute: function(attr, types, options) {
|
||||||
|
return this.compiler.parseAttribute(attr, types, options);
|
||||||
},
|
},
|
||||||
getAttribute: function (name) {
|
getAttribute: function (name) {
|
||||||
return this.attributes[name];
|
return this.attributes[name];
|
||||||
|
|||||||
@ -19,14 +19,21 @@ var TemplateBuilder = require('./TemplateBuilder');
|
|||||||
var parser = require('./parser');
|
var parser = require('./parser');
|
||||||
var Expression = require('./Expression');
|
var Expression = require('./Expression');
|
||||||
var TypeConverter = require('./TypeConverter');
|
var TypeConverter = require('./TypeConverter');
|
||||||
var taglibLookup = require('./taglib-lookup');
|
var raptorTaglibs = require('raptor-taglibs');
|
||||||
var nodePath = require('path');
|
var nodePath = require('path');
|
||||||
var ok = require('assert').ok;
|
var ok = require('assert').ok;
|
||||||
|
var attributeParser = require('./attribute-parser');
|
||||||
|
var expressionParser = require('./expression-parser');
|
||||||
|
var inherit = require('raptor-util/inherit');
|
||||||
|
var _Node = require('./Node');
|
||||||
|
var ElementNode = require('./ElementNode');
|
||||||
|
var TextNode = require('./TextNode');
|
||||||
|
var TagHandlerNode = require('raptor-taglib-core/TagHandlerNode');
|
||||||
|
|
||||||
function TemplateCompiler(path, options) {
|
function TemplateCompiler(path, options) {
|
||||||
this.dirname = nodePath.dirname(path);
|
this.dirname = nodePath.dirname(path);
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.taglibs = taglibLookup.buildLookup(this.dirname);
|
this.taglibs = raptorTaglibs.buildLookup(this.dirname);
|
||||||
this.options = options || {};
|
this.options = options || {};
|
||||||
this.errors = [];
|
this.errors = [];
|
||||||
}
|
}
|
||||||
@ -112,7 +119,7 @@ TemplateCompiler.prototype = {
|
|||||||
//The templateBuilder object is need to manage the compiled JavaScript output
|
//The templateBuilder object is need to manage the compiled JavaScript output
|
||||||
this.transformTree(rootNode, templateBuilder);
|
this.transformTree(rootNode, templateBuilder);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw createError(new Error('An error occurred while trying to compile template at path "' + filePath + '". Exception: ' + e), e);
|
throw createError(new Error('An error occurred while trying to compile template at path "' + filePath + '". Exception: ' + (e.stack || e)), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -139,10 +146,22 @@ TemplateCompiler.prototype = {
|
|||||||
isExpression: function (expression) {
|
isExpression: function (expression) {
|
||||||
return expression instanceof Expression;
|
return expression instanceof Expression;
|
||||||
},
|
},
|
||||||
|
makeExpression: function (expression) {
|
||||||
|
if (this.isExpression(expression)) {
|
||||||
|
return expression;
|
||||||
|
} else {
|
||||||
|
return new Expression(expression);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parseExpression: function(str, listeners, options) {
|
||||||
|
return expressionParser.parse(str, listeners, options);
|
||||||
|
},
|
||||||
|
parseAttribute: function(attr, types, options) {
|
||||||
|
return attributeParser.parse(attr, types, options);
|
||||||
|
},
|
||||||
createTagHandlerNode: function (tagName) {
|
createTagHandlerNode: function (tagName) {
|
||||||
var TagHandlerNode = require('../../taglibs/core/TagHandlerNode');
|
|
||||||
var tag = this.taglibs.getTag(tagName);
|
var tag = this.taglibs.getTag(tagName);
|
||||||
var tagHandlerNode = new TagHandlerNode(tag);
|
var tagHandlerNode = this.createNode(TagHandlerNode, tag);
|
||||||
return tagHandlerNode;
|
return tagHandlerNode;
|
||||||
},
|
},
|
||||||
convertType: function (value, type, allowExpressions) {
|
convertType: function (value, type, allowExpressions) {
|
||||||
@ -166,9 +185,7 @@ TemplateCompiler.prototype = {
|
|||||||
var tag = this.taglibs.getTag(tagName);
|
var tag = this.taglibs.getTag(tagName);
|
||||||
if (tag && tag.nodeClass) {
|
if (tag && tag.nodeClass) {
|
||||||
var nodeClass = require(tag.nodeClass);
|
var nodeClass = require(tag.nodeClass);
|
||||||
if (nodeClass.prototype.constructor !== nodeClass) {
|
nodeClass.prototype.constructor = nodeClass;
|
||||||
throw new Error('constructor not set correctly');
|
|
||||||
}
|
|
||||||
return nodeClass;
|
return nodeClass;
|
||||||
}
|
}
|
||||||
throw createError(new Error('Node class not found for tag "' + tagName + '"'));
|
throw createError(new Error('Node class not found for tag "' + tagName + '"'));
|
||||||
@ -177,6 +194,35 @@ TemplateCompiler.prototype = {
|
|||||||
var Taglib = require('./Taglib');
|
var Taglib = require('./Taglib');
|
||||||
return new Taglib.Tag();
|
return new Taglib.Tag();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
inheritNode: function(Ctor) {
|
||||||
|
if (!Ctor.prototype.__NODE) {
|
||||||
|
var nodeType = Ctor.nodeType || 'node';
|
||||||
|
nodeType = nodeType.toLowerCase();
|
||||||
|
|
||||||
|
if (nodeType === 'element') {
|
||||||
|
inherit(Ctor, ElementNode);
|
||||||
|
} else if (nodeType === 'node') {
|
||||||
|
inherit(Ctor, _Node);
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid node type: ' + nodeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createNode: function(Ctor, arg) {
|
||||||
|
ok(Ctor != null, 'Ctor is required');
|
||||||
|
ok(typeof Ctor === 'function', 'Ctor should be a function');
|
||||||
|
|
||||||
|
this.inheritNode(Ctor);
|
||||||
|
|
||||||
|
return new Ctor(arg);
|
||||||
|
},
|
||||||
|
|
||||||
|
createTextNode: function(text, escapeXml) {
|
||||||
|
return new TextNode(text, escapeXml);
|
||||||
|
},
|
||||||
|
|
||||||
checkUpToDate: function(sourceFile, targetFile) {
|
checkUpToDate: function(sourceFile, targetFile) {
|
||||||
if (this.options.checkUpToDate === false) {
|
if (this.options.checkUpToDate === false) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -63,7 +63,7 @@ TextNode.prototype = {
|
|||||||
var parentNode = this.parentNode;
|
var parentNode = this.parentNode;
|
||||||
var shouldEscapeXml = this.escapeXml !== false && parentNode && parentNode.isEscapeXmlBodyText() !== false;
|
var shouldEscapeXml = this.escapeXml !== false && parentNode && parentNode.isEscapeXmlBodyText() !== false;
|
||||||
if (shouldEscapeXml) {
|
if (shouldEscapeXml) {
|
||||||
if (this.getEscapeXmlContext() === EscapeXmlContext.Attribute) {
|
if (this.getEscapeXmlContext() === EscapeXmlContext.ATTRIBUTE) {
|
||||||
return escapeXmlAttr(text);
|
return escapeXmlAttr(text);
|
||||||
} else {
|
} else {
|
||||||
return escapeXml(text);
|
return escapeXml(text);
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
var createError = require('raptor-util').createError;
|
var createError = require('raptor-util').createError;
|
||||||
var ExpressionParser = require('./ExpressionParser');
|
var expressionParser = require('./expression-parser');
|
||||||
var stringify = require('raptor-json/stringify');
|
var stringify = require('raptor-json/stringify');
|
||||||
var Expression = require('./Expression');
|
var Expression = require('./Expression');
|
||||||
function TypeConverter() {
|
function TypeConverter() {
|
||||||
@ -29,6 +29,9 @@ TypeConverter.convert = function (value, targetType, allowExpressions) {
|
|||||||
if (targetType === 'custom' || targetType === 'identifier') {
|
if (targetType === 'custom' || targetType === 'identifier') {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (targetType === 'expression') {
|
if (targetType === 'expression') {
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
value = 'null';
|
value = 'null';
|
||||||
@ -37,7 +40,7 @@ TypeConverter.convert = function (value, targetType, allowExpressions) {
|
|||||||
}
|
}
|
||||||
var processedText = '';
|
var processedText = '';
|
||||||
if (allowExpressions) {
|
if (allowExpressions) {
|
||||||
ExpressionParser.parse(value, {
|
expressionParser.parse(value, {
|
||||||
text: function (text) {
|
text: function (text) {
|
||||||
processedText += text;
|
processedText += text;
|
||||||
expressionParts.push(stringify(text));
|
expressionParts.push(stringify(text));
|
||||||
@ -47,9 +50,17 @@ TypeConverter.convert = function (value, targetType, allowExpressions) {
|
|||||||
hasExpression = true;
|
hasExpression = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hasExpression) {
|
if (hasExpression) {
|
||||||
return new Expression(expressionParts.join('+'));
|
value = new Expression(expressionParts.join('+'));
|
||||||
|
|
||||||
|
if (targetType === 'template') {
|
||||||
|
return new Expression('__helpers.l(' + value + ')');
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = processedText;
|
value = processedText;
|
||||||
}
|
}
|
||||||
if (targetType === 'string') {
|
if (targetType === 'string') {
|
||||||
@ -76,6 +87,8 @@ TypeConverter.convert = function (value, targetType, allowExpressions) {
|
|||||||
}
|
}
|
||||||
} else if (targetType === 'path') {
|
} else if (targetType === 'path') {
|
||||||
return new Expression('require.resolve(' + JSON.stringify(value) + ')');
|
return new Expression('require.resolve(' + JSON.stringify(value) + ')');
|
||||||
|
} else if (targetType === 'template') {
|
||||||
|
return new Expression('__helpers.l(require.resolve(' + JSON.stringify(value) + '))');
|
||||||
} else {
|
} else {
|
||||||
throw createError(new Error('Unsupported attribute type: ' + targetType));
|
throw createError(new Error('Unsupported attribute type: ' + targetType));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,8 +31,7 @@ var createError = require('raptor-util').createError;
|
|||||||
var strings = require('raptor-strings');
|
var strings = require('raptor-strings');
|
||||||
var TypeConverter = require('./TypeConverter');
|
var TypeConverter = require('./TypeConverter');
|
||||||
var regExp = /"(?:[^"]|\\")*"|'(?:[^']|\\')*'|==|===|[;=]/g;
|
var regExp = /"(?:[^"]|\\")*"|'(?:[^']|\\')*'|==|===|[;=]/g;
|
||||||
function AttributeSplitter() {
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Parses the provided string to find the sub-attributes that it contains.
|
* Parses the provided string to find the sub-attributes that it contains.
|
||||||
* The parsed output can be either returned as an array or a map. By default,
|
* The parsed output can be either returned as an array or a map. By default,
|
||||||
@ -54,7 +53,7 @@ function AttributeSplitter() {
|
|||||||
* @param options
|
* @param options
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
AttributeSplitter.parse = function (attr, types, options) {
|
exports.parse = function (attr, types, options) {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
@ -136,7 +135,7 @@ AttributeSplitter.parse = function (attr, types, options) {
|
|||||||
* but they are just ignored. This ensures that semicolons inside strings
|
* but they are just ignored. This ensures that semicolons inside strings
|
||||||
* are not treated as
|
* are not treated as
|
||||||
*/
|
*/
|
||||||
while (matches = regExp.exec(attr)) {
|
while ((matches = regExp.exec(attr))) {
|
||||||
//console.error(matches[0]);
|
//console.error(matches[0]);
|
||||||
if (matches[0] == ';') {
|
if (matches[0] == ';') {
|
||||||
finishPart(matches.index);
|
finishPart(matches.index);
|
||||||
@ -151,5 +150,4 @@ AttributeSplitter.parse = function (attr, types, options) {
|
|||||||
finishPart(attr.length);
|
finishPart(attr.length);
|
||||||
//console.error("AttributeSplitter - result: ", result);
|
//console.error("AttributeSplitter - result: ", result);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
module.exports = AttributeSplitter;
|
|
||||||
@ -29,6 +29,9 @@ var endingTokens = {
|
|||||||
'$': null,
|
'$': null,
|
||||||
'$!': null
|
'$!': null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var parse;
|
||||||
|
|
||||||
function createStartRegExpStr(starts) {
|
function createStartRegExpStr(starts) {
|
||||||
var parts = [];
|
var parts = [];
|
||||||
starts.forEach(function (start) {
|
starts.forEach(function (start) {
|
||||||
@ -54,6 +57,7 @@ function getLine(str, pos) {
|
|||||||
var lines = str.split('\n');
|
var lines = str.split('\n');
|
||||||
var index = 0;
|
var index = 0;
|
||||||
var line;
|
var line;
|
||||||
|
|
||||||
while (index < lines.length) {
|
while (index < lines.length) {
|
||||||
line = lines[index];
|
line = lines[index];
|
||||||
if (pos - line.length + 1 < 0) {
|
if (pos - line.length + 1 < 0) {
|
||||||
@ -63,13 +67,11 @@ function getLine(str, pos) {
|
|||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
function ExpressionParser() {
|
|
||||||
}
|
return {
|
||||||
ExpressionParser.prototype = {
|
|
||||||
str: line,
|
str: line,
|
||||||
pos: pos
|
pos: pos
|
||||||
};
|
};
|
||||||
return ExpressionParser;
|
|
||||||
}
|
}
|
||||||
function errorContext(str, pos, length) {
|
function errorContext(str, pos, length) {
|
||||||
var line = getLine(str, pos);
|
var line = getLine(str, pos);
|
||||||
@ -104,7 +106,7 @@ function getConditionalExpression(expression) {
|
|||||||
var depth = 0;
|
var depth = 0;
|
||||||
var parts = [];
|
var parts = [];
|
||||||
var partStart = 0;
|
var partStart = 0;
|
||||||
while (matches = tokensRegExp.exec(expression)) {
|
while ((matches = tokensRegExp.exec(expression))) {
|
||||||
if (matches[0] === '{') {
|
if (matches[0] === '{') {
|
||||||
depth++;
|
depth++;
|
||||||
continue;
|
continue;
|
||||||
@ -141,7 +143,7 @@ function getConditionalExpression(expression) {
|
|||||||
}
|
}
|
||||||
function getExpression(part) {
|
function getExpression(part) {
|
||||||
var expressionParts = [];
|
var expressionParts = [];
|
||||||
ExpressionParser.parse(part, {
|
parse(part, {
|
||||||
text: function (text) {
|
text: function (text) {
|
||||||
expressionParts.push(stringify(text));
|
expressionParts.push(stringify(text));
|
||||||
},
|
},
|
||||||
@ -178,7 +180,7 @@ function processNestedStrings(expression, foundStrings) {
|
|||||||
}
|
}
|
||||||
hasExpression = false;
|
hasExpression = false;
|
||||||
parts = [];
|
parts = [];
|
||||||
ExpressionParser.parse(foundString.value, {
|
parse(foundString.value, {
|
||||||
text: handleText,
|
text: handleText,
|
||||||
expression: handleExpression
|
expression: handleExpression
|
||||||
});
|
});
|
||||||
@ -188,59 +190,56 @@ function processNestedStrings(expression, foundStrings) {
|
|||||||
}
|
}
|
||||||
return expression;
|
return expression;
|
||||||
}
|
}
|
||||||
var ExpressionParserHelper = function () {
|
|
||||||
function Class(callback, callbackThisObj) {
|
function ExpressionParserHelper(listeners) {
|
||||||
this.callback = callback;
|
this.listeners = listeners;
|
||||||
this.callbackThisObj = callbackThisObj;
|
this.prevText = null;
|
||||||
|
this.prevEscapeXml = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionParserHelper.prototype = {
|
||||||
|
_invokeCallback: function (name, value, escapeXml) {
|
||||||
|
if (!this.listeners[name]) {
|
||||||
|
throw createError(new Error(name + ' not allowed: ' + value));
|
||||||
|
}
|
||||||
|
this.listeners[name](value, escapeXml);
|
||||||
|
},
|
||||||
|
_endText: function () {
|
||||||
|
if (this.prevText !== null) {
|
||||||
|
this._invokeCallback('text', this.prevText, this.prevEscapeXml);
|
||||||
this.prevText = null;
|
this.prevText = null;
|
||||||
this.prevEscapeXml = null;
|
this.prevEscapeXml = null;
|
||||||
}
|
}
|
||||||
Class.prototype = {
|
},
|
||||||
_invokeCallback: function (name, value, escapeXml) {
|
addXmlText: function (xmlText) {
|
||||||
if (!this.callback[name]) {
|
this.addText(xmlText, false);
|
||||||
throw createError(new Error(name + ' not allowed: ' + value));
|
},
|
||||||
}
|
addText: function (text, escapeXml) {
|
||||||
this.callback[name].call(this.callbackThisObj, value, escapeXml);
|
if (this.prevText !== null && this.prevEscapeXml === escapeXml) {
|
||||||
},
|
this.prevText += text;
|
||||||
_endText: function () {
|
} else {
|
||||||
if (this.prevText !== null) {
|
this._endText();
|
||||||
this._invokeCallback('text', this.prevText, this.prevEscapeXml);
|
this.prevText = text;
|
||||||
this.prevText = null;
|
this.prevEscapeXml = escapeXml;
|
||||||
this.prevEscapeXml = null;
|
}
|
||||||
}
|
},
|
||||||
},
|
addXmlExpression: function (expression, escapeXml) {
|
||||||
addXmlText: function (xmlText) {
|
this.addExpression(expression, false);
|
||||||
this.addText(xmlText, false);
|
},
|
||||||
},
|
addExpression: function (expression, escapeXml) {
|
||||||
addText: function (text, escapeXml) {
|
this._endText();
|
||||||
if (this.prevText !== null && this.prevEscapeXml === escapeXml) {
|
if (!(expression instanceof Expression)) {
|
||||||
this.prevText += text;
|
expression = new Expression(expression);
|
||||||
} else {
|
}
|
||||||
this._endText();
|
this._invokeCallback('expression', expression, escapeXml !== false);
|
||||||
this.prevText = text;
|
},
|
||||||
this.prevEscapeXml = escapeXml;
|
addScriptlet: function (scriptlet) {
|
||||||
}
|
this._endText();
|
||||||
},
|
this._invokeCallback('scriptlet', scriptlet);
|
||||||
addXmlExpression: function (expression, escapeXml) {
|
}
|
||||||
this.addExpression(expression, false);
|
};
|
||||||
},
|
|
||||||
addExpression: function (expression, escapeXml) {
|
|
||||||
this._endText();
|
|
||||||
if (!(expression instanceof Expression)) {
|
|
||||||
expression = new Expression(expression);
|
|
||||||
}
|
|
||||||
this._invokeCallback('expression', expression, escapeXml !== false);
|
|
||||||
},
|
|
||||||
addScriptlet: function (scriptlet) {
|
|
||||||
this._endText();
|
|
||||||
this._invokeCallback('scriptlet', scriptlet);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return Class;
|
|
||||||
}();
|
|
||||||
|
|
||||||
function ExpressionParser() {
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @memberOf raptor/templating/compiler$ExpressionParser
|
* @memberOf raptor/templating/compiler$ExpressionParser
|
||||||
*
|
*
|
||||||
@ -248,7 +247,7 @@ function ExpressionParser() {
|
|||||||
* @param callback
|
* @param callback
|
||||||
* @param thisObj
|
* @param thisObj
|
||||||
*/
|
*/
|
||||||
ExpressionParser.parse = function (str, callback, thisObj, options) {
|
parse = function (str, listeners, options) {
|
||||||
|
|
||||||
ok(str != null, '"str" is required');
|
ok(str != null, '"str" is required');
|
||||||
|
|
||||||
@ -266,21 +265,21 @@ ExpressionParser.parse = function (str, callback, thisObj, options) {
|
|||||||
var startToken;
|
var startToken;
|
||||||
var custom = options.custom || {};
|
var custom = options.custom || {};
|
||||||
function handleError(message) {
|
function handleError(message) {
|
||||||
if (callback.error) {
|
if (listeners.error) {
|
||||||
callback.error.call(thisObj, message);
|
listeners.error(message);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
throw createError(new Error(message));
|
throw createError(new Error(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var startRegExp = createStartRegExp();
|
var startRegExp = createStartRegExp();
|
||||||
var helper = new ExpressionParserHelper(callback, thisObj);
|
var helper = new ExpressionParserHelper(listeners);
|
||||||
startRegExp.lastIndex = 0;
|
startRegExp.lastIndex = 0;
|
||||||
/*
|
/*
|
||||||
* Look for any of the possible start tokens (including the escaped and double-escaped versions)
|
* Look for any of the possible start tokens (including the escaped and double-escaped versions)
|
||||||
*/
|
*/
|
||||||
outer:
|
outer:
|
||||||
while (startMatches = startRegExp.exec(str)) {
|
while ((startMatches = startRegExp.exec(str))) {
|
||||||
if (strings.startsWith(startMatches[0], '\\\\')) {
|
if (strings.startsWith(startMatches[0], '\\\\')) {
|
||||||
// \\${
|
// \\${
|
||||||
/*
|
/*
|
||||||
@ -355,7 +354,7 @@ ExpressionParser.parse = function (str, callback, thisObj, options) {
|
|||||||
var depth = 0;
|
var depth = 0;
|
||||||
var foundStrings = [];
|
var foundStrings = [];
|
||||||
var handler;
|
var handler;
|
||||||
while (endMatches = endRegExp.exec(str)) {
|
while ((endMatches = endRegExp.exec(str))) {
|
||||||
if (endMatches[0] === '{') {
|
if (endMatches[0] === '{') {
|
||||||
depth++;
|
depth++;
|
||||||
continue;
|
continue;
|
||||||
@ -391,9 +390,9 @@ ExpressionParser.parse = function (str, callback, thisObj, options) {
|
|||||||
var customType;
|
var customType;
|
||||||
if (firstColon != -1) {
|
if (firstColon != -1) {
|
||||||
customType = expression.substring(0, firstColon);
|
customType = expression.substring(0, firstColon);
|
||||||
handler = custom[customType] || ExpressionParser.custom[customType];
|
handler = custom[customType] || exports.custom[customType];
|
||||||
if (handler) {
|
if (handler) {
|
||||||
handler.call(ExpressionParser, expression.substring(firstColon + 1), helper);
|
handler.call(exports, expression.substring(firstColon + 1), helper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +425,9 @@ ExpressionParser.parse = function (str, callback, thisObj, options) {
|
|||||||
}
|
}
|
||||||
helper._endText();
|
helper._endText();
|
||||||
};
|
};
|
||||||
ExpressionParser.custom = {
|
|
||||||
|
exports.parse = parse;
|
||||||
|
exports.custom = {
|
||||||
'xml': function (expression, helper) {
|
'xml': function (expression, helper) {
|
||||||
helper.addXmlExpression(new Expression(expression));
|
helper.addXmlExpression(new Expression(expression));
|
||||||
},
|
},
|
||||||
@ -443,4 +444,3 @@ ExpressionParser.custom = {
|
|||||||
helper.addText('\n');
|
helper.addText('\n');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
module.exports = ExpressionParser;
|
|
||||||
@ -15,7 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
var extend = require('raptor-util').extend;
|
var extend = require('raptor-util').extend;
|
||||||
|
var raptorTaglibs = require('raptor-taglibs');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
var nodePath = require('path');
|
||||||
|
|
||||||
var defaultOptions = {
|
var defaultOptions = {
|
||||||
minify: false,
|
minify: false,
|
||||||
@ -80,8 +82,7 @@ extend(exports, {
|
|||||||
Node: require('./Node'),
|
Node: require('./Node'),
|
||||||
ElementNode: require('./ElementNode'),
|
ElementNode: require('./ElementNode'),
|
||||||
TextNode: require('./TextNode'),
|
TextNode: require('./TextNode'),
|
||||||
AttributeSplitter: require('./AttributeSplitter'),
|
expressionParser: require('./expression-parser'),
|
||||||
ExpressionParser: require('./ExpressionParser'),
|
|
||||||
Expression: require('./Expression'),
|
Expression: require('./Expression'),
|
||||||
TypeConverter: require('./TypeConverter'),
|
TypeConverter: require('./TypeConverter'),
|
||||||
EscapeXmlContext: require('./EscapeXmlContext'),
|
EscapeXmlContext: require('./EscapeXmlContext'),
|
||||||
@ -89,3 +90,10 @@ extend(exports, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
exports.TemplateCompiler = require('./TemplateCompiler');
|
exports.TemplateCompiler = require('./TemplateCompiler');
|
||||||
|
|
||||||
|
raptorTaglibs.excludeDir(nodePath.join(__dirname, '../..'));
|
||||||
|
raptorTaglibs.registerTaglib(require.resolve('raptor-taglib-core/raptor-taglib.json'));
|
||||||
|
raptorTaglibs.registerTaglib(require.resolve('raptor-taglib-html/raptor-taglib.json'));
|
||||||
|
raptorTaglibs.registerTaglib(require.resolve('raptor-taglib-caching/raptor-taglib.json'));
|
||||||
|
raptorTaglibs.registerTaglib(require.resolve('raptor-taglib-layout/raptor-taglib.json'));
|
||||||
|
raptorTaglibs.registerTaglib(require.resolve('raptor-taglib-async/raptor-taglib.json'));
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
// Rather than using a full-blown JavaScript parser, we are going to use a few regular expressions
|
|
||||||
// to tokenize the code and find what we are interested in
|
|
||||||
var tagStartRegExp = /(^\s*exports.tag\s*=\s*)\{/m;
|
|
||||||
|
|
||||||
// Tokens: "<string>", '<string>', /*<some comment*/, //<single line comment>, {, }, ;
|
|
||||||
var tokensRegExp = /"(?:[^"]|\\")*"|'(?:[^'])|(\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/)|(\/\/.*)|[\{\};]/g;
|
|
||||||
|
|
||||||
function extractTagDef(code) {
|
|
||||||
|
|
||||||
var startMatches = tagStartRegExp.exec(code);
|
|
||||||
|
|
||||||
var tagDefStart;
|
|
||||||
var tagDefEnd;
|
|
||||||
|
|
||||||
if (startMatches) {
|
|
||||||
tagDefStart = startMatches.index + startMatches[1].length;
|
|
||||||
var nextTokenMatches;
|
|
||||||
tokensRegExp.lastIndex = tagDefStart;
|
|
||||||
var depth = 0;
|
|
||||||
|
|
||||||
while ((nextTokenMatches = tokensRegExp.exec(code))) {
|
|
||||||
if (nextTokenMatches[0] === '{') {
|
|
||||||
depth++;
|
|
||||||
continue;
|
|
||||||
} else if (nextTokenMatches[0] === '}') {
|
|
||||||
if (--depth === 0) {
|
|
||||||
tagDefEnd = tokensRegExp.lastIndex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (nextTokenMatches[0] === ';') {
|
|
||||||
tagDefEnd = nextTokenMatches.index;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagDefStart != null && tagDefEnd != null) {
|
|
||||||
var jsTagDef = code.substring(tagDefStart, tagDefEnd);
|
|
||||||
var tagDefObject = eval('(' + jsTagDef + ')');
|
|
||||||
return tagDefObject;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.extractTagDef = extractTagDef;
|
|
||||||
@ -1,393 +0,0 @@
|
|||||||
var fs = require('fs');
|
|
||||||
var ok = require('assert').ok;
|
|
||||||
var nodePath = require('path');
|
|
||||||
var Taglib = require('./Taglib');
|
|
||||||
var cache = {};
|
|
||||||
var forEachEntry = require('raptor-util').forEachEntry;
|
|
||||||
var raptorRegexp = require('raptor-regexp');
|
|
||||||
var tagDefFromCode = require('./tag-def-from-code');
|
|
||||||
var resolve = require('raptor-modules/resolver').serverResolveRequire;
|
|
||||||
var propertyHandlers = require('property-handlers');
|
|
||||||
|
|
||||||
function buildAttribute(attr, attrProps, path) {
|
|
||||||
|
|
||||||
|
|
||||||
propertyHandlers(attrProps, {
|
|
||||||
type: function(value) {
|
|
||||||
attr.type = value;
|
|
||||||
},
|
|
||||||
targetProperty: function(value) {
|
|
||||||
attr.targetProperty = value;
|
|
||||||
},
|
|
||||||
defaultValue: function(value) {
|
|
||||||
attr.defaultValue = value;
|
|
||||||
},
|
|
||||||
pattern: function(value) {
|
|
||||||
if (value === true) {
|
|
||||||
var patternRegExp = raptorRegexp.simple(attr.name);
|
|
||||||
attr.pattern = patternRegExp;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
allowExpressions: function(value) {
|
|
||||||
attr.allowExpressions = value;
|
|
||||||
},
|
|
||||||
preserveName: function(value) {
|
|
||||||
attr.preserveName = value;
|
|
||||||
},
|
|
||||||
required: function(value) {
|
|
||||||
attr.required = value === true;
|
|
||||||
},
|
|
||||||
removeDashes: function(value) {
|
|
||||||
attr.removeDashes = value === true;
|
|
||||||
}
|
|
||||||
}, path);
|
|
||||||
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleAttributes(value, parent, path) {
|
|
||||||
forEachEntry(value, function(attrName, attrProps) {
|
|
||||||
var attr = new Taglib.Attribute(attrName);
|
|
||||||
|
|
||||||
if (attrProps == null) {
|
|
||||||
attrProps = {
|
|
||||||
type: 'string'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (typeof attrProps === 'string') {
|
|
||||||
attrProps = {
|
|
||||||
type: attrProps
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
buildAttribute(attr, attrProps, '"' + attrName + '" attribute as part of ' + path);
|
|
||||||
|
|
||||||
parent.addAttribute(attr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildTag(tagObject, path, taglib, dirname) {
|
|
||||||
ok(tagObject);
|
|
||||||
ok(typeof path === 'string');
|
|
||||||
ok(taglib);
|
|
||||||
ok(typeof dirname === 'string');
|
|
||||||
|
|
||||||
var tag = new Taglib.Tag(taglib);
|
|
||||||
|
|
||||||
propertyHandlers(tagObject, {
|
|
||||||
name: function(value) {
|
|
||||||
tag.name = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
renderer: function(value) {
|
|
||||||
var path = resolve(value, dirname);
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
throw new Error('Renderer at path "' + path + '" does not exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
tag.renderer = path;
|
|
||||||
},
|
|
||||||
template: function(value) {
|
|
||||||
var path = nodePath.resolve(dirname, value);
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
throw new Error('Template at path "' + path + '" does not exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
tag.template = path;
|
|
||||||
},
|
|
||||||
attributes: function(value) {
|
|
||||||
handleAttributes(value, tag, path);
|
|
||||||
},
|
|
||||||
nodeClass: function(value) {
|
|
||||||
var path = resolve(value, dirname);
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
throw new Error('Node module at path "' + path + '" does not exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
tag.nodeClass = path;
|
|
||||||
},
|
|
||||||
transformer: function(value) {
|
|
||||||
var transformer = new Taglib.Transformer();
|
|
||||||
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
value = {
|
|
||||||
path: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyHandlers(value, {
|
|
||||||
path: function(value) {
|
|
||||||
var path = resolve(value, dirname);
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
throw new Error('Transformer at path "' + path + '" does not exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
transformer.path = path;
|
|
||||||
},
|
|
||||||
|
|
||||||
priority: function(value) {
|
|
||||||
transformer.priority = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
name: function(value) {
|
|
||||||
transformer.name = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
properties: function(value) {
|
|
||||||
var properties = transformer.properties || (transformer.properties = {});
|
|
||||||
for (var k in value) {
|
|
||||||
if (value.hasOwnProperty(k)) {
|
|
||||||
properties[k] = value[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 'transformer in ' + path);
|
|
||||||
|
|
||||||
ok(transformer.path, '"path" is required for transformer');
|
|
||||||
|
|
||||||
tag.addTransformer(transformer);
|
|
||||||
},
|
|
||||||
|
|
||||||
'var': function(value) {
|
|
||||||
tag.addNestedVariable({
|
|
||||||
name: value
|
|
||||||
});
|
|
||||||
},
|
|
||||||
vars: function(value) {
|
|
||||||
if (value) {
|
|
||||||
value.forEach(function(v, i) {
|
|
||||||
var nestedVariable;
|
|
||||||
|
|
||||||
if (typeof v === 'string') {
|
|
||||||
nestedVariable = {
|
|
||||||
name: v
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
nestedVariable = {};
|
|
||||||
|
|
||||||
propertyHandlers(v, {
|
|
||||||
|
|
||||||
name: function(value) {
|
|
||||||
nestedVariable.name = value;
|
|
||||||
},
|
|
||||||
|
|
||||||
nameFromAttribute: function(value) {
|
|
||||||
nestedVariable.nameFromAttribute = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 'var at index ' + i);
|
|
||||||
|
|
||||||
if (!nestedVariable.name && !nestedVariable.nameFromAttribute) {
|
|
||||||
throw new Error('The "name" or "name-from-attribute" attribute is required for a nested variable');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tag.addNestedVariable(nestedVariable);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
importVar: function(value) {
|
|
||||||
forEachEntry(value, function(varName, varValue) {
|
|
||||||
var importedVar = {
|
|
||||||
targetProperty: varName
|
|
||||||
};
|
|
||||||
|
|
||||||
var expression = varValue;
|
|
||||||
|
|
||||||
if (!expression) {
|
|
||||||
expression = varName;
|
|
||||||
}
|
|
||||||
else if (typeof expression === 'object') {
|
|
||||||
expression = expression.expression;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!expression) {
|
|
||||||
throw new Error('Invalid "import-var": ' + require('util').inspect(varValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
importedVar.expression = expression;
|
|
||||||
tag.addImportedVariable(importedVar);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, path);
|
|
||||||
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {String} tagsConfigPath path to tag definition file
|
|
||||||
* @param {String} tagsConfigDirname path to directory of tags config file (should be path.dirname(tagsConfigPath))
|
|
||||||
* @param {String} dir the path to directory to scan
|
|
||||||
* @param {String} taglib the taglib that is being loaded
|
|
||||||
*/
|
|
||||||
function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, taglib) {
|
|
||||||
dir = nodePath.resolve(tagsConfigDirname, dir);
|
|
||||||
var children = fs.readdirSync(dir);
|
|
||||||
for (var i=0, len=children.length; i<len; i++) {
|
|
||||||
var childFilename = children[i];
|
|
||||||
if (childFilename === 'node_modules') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var tagDirname = nodePath.join(dir, childFilename);
|
|
||||||
var tagFile = nodePath.join(dir, childFilename, 'raptor-tag.json');
|
|
||||||
var tagObject;
|
|
||||||
var tag;
|
|
||||||
var rendererFile = nodePath.join(dir, childFilename, 'renderer.js');
|
|
||||||
|
|
||||||
// Record dependencies so that we can check if a template is up-to-date
|
|
||||||
taglib.addInputFile(tagFile);
|
|
||||||
taglib.addInputFile(rendererFile);
|
|
||||||
|
|
||||||
if (fs.existsSync(tagFile)) {
|
|
||||||
// raptor-tag.json exists in the directory, use that as the tag definition
|
|
||||||
tagObject = JSON.parse(fs.readFileSync(tagFile, {encoding: 'utf8'}));
|
|
||||||
tag = buildTag(tagObject, tagsConfigPath, taglib, tagDirname);
|
|
||||||
tag.name = childFilename;
|
|
||||||
taglib.addTag(tag);
|
|
||||||
} else {
|
|
||||||
// raptor-tag.json does *not* exist... checking for a 'renderer.js'
|
|
||||||
|
|
||||||
if (fs.existsSync(rendererFile)) {
|
|
||||||
var rendererCode = fs.readFileSync(rendererFile, {encoding: 'utf8'});
|
|
||||||
var tagDef = tagDefFromCode.extractTagDef(rendererCode);
|
|
||||||
if (!tagDef) {
|
|
||||||
tagDef = {
|
|
||||||
attributes: {
|
|
||||||
'*': {
|
|
||||||
type: 'string',
|
|
||||||
targetProperty: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
tagDef.renderer = rendererFile;
|
|
||||||
tag = buildTag(tagDef, tagsConfigPath, taglib, tagDirname);
|
|
||||||
tag.name = childFilename;
|
|
||||||
taglib.addTag(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function load(path) {
|
|
||||||
if (cache[path]) {
|
|
||||||
return cache[path];
|
|
||||||
}
|
|
||||||
|
|
||||||
var src = fs.readFileSync(path, {encoding: 'utf8'});
|
|
||||||
var taglib = new Taglib(path);
|
|
||||||
taglib.addInputFile(path);
|
|
||||||
var dirname = nodePath.dirname(path);
|
|
||||||
|
|
||||||
var taglibObject;
|
|
||||||
|
|
||||||
try {
|
|
||||||
taglibObject = JSON.parse(src);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
throw new Error('Unable to parse taglib JSON at path "' + path + '". Exception: ' + e);
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyHandlers(taglibObject, {
|
|
||||||
attributes: function(value) {
|
|
||||||
handleAttributes(value, taglib, path);
|
|
||||||
},
|
|
||||||
tags: function(tags) {
|
|
||||||
forEachEntry(tags, function(tagName, path) {
|
|
||||||
ok(path, 'Invalid tag definition for "' + tagName + '"');
|
|
||||||
var tagObject;
|
|
||||||
|
|
||||||
var tagDirname;
|
|
||||||
|
|
||||||
if (typeof path === 'string') {
|
|
||||||
path = nodePath.resolve(dirname, path);
|
|
||||||
taglib.addInputFile(path);
|
|
||||||
|
|
||||||
tagDirname = nodePath.dirname(path);
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
throw new Error('Tag at path "' + path + '" does not exist. Taglib: ' + taglib.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
var tagJSON = fs.readFileSync(path, {encoding: 'utf8'});
|
|
||||||
|
|
||||||
try {
|
|
||||||
tagObject = JSON.parse(tagJSON);
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
throw new Error('Unable to parse tag JSON for tag at path "' + path + '"');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tagDirname = dirname; // Tag is in the same taglib file
|
|
||||||
tagObject = path;
|
|
||||||
path = '<' + tagName + '> tag in ' + taglib.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var tag = buildTag(tagObject, path, taglib, tagDirname);
|
|
||||||
if (tag.name === undefined) {
|
|
||||||
tag.name = tagName;
|
|
||||||
}
|
|
||||||
taglib.addTag(tag);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
tagsDir: function(dir) {
|
|
||||||
|
|
||||||
if (Array.isArray(dir)) {
|
|
||||||
for (var i = 0; i < dir.length; i++) {
|
|
||||||
scanTagsDir(path, dirname, dir[i], taglib);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
scanTagsDir(path, dirname, dir, taglib);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
textTransformer: function(value) {
|
|
||||||
var transformer = new Taglib.Transformer();
|
|
||||||
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
value = {
|
|
||||||
path: value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyHandlers(value, {
|
|
||||||
path: function(value) {
|
|
||||||
var path = resolve(value, dirname);
|
|
||||||
if (!fs.existsSync(path)) {
|
|
||||||
throw new Error('Transformer at path "' + path + '" does not exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
transformer.path = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
}, 'text-transformer in ' + path);
|
|
||||||
|
|
||||||
ok(transformer.path, '"path" is required for transformer');
|
|
||||||
|
|
||||||
taglib.addTextTransformer(transformer);
|
|
||||||
}
|
|
||||||
}, path);
|
|
||||||
|
|
||||||
taglib.id = path;
|
|
||||||
|
|
||||||
cache[path] = taglib;
|
|
||||||
|
|
||||||
return taglib;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadTaglibXml(taglibXml, path) {
|
|
||||||
var TaglibXmlLoader = require('./TaglibXmlLoader');
|
|
||||||
var taglib = TaglibXmlLoader.load(taglibXml, path);
|
|
||||||
taglib.id = path;
|
|
||||||
return taglib;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadTaglibXmlFromFile(path) {
|
|
||||||
var src = fs.readFileSync(path, {encoding: 'utf8'});
|
|
||||||
return loadTaglibXml(src, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.load = load;
|
|
||||||
exports.loadTaglibXml = loadTaglibXml;
|
|
||||||
exports.loadTaglibXmlFromFile = loadTaglibXmlFromFile;
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
var nodePath = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var taglibLoader = require('./taglib-loader');
|
|
||||||
var existsCache = {};
|
|
||||||
var File = require('raptor-files/File');
|
|
||||||
var TaglibLookup = require('./TaglibLookup');
|
|
||||||
|
|
||||||
exports.coreTaglibs = [];
|
|
||||||
|
|
||||||
var lookupCache = {};
|
|
||||||
var discoverCache = {};
|
|
||||||
|
|
||||||
function existsCached(path) {
|
|
||||||
var exists = existsCache[path];
|
|
||||||
if (exists === undefined) {
|
|
||||||
exists = fs.existsSync(path);
|
|
||||||
existsCache = exists;
|
|
||||||
}
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
function tryDir(dirname, discovered) {
|
|
||||||
var taglibPath = nodePath.join(dirname, 'raptor-taglib.json');
|
|
||||||
if (existsCached(taglibPath)) {
|
|
||||||
var taglib = taglibLoader.load(taglibPath);
|
|
||||||
|
|
||||||
discovered.push(taglib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function tryNodeModules(parent, discovered) {
|
|
||||||
if (nodePath.basename(parent) === 'node_modules') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodeModulesDir = nodePath.join(parent, 'node_modules');
|
|
||||||
if (existsCached(nodeModulesDir)) {
|
|
||||||
var file = new File(nodeModulesDir);
|
|
||||||
var children = file.listFiles();
|
|
||||||
children.forEach(function(moduleDir) {
|
|
||||||
if (moduleDir.isDirectory()) {
|
|
||||||
var taglibPath = nodePath.join(moduleDir.getAbsolutePath(), 'raptor-taglib.json');
|
|
||||||
if (existsCached(taglibPath)) {
|
|
||||||
var taglib = taglibLoader.load(taglibPath);
|
|
||||||
taglib.moduleName = moduleDir.getName();
|
|
||||||
discovered.push(taglib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function discoverHelper(dirname, discovered) {
|
|
||||||
tryDir(dirname, discovered);
|
|
||||||
tryNodeModules(dirname, discovered);
|
|
||||||
|
|
||||||
var parent = nodePath.dirname(dirname);
|
|
||||||
if (parent && parent !== dirname) {
|
|
||||||
discoverHelper(parent, discovered);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function discover(dirname) {
|
|
||||||
|
|
||||||
var discovered = discoverCache[dirname];
|
|
||||||
if (discovered) {
|
|
||||||
return discovered;
|
|
||||||
}
|
|
||||||
|
|
||||||
discovered = [];
|
|
||||||
|
|
||||||
discoverHelper(dirname, discovered);
|
|
||||||
|
|
||||||
discovered = discovered.concat(exports.coreTaglibs);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
discoverCache[dirname] = discovered;
|
|
||||||
|
|
||||||
return discovered;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildLookup(dirname) {
|
|
||||||
var taglibs = discover(dirname);
|
|
||||||
|
|
||||||
var lookupCacheKey = taglibs
|
|
||||||
.map(function(taglib) {
|
|
||||||
return taglib.id;
|
|
||||||
})
|
|
||||||
.join(',');
|
|
||||||
|
|
||||||
var lookup = lookupCache[lookupCacheKey];
|
|
||||||
if (lookup === undefined) {
|
|
||||||
lookup = new TaglibLookup();
|
|
||||||
|
|
||||||
for (var i=taglibs.length-1; i>=0; i--) {
|
|
||||||
lookup.addTaglib(taglibs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
lookupCache[lookupCacheKey] = lookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCoreTaglib(taglib) {
|
|
||||||
exports.coreTaglibs.push(taglib);
|
|
||||||
}
|
|
||||||
|
|
||||||
addCoreTaglib(taglibLoader.load(nodePath.join(__dirname, '../../taglibs/core/raptor-taglib.json')));
|
|
||||||
addCoreTaglib(taglibLoader.load(nodePath.join(__dirname, '../../taglibs/html/raptor-taglib.json')));
|
|
||||||
addCoreTaglib(taglibLoader.load(nodePath.join(__dirname, '../../taglibs/caching/raptor-taglib.json')));
|
|
||||||
addCoreTaglib(taglibLoader.load(nodePath.join(__dirname, '../../taglibs/layout/raptor-taglib.json')));
|
|
||||||
addCoreTaglib(taglibLoader.load(nodePath.join(__dirname, '../../taglibs/async/raptor-taglib.json')));
|
|
||||||
|
|
||||||
exports.buildLookup = buildLookup;
|
|
||||||
12
package.json
12
package.json
@ -32,18 +32,22 @@
|
|||||||
"raptor-xml": "^0.2.0-beta",
|
"raptor-xml": "^0.2.0-beta",
|
||||||
"raptor-objects": "^0.2.0-beta",
|
"raptor-objects": "^0.2.0-beta",
|
||||||
"raptor-ecma": "^0.2.0-beta",
|
"raptor-ecma": "^0.2.0-beta",
|
||||||
"raptor-files": "^0.2.0-beta",
|
|
||||||
"htmlparser2": "~3.5.1",
|
"htmlparser2": "~3.5.1",
|
||||||
"char-props": "~0.1.5",
|
"char-props": "~0.1.5",
|
||||||
"raptor-promises": "^0.2.0-beta",
|
"raptor-promises": "^0.2.0-beta",
|
||||||
"raptor-args": "^0.1.9-beta",
|
"raptor-args": "^0.1.9-beta",
|
||||||
"minimatch": "^0.2.14",
|
"minimatch": "^0.2.14",
|
||||||
"property-handlers": "^0.2.1-beta"
|
"property-handlers": "^0.2.1-beta",
|
||||||
|
"raptor-taglibs": "^0.2.0-beta",
|
||||||
|
"raptor-taglib-async": "^0.2.0-beta",
|
||||||
|
"raptor-taglib-caching": "^0.2.0-beta",
|
||||||
|
"raptor-taglib-core": "^0.2.0-beta",
|
||||||
|
"raptor-taglib-html": "^0.2.0-beta",
|
||||||
|
"raptor-taglib-layout": "^0.2.0-beta"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "~1.15.1",
|
"mocha": "~1.15.1",
|
||||||
"chai": "~1.8.1",
|
"chai": "~1.8.1"
|
||||||
"raptor-cache": "^0.2.0-beta"
|
|
||||||
},
|
},
|
||||||
"license": "Apache License v2.0",
|
"license": "Apache License v2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@ -77,8 +77,12 @@ module.exports = {
|
|||||||
a: attr,
|
a: attr,
|
||||||
|
|
||||||
as: attrs,
|
as: attrs,
|
||||||
|
l: function(path) {
|
||||||
|
return typeof path === 'string' ? runtime.load(path) : path;
|
||||||
|
},
|
||||||
|
|
||||||
/* Helpers that require a context below: */
|
/* Helpers that require a context below: */
|
||||||
|
|
||||||
t: function (context, handler, props, body, namespacedProps) {
|
t: function (context, handler, props, body, namespacedProps) {
|
||||||
if (!props) {
|
if (!props) {
|
||||||
props = {};
|
props = {};
|
||||||
@ -108,10 +112,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
i: function(context, path, data, require) {
|
i: function(context, path, data) {
|
||||||
if (typeof require === 'function') {
|
|
||||||
path = require.resolve(path);
|
|
||||||
}
|
|
||||||
runtime.render(path, data, context);
|
runtime.render(path, data, context);
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -28,6 +28,24 @@ var cache = {};
|
|||||||
|
|
||||||
exports.Context = Context;
|
exports.Context = Context;
|
||||||
|
|
||||||
|
function load(templatePath) {
|
||||||
|
var templateFunc;
|
||||||
|
|
||||||
|
if (typeof templatePath === 'string') {
|
||||||
|
templateFunc = cache[templatePath];
|
||||||
|
if (!templateFunc) {
|
||||||
|
templateFunc = cache[templatePath] = loader(templatePath)(helpers);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Instead of a path, assume we got a compiled template module
|
||||||
|
templateFunc = templatePath._ || (templatePath._ = templatePath(helpers));
|
||||||
|
}
|
||||||
|
|
||||||
|
return templateFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.load = load;
|
||||||
|
|
||||||
exports.render = function (templatePath, data, callback, context) {
|
exports.render = function (templatePath, data, callback, context) {
|
||||||
if (typeof callback !== 'function') {
|
if (typeof callback !== 'function') {
|
||||||
// A context object was provided instead of a callback
|
// A context object was provided instead of a callback
|
||||||
@ -42,20 +60,7 @@ exports.render = function (templatePath, data, callback, context) {
|
|||||||
shouldEnd = true;
|
shouldEnd = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var templateFunc;
|
load(templatePath)(data || {}, context); //Invoke the template rendering function with the required arguments
|
||||||
|
|
||||||
if (typeof templatePath === 'string') {
|
|
||||||
templateFunc = cache[templatePath];
|
|
||||||
if (!templateFunc) {
|
|
||||||
templateFunc = cache[templatePath] = loader(templatePath)(helpers);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Instead of a path, assume we got a compiled template module
|
|
||||||
templateFunc = templatePath._ || (templatePath._ = templatePath(helpers));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
templateFunc(data || {}, context); //Invoke the template rendering function with the required arguments
|
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
context
|
context
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
var varNameRegExp = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
||||||
module.exports = {
|
|
||||||
process: function (node, compiler, template) {
|
|
||||||
var varName = node.getAttribute('var') || node.getAttribute('data-provider') || node.getAttribute('dependency');
|
|
||||||
if (varName) {
|
|
||||||
if (!varNameRegExp.test(varName)) {
|
|
||||||
node.addError('Invalid variable name of "' + varName + '"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
node.addError('Either "var" or "data-provider" is required');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var argProps = [];
|
|
||||||
var propsToRemove = [];
|
|
||||||
node.forEachProperty(function (name, value) {
|
|
||||||
if (name.startsWith('arg-')) {
|
|
||||||
var argName = name.substring('arg-'.length);
|
|
||||||
argProps.push(JSON.stringify(argName) + ': ' + value);
|
|
||||||
propsToRemove.push(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
propsToRemove.forEach(function (propName) {
|
|
||||||
node.removeProperty(propName);
|
|
||||||
});
|
|
||||||
var argString;
|
|
||||||
if (argProps.length) {
|
|
||||||
argString = '{' + argProps.join(', ') + '}';
|
|
||||||
}
|
|
||||||
var arg = node.getProperty('arg');
|
|
||||||
if (arg) {
|
|
||||||
var extendFuncName = template.getStaticHelperFunction('extend', 'xt');
|
|
||||||
argString = extendFuncName + '(' + arg + ', ' + argString + ')';
|
|
||||||
}
|
|
||||||
if (argString) {
|
|
||||||
node.setProperty('arg', template.makeExpression(argString));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
var raptorDataProviders = require('raptor-data-providers');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
render: function (input, context) {
|
|
||||||
var dataProvider = input.dataProvider;
|
|
||||||
|
|
||||||
var dataProviders = raptorDataProviders.forContext(context, false /* don't create if missing */);
|
|
||||||
|
|
||||||
var arg = input.arg || {};
|
|
||||||
|
|
||||||
arg.context = context;
|
|
||||||
var asyncContext = context.beginAsync(input.timeout);
|
|
||||||
|
|
||||||
function onError(e) {
|
|
||||||
asyncContext.error(e || 'Async fragment failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderBody(data) {
|
|
||||||
try {
|
|
||||||
if (input.invokeBody) {
|
|
||||||
input.invokeBody(asyncContext, data);
|
|
||||||
}
|
|
||||||
asyncContext.end();
|
|
||||||
} catch (e) {
|
|
||||||
onError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var method = input.method;
|
|
||||||
if (method) {
|
|
||||||
dataProvider = dataProvider[method].bind(dataProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
dataProviders.requestData(dataProvider, arg, function(err, data) {
|
|
||||||
if (err) {
|
|
||||||
return onError(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderBody(data);
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
onError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"dependencies": [
|
|
||||||
{
|
|
||||||
"package": "raptor/render-context/async"
|
|
||||||
},
|
|
||||||
"AsyncFragmentTag.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
{
|
|
||||||
"tags": {
|
|
||||||
"async-fragment": {
|
|
||||||
"renderer": "./async-fragment-tag",
|
|
||||||
"attributes": {
|
|
||||||
"data-provider": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"arg": {
|
|
||||||
"type": "expression",
|
|
||||||
"preserve-name": true
|
|
||||||
},
|
|
||||||
"arg-*": {
|
|
||||||
"pattern": true,
|
|
||||||
"type": "string",
|
|
||||||
"preserve-name": true
|
|
||||||
},
|
|
||||||
"var": {
|
|
||||||
"type": "identifier"
|
|
||||||
},
|
|
||||||
"timeout": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"method": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vars": [
|
|
||||||
"context",
|
|
||||||
{
|
|
||||||
"name-from-attribute": "var OR dependency OR data-provider|keep"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"transformer": "./AsyncFragmentTagTransformer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
var promiseUtil = require('raptor-promises/util');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
render: function (input, context) {
|
|
||||||
var attributes = context.attributes;
|
|
||||||
var cacheProvider = attributes.cacheProvider;
|
|
||||||
var cache;
|
|
||||||
|
|
||||||
var cacheKey = input.cacheKey;
|
|
||||||
if (!cacheKey) {
|
|
||||||
throw new Error('cache-key is required for <caching:cached-fragment>');
|
|
||||||
}
|
|
||||||
if (!cacheProvider) {
|
|
||||||
var raptorCacheModulePath;
|
|
||||||
try {
|
|
||||||
raptorCacheModulePath = require.resolve('raptor-cache');
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
throw new Error('The "raptor-cache" module should be installed as an application-level dependency when using caching tags');
|
|
||||||
}
|
|
||||||
cacheProvider = require(raptorCacheModulePath).getDefaultProvider();
|
|
||||||
}
|
|
||||||
cache = cacheProvider.getCache(input.cacheName);
|
|
||||||
var cachePromise = cache.get(
|
|
||||||
cacheKey,
|
|
||||||
{
|
|
||||||
builder: function() {
|
|
||||||
var result = context.captureString(function () {
|
|
||||||
if (input.invokeBody) {
|
|
||||||
input.invokeBody();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var asyncContext = context.beginAsync();
|
|
||||||
|
|
||||||
promiseUtil.immediateThen(
|
|
||||||
cachePromise,
|
|
||||||
function (result) {
|
|
||||||
asyncContext.end(result);
|
|
||||||
},
|
|
||||||
function (e) {
|
|
||||||
asyncContext.error(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"tags": {
|
|
||||||
"cached-fragment": {
|
|
||||||
"renderer": "./CachedFragmentTag",
|
|
||||||
"attributes": {
|
|
||||||
"cache-key": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"cache-name": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var varNameRegExp = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
||||||
function AssignNode(props) {
|
|
||||||
AssignNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssignNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var varName = this.getProperty('var');
|
|
||||||
var value = this.getProperty('value');
|
|
||||||
if (!varName) {
|
|
||||||
this.addError('"var" attribute is required');
|
|
||||||
} else if (!varNameRegExp.test(varName)) {
|
|
||||||
this.addError('Invalid variable name of "' + varName + '"');
|
|
||||||
varName = null;
|
|
||||||
}
|
|
||||||
if (!value) {
|
|
||||||
this.addError('"value" attribute is required');
|
|
||||||
}
|
|
||||||
if (varName) {
|
|
||||||
template.statement(varName + '=' + value + ';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(AssignNode, require('../../compiler').Node);
|
|
||||||
module.exports = AssignNode;
|
|
||||||
@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var strings = require('raptor-strings');
|
|
||||||
var WhenNode = require('./WhenNode');
|
|
||||||
var OtherwiseNode = require('./OtherwiseNode');
|
|
||||||
function ChooseNode(props) {
|
|
||||||
ChooseNode.$super.call(this);
|
|
||||||
}
|
|
||||||
ChooseNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var otherwiseNode = null;
|
|
||||||
var foundWhenNode = false;
|
|
||||||
var allowedNodes = [];
|
|
||||||
this.forEachChild(function (child) {
|
|
||||||
if (child.isTextNode()) {
|
|
||||||
if (!strings.isEmpty(child.getText())) {
|
|
||||||
this.addError('Static text "' + strings.trim(child.getText()) + '" is not allowed in ' + this.toString() + ' tag.');
|
|
||||||
}
|
|
||||||
} else if (child.getNodeClass() === WhenNode) {
|
|
||||||
if (otherwiseNode) {
|
|
||||||
this.addError(otherwiseNode + ' tag must be last child of tag ' + this + '.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!foundWhenNode) {
|
|
||||||
foundWhenNode = true;
|
|
||||||
child.firstWhen = true;
|
|
||||||
}
|
|
||||||
allowedNodes.push(child);
|
|
||||||
} else if (child.getNodeClass() === OtherwiseNode) {
|
|
||||||
if (otherwiseNode) {
|
|
||||||
this.addError('More than one ' + otherwiseNode + ' tag is not allowed as child of tag ' + this + '.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
otherwiseNode = child;
|
|
||||||
allowedNodes.push(otherwiseNode);
|
|
||||||
} else {
|
|
||||||
this.addError(child + ' tag is not allowed as child of tag ' + this + '.');
|
|
||||||
child.generateCode(template); //Generate the code for the children so that we can still show errors to the user for nested nodes
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
allowedNodes.forEach(function (child, i) {
|
|
||||||
child.hasElse = i < allowedNodes.length - 1;
|
|
||||||
child.generateCode(template);
|
|
||||||
});
|
|
||||||
if (!foundWhenNode) {
|
|
||||||
this.addError('' + otherwiseNode + ' tag is required to have at least one sibling <c:when> tag.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(ChooseNode, require('../../compiler').Node);
|
|
||||||
module.exports = ChooseNode;
|
|
||||||
@ -1,346 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function removeDashes(str) {
|
|
||||||
return str.replace(/-([a-z])/g, function (match, lower) {
|
|
||||||
return lower.toUpperCase();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var extend = require('raptor-util').extend;
|
|
||||||
|
|
||||||
var WriteNode = require('./WriteNode');
|
|
||||||
var ForNode = require('./ForNode');
|
|
||||||
var IfNode = require('./IfNode');
|
|
||||||
var ElseIfNode = require('./ElseIfNode');
|
|
||||||
var ElseNode = require('./ElseNode');
|
|
||||||
var WithNode = require('./WithNode');
|
|
||||||
var WhenNode = require('./WhenNode');
|
|
||||||
var OtherwiseNode = require('./OtherwiseNode');
|
|
||||||
var TagHandlerNode = require('./TagHandlerNode');
|
|
||||||
var IncludeNode = require('./IncludeNode');
|
|
||||||
var Expression = require('../../compiler').Expression;
|
|
||||||
var AttributeSplitter = require('../../compiler').AttributeSplitter;
|
|
||||||
var TypeConverter = require('../../compiler').TypeConverter;
|
|
||||||
var EscapeXmlContext = require('../../compiler').EscapeXmlContext;
|
|
||||||
var resolver = require('raptor-modules/resolver');
|
|
||||||
|
|
||||||
function getPropValue(value, type, allowExpressions) {
|
|
||||||
return TypeConverter.convert(value, type, allowExpressions);
|
|
||||||
}
|
|
||||||
|
|
||||||
function CoreTagTransformer() {
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreTagTransformer.prototype = {
|
|
||||||
process: function (node, compiler, template) {
|
|
||||||
//Find and handle nested <c:attrs> elements
|
|
||||||
this.findNestedAttrs(node, compiler, template);
|
|
||||||
var inputAttr;
|
|
||||||
var forEachNode;
|
|
||||||
var tag;
|
|
||||||
|
|
||||||
function forEachProp(callback, thisObj) {
|
|
||||||
var foundProps = {};
|
|
||||||
|
|
||||||
node.forEachAttributeAnyNS(function (attr) {
|
|
||||||
var attrDef = compiler.taglibs.getAttribute(node, attr);
|
|
||||||
var type = attrDef ? attrDef.type || 'string' : 'string';
|
|
||||||
|
|
||||||
var value;
|
|
||||||
|
|
||||||
if (!attrDef) {
|
|
||||||
// var isAttrForTaglib = compiler.taglibs.isTaglib(attrUri);
|
|
||||||
//Tag doesn't allow dynamic attributes
|
|
||||||
node.addError('The tag "' + tag.name + '" in taglib "' + tag.taglibId + '" does not support attribute "' + attr + '"');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr.value instanceof Expression) {
|
|
||||||
value = attr.value;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
value = getPropValue(attr.value, type, attrDef ? attrDef.allowExpressions !== false : true);
|
|
||||||
} catch (e) {
|
|
||||||
node.addError('Invalid attribute value of "' + attr.value + '" for attribute "' + attr.name + '": ' + e.message);
|
|
||||||
value = attr.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
var propName;
|
|
||||||
if (attrDef.dynamicAttribute) {
|
|
||||||
propName = attr.qName;
|
|
||||||
} else {
|
|
||||||
if (attrDef.targetProperty) {
|
|
||||||
propName = attrDef.targetProperty;
|
|
||||||
} else if (attrDef.preserveName) {
|
|
||||||
propName = attr.localName;
|
|
||||||
} else {
|
|
||||||
propName = removeDashes(attr.localName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foundProps[propName] = true;
|
|
||||||
callback.call(thisObj, propName, value, attrDef);
|
|
||||||
});
|
|
||||||
|
|
||||||
tag.forEachAttribute(function (attr) {
|
|
||||||
if (attr.hasOwnProperty('defaultValue') && !foundProps[attr.name]) {
|
|
||||||
callback.call(thisObj, attr.name, template.makeExpression(JSON.stringify(attr.defaultValue)), '', attr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tag = node.tag || compiler.taglibs.getTag(node);
|
|
||||||
|
|
||||||
var coreAttrHandlers = {
|
|
||||||
'c-space': function(attr) {
|
|
||||||
this['c-whitespace'](attr);
|
|
||||||
},
|
|
||||||
'c-whitespace': function(attr) {
|
|
||||||
if (attr.value === 'preserve') {
|
|
||||||
node.setPreserveWhitespace(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'c-escape-xml': function(attr) {
|
|
||||||
node.setEscapeXmlBodyText(attr.value !== 'false');
|
|
||||||
},
|
|
||||||
'c-parse-body-text': function(attr) {
|
|
||||||
node.parseBodyText = attr.value !== 'false';
|
|
||||||
},
|
|
||||||
'c-when': function(attr) {
|
|
||||||
var whenNode = new WhenNode({
|
|
||||||
test: new Expression(attr.value),
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
node.parentNode.replaceChild(whenNode, node);
|
|
||||||
whenNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-otherwise': function(attr) {
|
|
||||||
var otherwiseNode = new OtherwiseNode({ pos: node.getPosition() });
|
|
||||||
node.parentNode.replaceChild(otherwiseNode, node);
|
|
||||||
otherwiseNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-attrs': function(attr) {
|
|
||||||
node.dynamicAttributesExpression = attr.value;
|
|
||||||
},
|
|
||||||
'c-for-each': function(attr) {
|
|
||||||
this['for'](attr);
|
|
||||||
},
|
|
||||||
'c-for': function(attr) {
|
|
||||||
var forEachProps = AttributeSplitter.parse(attr.value, {
|
|
||||||
each: { type: 'custom' },
|
|
||||||
separator: { type: 'expression' },
|
|
||||||
'iterator': { type: 'expression' },
|
|
||||||
'status-var': { type: 'identifier' },
|
|
||||||
'for-loop': {
|
|
||||||
type: 'boolean',
|
|
||||||
allowExpressions: false
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
removeDashes: true,
|
|
||||||
defaultName: 'each',
|
|
||||||
errorHandler: function (message) {
|
|
||||||
node.addError('Invalid c:for attribute of "' + attr.value + '". Error: ' + message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
forEachProps.pos = node.getPosition();
|
|
||||||
//Copy the position property
|
|
||||||
forEachNode = new ForNode(forEachProps);
|
|
||||||
//Surround the existing node with an "forEach" node by replacing the current
|
|
||||||
//node with the new "forEach" node and then adding the current node as a child
|
|
||||||
node.parentNode.replaceChild(forEachNode, node);
|
|
||||||
forEachNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-if': function(attr) {
|
|
||||||
var ifNode = new IfNode({
|
|
||||||
test: new Expression(attr.value),
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
//Surround the existing node with an "if" node by replacing the current
|
|
||||||
//node with the new "if" node and then adding the current node as a child
|
|
||||||
node.parentNode.replaceChild(ifNode, node);
|
|
||||||
ifNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-else-if': function(attr) {
|
|
||||||
var elseIfNode = new ElseIfNode({
|
|
||||||
test: new Expression(attr.value),
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
//Surround the existing node with an "if" node by replacing the current
|
|
||||||
//node with the new "if" node and then adding the current node as a child
|
|
||||||
node.parentNode.replaceChild(elseIfNode, node);
|
|
||||||
elseIfNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-else': function(attr) {
|
|
||||||
var elseNode = new ElseNode({ pos: node.getPosition() });
|
|
||||||
//Surround the existing node with an "if" node by replacing the current
|
|
||||||
//node with the new "if" node and then adding the current node as a child
|
|
||||||
node.parentNode.replaceChild(elseNode, node);
|
|
||||||
elseNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-with': function(attr) {
|
|
||||||
var withNode = new WithNode({
|
|
||||||
vars: attr.value,
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
node.parentNode.replaceChild(withNode, node);
|
|
||||||
withNode.appendChild(node);
|
|
||||||
},
|
|
||||||
'c-body-content': function(attr) {
|
|
||||||
this.content(attr);
|
|
||||||
},
|
|
||||||
'c-content': function(attr) {
|
|
||||||
var newChild = new WriteNode({
|
|
||||||
expression: attr.value,
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
node.removeChildren();
|
|
||||||
node.appendChild(newChild);
|
|
||||||
},
|
|
||||||
'c-trim-body-indent': function(attr) {
|
|
||||||
if (attr.value === 'true') {
|
|
||||||
node.trimBodyIndent = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'c-strip': function(attr) {
|
|
||||||
if (!node.setStripExpression) {
|
|
||||||
node.addError('The c:strip directive is not allowed for target node');
|
|
||||||
}
|
|
||||||
node.setStripExpression(attr.value);
|
|
||||||
},
|
|
||||||
'c-replace': function(attr) {
|
|
||||||
var replaceWriteNode = new WriteNode({
|
|
||||||
expression: attr.value,
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
//Replace the existing node with an node that only has children
|
|
||||||
node.parentNode.replaceChild(replaceWriteNode, node);
|
|
||||||
node = replaceWriteNode;
|
|
||||||
},
|
|
||||||
'c-input': function(attr) {
|
|
||||||
inputAttr = attr.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
node.forEachAttributeNS('', function(attr) {
|
|
||||||
|
|
||||||
var handler = coreAttrHandlers[attr.qName];
|
|
||||||
if (handler) {
|
|
||||||
node.removeAttribute(attr.localName);
|
|
||||||
coreAttrHandlers[attr.localName](attr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (tag) {
|
|
||||||
if (tag.preserveWhitespace) {
|
|
||||||
node.setPreserveWhitespace(true);
|
|
||||||
}
|
|
||||||
if (tag.renderer || tag.template) {
|
|
||||||
if (tag.renderer) {
|
|
||||||
//Instead of compiling as a static XML element, we'll
|
|
||||||
//make the node render as a tag handler node so that
|
|
||||||
//writes code that invokes the handler
|
|
||||||
TagHandlerNode.convertNode(node, tag);
|
|
||||||
if (inputAttr) {
|
|
||||||
node.setInputExpression(template.makeExpression(inputAttr));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var templatePath = resolver.deresolve(tag.template, compiler.dirname);
|
|
||||||
// The tag is mapped to a template that will be used to perform
|
|
||||||
// the rendering so convert the node into a "IncludeNode" that can
|
|
||||||
// be used to include the output of rendering a template
|
|
||||||
IncludeNode.convertNode(node, templatePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
forEachProp(function (name, value, attrDef) {
|
|
||||||
if (attrDef.dynamicAttribute && attrDef.targetProperty) {
|
|
||||||
if (attrDef.removeDashes === true) {
|
|
||||||
name = removeDashes(name);
|
|
||||||
}
|
|
||||||
node.addDynamicAttribute(name, value);
|
|
||||||
node.setDynamicAttributesProperty(attrDef.targetProperty);
|
|
||||||
} else {
|
|
||||||
node.setProperty(name, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} else if (tag.nodeClass) {
|
|
||||||
var NodeCompilerClass = require(tag.nodeClass);
|
|
||||||
extend(node, NodeCompilerClass.prototype);
|
|
||||||
NodeCompilerClass.call(node);
|
|
||||||
node.setNodeClass(NodeCompilerClass);
|
|
||||||
forEachProp(function (name, value) {
|
|
||||||
node.setProperty(name, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
findNestedAttrs: function (node, compiler, template) {
|
|
||||||
node.forEachChild(function (child) {
|
|
||||||
if (child.qName === 'c-attr') {
|
|
||||||
this.handleAttr(child, compiler, template);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
handleAttr: function (node, compiler, template) {
|
|
||||||
var parentNode = node.parentNode;
|
|
||||||
if (!parentNode.isElementNode()) {
|
|
||||||
node.addError(this.toString() + ' tag is not nested within an element tag.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var hasValue = node.hasAttribute('value');
|
|
||||||
var attrName = node.getAttribute('name');
|
|
||||||
var attrValue = node.getAttribute('value');
|
|
||||||
var attrUri = node.getAttribute('namespace') || '';
|
|
||||||
var attrPrefix = node.getAttribute('prefix') || '';
|
|
||||||
if (parentNode.hasAttributeNS(attrUri, attrName)) {
|
|
||||||
node.addError(node.toString() + ' tag adds duplicate attribute with name "' + attrName + '"' + (attrUri ? ' and URI "' + attrUri + '"' : ''));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
node.removeAttribute('name');
|
|
||||||
node.removeAttribute('value');
|
|
||||||
node.removeAttribute('namespace');
|
|
||||||
node.removeAttribute('prefix');
|
|
||||||
if (node.hasAttributesAnyNS()) {
|
|
||||||
var invalidAttrs = node.getAllAttributes().map(function (attr) {
|
|
||||||
return attr.qName;
|
|
||||||
});
|
|
||||||
node.addError('Invalid attributes for tag ' + node.toString() + ': ' + invalidAttrs.join(', '));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//Cleanup whitespace between <c:attr> tags
|
|
||||||
if (node.previousSibling && node.previousSibling.isTextNode() && node.previousSibling.getText().trim() === '') {
|
|
||||||
node.previousSibling.detach();
|
|
||||||
}
|
|
||||||
if (node.nextSibling && node.nextSibling.isTextNode() && node.nextSibling.getText().trim() === '') {
|
|
||||||
node.nextSibling.detach();
|
|
||||||
}
|
|
||||||
if (node.nextSibling && node.nextSibling.isTextNode()) {
|
|
||||||
node.nextSibling.setText(node.nextSibling.getText().replace(/^\n\s*/, ''));
|
|
||||||
}
|
|
||||||
node.detach();
|
|
||||||
//Remove the node out of the tree
|
|
||||||
compiler.transformTree(node, template);
|
|
||||||
if (hasValue) {
|
|
||||||
parentNode.setAttributeNS(attrUri, attrName, attrValue, attrPrefix);
|
|
||||||
} else {
|
|
||||||
node.setEscapeXmlContext(EscapeXmlContext.Attribute);
|
|
||||||
//Escape body text and expressions as attributes
|
|
||||||
parentNode.setAttributeNS(attrUri, attrName, node.getBodyContentExpression(template), attrPrefix, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
module.exports = CoreTagTransformer;
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var ExpressionParser = require('../../compiler').ExpressionParser;
|
|
||||||
var TextNode = require('../../compiler').TextNode;
|
|
||||||
var WriteNode = require('./WriteNode');
|
|
||||||
var ScriptletNode = require('./ScriptletNode');
|
|
||||||
function CoreTextTransformer() {
|
|
||||||
}
|
|
||||||
CoreTextTransformer.prototype = {
|
|
||||||
process: function (node, compiler) {
|
|
||||||
if (node.parentNode && node.parentNode.parseBodyText === false) {
|
|
||||||
return; //Don't try to parse expressions
|
|
||||||
}
|
|
||||||
var parts = [];
|
|
||||||
ExpressionParser.parse(node.text, {
|
|
||||||
text: function (text, escapeXml) {
|
|
||||||
parts.push({
|
|
||||||
text: text,
|
|
||||||
escapeXml: escapeXml
|
|
||||||
});
|
|
||||||
},
|
|
||||||
expression: function (expression, escapeXml) {
|
|
||||||
parts.push({
|
|
||||||
expression: expression,
|
|
||||||
escapeXml: escapeXml
|
|
||||||
});
|
|
||||||
},
|
|
||||||
scriptlet: function (scriptlet) {
|
|
||||||
parts.push({ scriptlet: scriptlet });
|
|
||||||
},
|
|
||||||
error: function (message) {
|
|
||||||
node.addError(message);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
if (parts.length > 0) {
|
|
||||||
var startIndex = 0;
|
|
||||||
if (parts[0].text) {
|
|
||||||
node.setText(parts[0].text);
|
|
||||||
//Update this text node to match first text part and we'll add the remaining
|
|
||||||
node.setEscapeXml(parts[0].escapeXml !== false);
|
|
||||||
startIndex = 1;
|
|
||||||
} else {
|
|
||||||
node.text = '';
|
|
||||||
//The first part is an expression so we'll just zero out this text node
|
|
||||||
startIndex = 0;
|
|
||||||
}
|
|
||||||
var newNodes = [];
|
|
||||||
for (var i = startIndex, part, newNode; i < parts.length; i++) {
|
|
||||||
part = parts[i];
|
|
||||||
newNode = null;
|
|
||||||
if (part.hasOwnProperty('text')) {
|
|
||||||
newNode = new TextNode(part.text, part.escapeXml !== false);
|
|
||||||
newNode.setTransformerApplied(this); //We shouldn't reprocess the new text node
|
|
||||||
} else if (part.hasOwnProperty('expression')) {
|
|
||||||
newNode = new WriteNode({
|
|
||||||
expression: part.expression,
|
|
||||||
escapeXml: part.escapeXml !== false
|
|
||||||
});
|
|
||||||
} else if (part.hasOwnProperty('scriptlet')) {
|
|
||||||
newNode = new ScriptletNode(part.scriptlet);
|
|
||||||
}
|
|
||||||
if (newNode) {
|
|
||||||
newNode.setPosition(node.getPosition());
|
|
||||||
newNodes.push(newNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newNodes.length) {
|
|
||||||
node.parentNode.insertAfter(newNodes, node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
module.exports = CoreTextTransformer;
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var strings = require('raptor-strings');
|
|
||||||
var funcDefRegExp = /^([A-Za-z_][A-Za-z0-9_]*)(?:\(((?:[A-Za-z_][A-Za-z0-9_]*,\s*)*[A-Za-z_][A-Za-z0-9_]*)?\))?$/;
|
|
||||||
function DefNode(props) {
|
|
||||||
DefNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var func = this.getProperty('function');
|
|
||||||
if (!func) {
|
|
||||||
this.addError('"function" attribute is required');
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
func = strings.trim(func);
|
|
||||||
var matches = funcDefRegExp.exec(func);
|
|
||||||
if (matches) {
|
|
||||||
var name = matches[1];
|
|
||||||
var params = matches[2] ? matches[2].split(/\s*,\s*/) : [];
|
|
||||||
var definedFunctions = template.getAttribute('core:definedFunctions');
|
|
||||||
if (!definedFunctions) {
|
|
||||||
definedFunctions = template.setAttribute('core:definedFunctions', {});
|
|
||||||
}
|
|
||||||
definedFunctions[name] = {
|
|
||||||
params: params,
|
|
||||||
bodyParam: this.getProperty('bodyParam')
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
this.addError('Invalid function name of "' + func + '"');
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (func.indexOf('(') === -1) {
|
|
||||||
func += '()';
|
|
||||||
}
|
|
||||||
|
|
||||||
template.statement('function ' + func + ' {').indent(function () {
|
|
||||||
template.line('return __helpers.c(context, function() {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('});');
|
|
||||||
}, this).line('}');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(DefNode, require('../../compiler').Node);
|
|
||||||
module.exports = DefNode;
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function ElseIfNode(props) {
|
|
||||||
ElseIfNode.$super.call(this, 'c-else-if');
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ElseIfNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var test = this.getProperty('test');
|
|
||||||
if (!test) {
|
|
||||||
this.addError('"test" attribute is required');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
template.line('else if (' + test + ') {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(ElseIfNode, require('../../compiler').ElementNode);
|
|
||||||
module.exports = ElseIfNode;
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function ElseNode(props) {
|
|
||||||
ElseNode.$super.call(this, 'c-else');
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ElseNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
if (this.valid == null) {
|
|
||||||
return; //Don't generate code for an invalid else
|
|
||||||
}
|
|
||||||
template.line('else {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(ElseNode, require('../../compiler').ElementNode);
|
|
||||||
module.exports = ElseNode;
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var strings = require('raptor-strings');
|
|
||||||
function ElseTagTransformer() {
|
|
||||||
}
|
|
||||||
ElseTagTransformer.prototype = {
|
|
||||||
process: function (node, compiler) {
|
|
||||||
var curNode = node.previousSibling;
|
|
||||||
var matchingNode;
|
|
||||||
var IfNode = compiler.getNodeClass('c-if');
|
|
||||||
var ElseIfNode = compiler.getNodeClass('c-else-if');
|
|
||||||
var whitespaceNodes = [];
|
|
||||||
while (curNode) {
|
|
||||||
if (curNode.getNodeClass() === ElseIfNode || curNode.getNodeClass() === IfNode) {
|
|
||||||
matchingNode = curNode;
|
|
||||||
break;
|
|
||||||
} else if (curNode.isTextNode()) {
|
|
||||||
if (!strings.isEmpty(curNode.getText())) {
|
|
||||||
node.addError('Static text "' + strings.trim(curNode.getText()) + '" is not allowed before ' + node.toString() + ' tag.');
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
whitespaceNodes.push(curNode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
node.addError(curNode + ' is not allowed before ' + node.toString() + ' tag.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
curNode = curNode.previousSibling;
|
|
||||||
}
|
|
||||||
if (!matchingNode) {
|
|
||||||
node.addError('<c-if> or <c-else-if> node not found immediately before ' + node.toString() + ' tag.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
whitespaceNodes.forEach(function (whitespaceNode) {
|
|
||||||
whitespaceNode.parentNode.removeChild(whitespaceNode);
|
|
||||||
});
|
|
||||||
matchingNode.hasElse = true;
|
|
||||||
node.valid = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
module.exports = ElseTagTransformer;
|
|
||||||
@ -1,142 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var forEachRegEx = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s+in\s+(.+)$/;
|
|
||||||
var forEachPropRegEx = /^\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*,\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)\s+in\s+(.+)$/;
|
|
||||||
var stringify = require('raptor-json/stringify').stringify;
|
|
||||||
function parseForEach(value) {
|
|
||||||
var match = value.match(forEachRegEx);
|
|
||||||
if (match) {
|
|
||||||
return {
|
|
||||||
'var': match[1],
|
|
||||||
'in': match[2]
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
match = value.match(forEachPropRegEx);
|
|
||||||
if (!match) {
|
|
||||||
throw new Error('Invalid each attribute of "' + value + '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'nameVar': match[1],
|
|
||||||
'valueVar': match[2],
|
|
||||||
'in': match[3]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function ForNode(props) {
|
|
||||||
ForNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ForNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var each = this.getProperty('each');
|
|
||||||
var separator = this.getProperty('separator');
|
|
||||||
var statusVar = this.getProperty('statusVar') || this.getProperty('varStatus');
|
|
||||||
var customIterator = this.getProperty('iterator');
|
|
||||||
if (!each) {
|
|
||||||
this.addError('"each" attribute is required');
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var parts;
|
|
||||||
try {
|
|
||||||
parts = parseForEach(each);
|
|
||||||
} catch (e) {
|
|
||||||
this.addError(e.message);
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var items = template.makeExpression(parts['in']);
|
|
||||||
var varName = parts['var'];
|
|
||||||
var nameVarName = parts.nameVar;
|
|
||||||
var valueVarName = parts.valueVar;
|
|
||||||
if (nameVarName) {
|
|
||||||
if (separator) {
|
|
||||||
this.addError('Separator is not supported when looping over properties');
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (statusVar) {
|
|
||||||
this.addError('Loop status variable not supported when looping over properties');
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (separator && !statusVar) {
|
|
||||||
statusVar = '__loop';
|
|
||||||
}
|
|
||||||
var funcName;
|
|
||||||
var forEachParams;
|
|
||||||
if (customIterator) {
|
|
||||||
var statusVarFlag = '';
|
|
||||||
if (statusVar) {
|
|
||||||
statusVarFlag = ', true';
|
|
||||||
forEachParams = [
|
|
||||||
varName,
|
|
||||||
statusVar
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
forEachParams = [varName];
|
|
||||||
}
|
|
||||||
template.statement(customIterator + '(' + items + ', function(' + forEachParams.join(',') + ') {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}' + statusVarFlag + ');');
|
|
||||||
} else if (statusVar) {
|
|
||||||
forEachParams = [
|
|
||||||
varName,
|
|
||||||
statusVar
|
|
||||||
];
|
|
||||||
funcName = template.getStaticHelperFunction('forEachWithStatusVar', 'fv');
|
|
||||||
template.statement(funcName + '(' + items + ', function(' + forEachParams.join(',') + ') {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
if (separator) {
|
|
||||||
template.statement('if (!' + statusVar + '.isLast()) {').indent(function () {
|
|
||||||
template.write(template.isExpression(separator) ? separator.getExpression() : stringify(separator));
|
|
||||||
}, this).line('}');
|
|
||||||
}
|
|
||||||
}, this).line('});');
|
|
||||||
} else {
|
|
||||||
if (this.getProperty('forLoop') === true) {
|
|
||||||
forEachParams = [
|
|
||||||
'__array',
|
|
||||||
'__index',
|
|
||||||
'__length',
|
|
||||||
varName
|
|
||||||
];
|
|
||||||
template.statement(template.getStaticHelperFunction('forLoop', 'fl') + '(' + items + ', function(' + forEachParams.join(',') + ') {').indent(function () {
|
|
||||||
template.statement('for (;__index<__length;__index++) {').indent(function () {
|
|
||||||
template.statement(varName + '=__array[__index];');
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}');
|
|
||||||
}, this).line('});');
|
|
||||||
} else {
|
|
||||||
forEachParams = nameVarName ? [
|
|
||||||
nameVarName,
|
|
||||||
valueVarName
|
|
||||||
] : [varName];
|
|
||||||
funcName = nameVarName ? template.getStaticHelperFunction('forEachProp', 'fp') : template.getStaticHelperFunction('forEach', 'f');
|
|
||||||
template.statement(funcName + '(' + items + ', function(' + forEachParams.join(',') + ') {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('});');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(ForNode, require('../../compiler').Node);
|
|
||||||
module.exports = ForNode;
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function IfNode(props) {
|
|
||||||
IfNode.$super.call(this, 'c-if');
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IfNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var test = this.getProperty('test');
|
|
||||||
if (!test) {
|
|
||||||
this.addError('"test" attribute is required');
|
|
||||||
}
|
|
||||||
template.statement('if (' + test + ') {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(IfNode, require('../../compiler').ElementNode);
|
|
||||||
module.exports = IfNode;
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var stringify = require('raptor-json/stringify');
|
|
||||||
var nodePath = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
|
|
||||||
var extend = require('raptor-util').extend;
|
|
||||||
function IncludeNode(props) {
|
|
||||||
IncludeNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IncludeNode.convertNode = function (node, template) {
|
|
||||||
extend(node, IncludeNode.prototype);
|
|
||||||
IncludeNode.call(node);
|
|
||||||
node.setProperty('template', stringify(template));
|
|
||||||
};
|
|
||||||
IncludeNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var templatePath = this.getProperty('template');
|
|
||||||
var templateData = this.getProperty('templateData') || this.getProperty('template-data');
|
|
||||||
var resourcePath;
|
|
||||||
var _this = this;
|
|
||||||
|
|
||||||
if (templatePath) {
|
|
||||||
this.removeProperty('template');
|
|
||||||
|
|
||||||
var dataExpression;
|
|
||||||
if (templateData) {
|
|
||||||
dataExpression = templateData;
|
|
||||||
} else {
|
|
||||||
dataExpression = {
|
|
||||||
toString: function () {
|
|
||||||
var propParts = [];
|
|
||||||
|
|
||||||
_this.forEachProperty(function (name, value) {
|
|
||||||
name = name.replace(/-([a-z])/g, function (match, lower) {
|
|
||||||
return lower.toUpperCase();
|
|
||||||
});
|
|
||||||
propParts.push(stringify(name) + ': ' + value);
|
|
||||||
}, _this);
|
|
||||||
|
|
||||||
if (_this.hasChildren()) {
|
|
||||||
propParts.push(stringify('invokeBody') + ': ' + _this.getBodyContentFunctionExpression(template, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
return '{' + propParts.join(', ') + '}';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
template.include(templatePath, dataExpression);
|
|
||||||
} else if ((resourcePath = this.getAttribute('resource'))) {
|
|
||||||
var isStatic = this.getProperty('static') !== false;
|
|
||||||
if (isStatic) {
|
|
||||||
resourcePath = nodePath.resolve(template.dirname, resourcePath);
|
|
||||||
if (!fs.existsSync(resourcePath)) {
|
|
||||||
this.addError('Resource not found: ' + resourcePath);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
template.write(stringify(fs.readFileSync(resourcePath, {encoding: 'utf8'})));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.addError('"template" or "resource" attribute is required');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(IncludeNode, require('../../compiler').Node);
|
|
||||||
module.exports = IncludeNode;
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var forEach = require('raptor-util').forEach;
|
|
||||||
function InvokeNode(props) {
|
|
||||||
InvokeNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InvokeNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var func = this.getProperty('function');
|
|
||||||
var funcDef;
|
|
||||||
var bodyParam;
|
|
||||||
var definedFunctions = template.getAttribute('core:definedFunctions');
|
|
||||||
if (!func) {
|
|
||||||
this.addError('"function" attribute is required');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (func.indexOf('(') === -1) {
|
|
||||||
funcDef = definedFunctions ? definedFunctions[func] : null;
|
|
||||||
var argParts = [];
|
|
||||||
var validParamsLookup = {};
|
|
||||||
var params = [];
|
|
||||||
if (funcDef) {
|
|
||||||
params = funcDef.params || [];
|
|
||||||
bodyParam = funcDef.bodyParam;
|
|
||||||
/*
|
|
||||||
* Loop over the defined parameters to figure out the names of allowed parameters and add them to a lookup
|
|
||||||
*/
|
|
||||||
forEach(params, function (param) {
|
|
||||||
validParamsLookup[param] = true;
|
|
||||||
}, this);
|
|
||||||
}
|
|
||||||
var bodyArg = null;
|
|
||||||
if (this.hasChildren()) {
|
|
||||||
if (!funcDef || !funcDef.bodyParam) {
|
|
||||||
this.addError('Nested content provided when invoking macro "' + func + '" but defined macro does not support nested content.');
|
|
||||||
} else {
|
|
||||||
bodyArg = this.getBodyContentExpression(template, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* VALIDATION:
|
|
||||||
* Loop over all of the provided attributes and make sure they are allowed
|
|
||||||
*/
|
|
||||||
this.forEachProperty(function (name, value) {
|
|
||||||
if (name === 'function') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!validParamsLookup[name]) {
|
|
||||||
this.addError('Parameter with name "' + name + '" not supported for function with name "' + func + '". Allowed parameters: ' + params.join(', '));
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
/*
|
|
||||||
* One more pass to build the argument list
|
|
||||||
*/
|
|
||||||
forEach(params, function (param) {
|
|
||||||
validParamsLookup[param] = true;
|
|
||||||
if (param === bodyParam) {
|
|
||||||
argParts.push(bodyArg ? bodyArg : 'undefined');
|
|
||||||
} else {
|
|
||||||
var arg = this.getAttribute(param);
|
|
||||||
if (arg == null) {
|
|
||||||
argParts.push('undefined');
|
|
||||||
} else {
|
|
||||||
argParts.push(this.getProperty(param));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
template.write(func + '(' + argParts.join(',') + ')');
|
|
||||||
} else {
|
|
||||||
var funcName = func.substring(0, func.indexOf('('));
|
|
||||||
funcDef = definedFunctions ? definedFunctions[funcName] : null;
|
|
||||||
if (funcDef) {
|
|
||||||
template.write(func);
|
|
||||||
} else {
|
|
||||||
template.statement(func + ';\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(InvokeNode, require('../../compiler').Node);
|
|
||||||
module.exports = InvokeNode;
|
|
||||||
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function OtherwiseNode(props) {
|
|
||||||
OtherwiseNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OtherwiseNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
template.line('else {').indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}');
|
|
||||||
},
|
|
||||||
toString: function () {
|
|
||||||
return '<c:otherwise>';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(OtherwiseNode, require('../../compiler').Node);
|
|
||||||
module.exports = OtherwiseNode;
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var varNameRegExp = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
||||||
function RequireNode(props) {
|
|
||||||
RequireNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RequireNode.prototype = {
|
|
||||||
javaScriptOnly: true,
|
|
||||||
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var module = this.getProperty('module');
|
|
||||||
var varName = this.getProperty('var');
|
|
||||||
|
|
||||||
if (!module) {
|
|
||||||
this.addError('"module" attribute is required');
|
|
||||||
}
|
|
||||||
if (!varName) {
|
|
||||||
this.addError('"varName" attribute is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module && varName) {
|
|
||||||
template.addStaticVar(varName, 'require(' + module + ')');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(RequireNode, require('../../compiler').Node);
|
|
||||||
module.exports = RequireNode;
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function ScriptletNode(code) {
|
|
||||||
ScriptletNode.$super.call(this, 'scriptlet');
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
ScriptletNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
if (this.code) {
|
|
||||||
template.code(this.code);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toString: function () {
|
|
||||||
return '{%' + this.code + '%}';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(ScriptletNode, require('../../compiler').Node);
|
|
||||||
module.exports = ScriptletNode;
|
|
||||||
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var objects = require('raptor-objects');
|
|
||||||
var extend = require('raptor-util').extend;
|
|
||||||
var forEachEntry = require('raptor-util').forEachEntry;
|
|
||||||
var stringify = require('raptor-json/stringify');
|
|
||||||
var Expression = require('../../compiler').Expression;
|
|
||||||
var raptorModulesResolver = require('raptor-modules/resolver');
|
|
||||||
|
|
||||||
function addHandlerVar(template, renderer) {
|
|
||||||
var handlerVars = template._handlerVars || (template._handlerVars = {});
|
|
||||||
var handlerVar = handlerVars[renderer];
|
|
||||||
if (!handlerVar) {
|
|
||||||
handlerVars[renderer] = handlerVar = renderer.replace(/[.\-\/]/g, '_').replace(/^[_]+/g, '');
|
|
||||||
template.addStaticVar(handlerVar, 'require(' + stringify(renderer) + ')');
|
|
||||||
}
|
|
||||||
return handlerVar;
|
|
||||||
}
|
|
||||||
function getPropsStr(props, template) {
|
|
||||||
var propsArray = [];
|
|
||||||
if (props) {
|
|
||||||
template.indent(function () {
|
|
||||||
forEachEntry(props, function (name, value) {
|
|
||||||
if (value instanceof Expression) {
|
|
||||||
|
|
||||||
var expressionStr;
|
|
||||||
template.indent(function () {
|
|
||||||
expressionStr = value.expression.toString();
|
|
||||||
});
|
|
||||||
propsArray.push(template.indentStr() + stringify(name) + ': ' + expressionStr);
|
|
||||||
} else if (typeof value === 'string' || typeof value === 'object') {
|
|
||||||
propsArray.push(template.indentStr() + stringify(name) + ': ' + stringify(value));
|
|
||||||
} else {
|
|
||||||
propsArray.push(template.indentStr() + stringify(name) + ': ' + value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
if (propsArray.length) {
|
|
||||||
return '{\n' + propsArray.join(',\n') + '\n' + template.indentStr() + '}';
|
|
||||||
} else {
|
|
||||||
return '{}';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return '{}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function TagHandlerNode(tag) {
|
|
||||||
if (!this.nodeType) {
|
|
||||||
TagHandlerNode.$super.call(this);
|
|
||||||
}
|
|
||||||
this.tag = tag;
|
|
||||||
this.dynamicAttributes = null;
|
|
||||||
this.preInvokeCode = [];
|
|
||||||
this.postInvokeCode = [];
|
|
||||||
this.inputExpression = null;
|
|
||||||
}
|
|
||||||
TagHandlerNode.convertNode = function (node, tag) {
|
|
||||||
extend(node, TagHandlerNode.prototype);
|
|
||||||
TagHandlerNode.call(node, tag);
|
|
||||||
};
|
|
||||||
TagHandlerNode.prototype = {
|
|
||||||
addDynamicAttribute: function (name, value) {
|
|
||||||
if (!this.dynamicAttributes) {
|
|
||||||
this.dynamicAttributes = {};
|
|
||||||
}
|
|
||||||
this.dynamicAttributes[name] = value;
|
|
||||||
},
|
|
||||||
setDynamicAttributesProperty: function(name) {
|
|
||||||
this.dynamicAttributesProperty = name;
|
|
||||||
},
|
|
||||||
addPreInvokeCode: function (code) {
|
|
||||||
this.preInvokeCode.push(code);
|
|
||||||
},
|
|
||||||
addPostInvokeCode: function (code) {
|
|
||||||
this.postInvokeCode.push(code);
|
|
||||||
},
|
|
||||||
setInputExpression: function (expression) {
|
|
||||||
this.inputExpression = expression;
|
|
||||||
},
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var rendererPath = raptorModulesResolver.deresolve(this.tag.renderer, template.dirname);
|
|
||||||
var handlerVar = addHandlerVar(template, rendererPath);
|
|
||||||
|
|
||||||
this.tag.forEachImportedVariable(function (importedVariable) {
|
|
||||||
this.setProperty(importedVariable.targetProperty, new Expression(importedVariable.expression));
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
var _this = this;
|
|
||||||
var variableNames = [];
|
|
||||||
_this.tag.forEachVariable(function (nestedVar) {
|
|
||||||
var varName;
|
|
||||||
if (nestedVar.nameFromAttribute) {
|
|
||||||
var possibleNameAttributes = nestedVar.nameFromAttribute.split(/\s+or\s+|\s*,\s*/i);
|
|
||||||
for (var i = 0, len = possibleNameAttributes.length; i < len; i++) {
|
|
||||||
var attrName = possibleNameAttributes[i];
|
|
||||||
var keep = false;
|
|
||||||
if (attrName.endsWith('|keep')) {
|
|
||||||
keep = true;
|
|
||||||
attrName = attrName.slice(0, 0 - '|keep'.length);
|
|
||||||
possibleNameAttributes[i] = attrName;
|
|
||||||
}
|
|
||||||
varName = this.getAttribute(attrName);
|
|
||||||
if (varName) {
|
|
||||||
if (!keep) {
|
|
||||||
this.removeProperty(attrName);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!varName) {
|
|
||||||
this.addError('Attribute ' + possibleNameAttributes.join(' or ') + ' is required');
|
|
||||||
varName = '_var'; // Let it continue with errors
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
varName = nestedVar.name;
|
|
||||||
if (!varName) {
|
|
||||||
this.addError('Variable name is required');
|
|
||||||
varName = '_var'; // Let it continue with errors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
variableNames.push(varName);
|
|
||||||
}, this);
|
|
||||||
if (_this.preInvokeCode.length) {
|
|
||||||
_this.preInvokeCode.forEach(function (code) {
|
|
||||||
template.indent().code(code).code('\n');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template.contextHelperMethodCall('t', function () {
|
|
||||||
template.code('\n').indent(function () {
|
|
||||||
template.line(handlerVar + ',').indent();
|
|
||||||
if (_this.inputExpression) {
|
|
||||||
template.code(_this.inputExpression);
|
|
||||||
} else {
|
|
||||||
if (_this.dynamicAttributes) {
|
|
||||||
template.indent(function() {
|
|
||||||
_this.setProperty(_this.dynamicAttributesProperty, template.makeExpression(getPropsStr(_this.dynamicAttributes, template)));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template.code(getPropsStr(_this.getProperties(), template));
|
|
||||||
}
|
|
||||||
if (_this.hasChildren()) {
|
|
||||||
var bodyParams = [];
|
|
||||||
variableNames.forEach(function (varName) {
|
|
||||||
bodyParams.push(varName);
|
|
||||||
});
|
|
||||||
template.code(',\n').line('function(' + bodyParams.join(',') + ') {').indent(function () {
|
|
||||||
_this.generateCodeForChildren(template);
|
|
||||||
}).indent().code('}');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (_this.postInvokeCode.length) {
|
|
||||||
_this.postInvokeCode.forEach(function (code) {
|
|
||||||
template.indent().code(code).code('\n');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(TagHandlerNode, require('../../compiler').Node);
|
|
||||||
module.exports = TagHandlerNode;
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function TemplateNode(props) {
|
|
||||||
TemplateNode.$super.call(this, 'template', 'core', 'c');
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TemplateNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var params = this.getProperty('params');
|
|
||||||
if (params) {
|
|
||||||
params = params.split(/(?:\s*,\s*)|(?:\s+)/g);
|
|
||||||
params.forEach(function (param) {
|
|
||||||
param = param.trim();
|
|
||||||
if (param.length) {
|
|
||||||
template.addVar(param, 'data.' + param);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
} else {
|
|
||||||
params = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(TemplateNode, require('../../compiler').ElementNode);
|
|
||||||
module.exports = TemplateNode;
|
|
||||||
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var varNameRegExp = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
||||||
function VarNode(props) {
|
|
||||||
VarNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VarNode.prototype = {
|
|
||||||
javaScriptOnly: true,
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var varName = this.getProperty('name');
|
|
||||||
var value = this.getProperty('value') || this.getProperty('string-value');
|
|
||||||
if (!varName) {
|
|
||||||
this.addError('"name" attribute is required');
|
|
||||||
} else if (!varNameRegExp.test(varName)) {
|
|
||||||
this.addError('Invalid variable name of "' + varName + '"');
|
|
||||||
varName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isStatic = this.getProperty('static');
|
|
||||||
|
|
||||||
if (varName) {
|
|
||||||
if (isStatic) {
|
|
||||||
template.addStaticVar(varName, value);
|
|
||||||
} else {
|
|
||||||
template.statement('var ' + varName + (value ? '=' + value : '') + ';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(VarNode, require('../../compiler').Node);
|
|
||||||
module.exports = VarNode;
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
function WhenNode(props) {
|
|
||||||
WhenNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WhenNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var test = this.getProperty('test');
|
|
||||||
if (!test) {
|
|
||||||
this.addError('"test" attribute is required for ' + this.toString() + ' tag.');
|
|
||||||
}
|
|
||||||
var ifCode = 'if (' + test + ')';
|
|
||||||
if (!this.firstWhen) {
|
|
||||||
template.line('else ' + ifCode + ' {');
|
|
||||||
} else {
|
|
||||||
template.statement(ifCode + ' {');
|
|
||||||
}
|
|
||||||
template.indent(function () {
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(WhenNode, require('../../compiler').Node);
|
|
||||||
module.exports = WhenNode;
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var AttributeSplitter = require('../../compiler').AttributeSplitter;
|
|
||||||
var varNameRegExp = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
||||||
function WithNode(props) {
|
|
||||||
WithNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WithNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var vars = this.getProperty('vars');
|
|
||||||
var _this = this;
|
|
||||||
if (!vars) {
|
|
||||||
this.addError('"vars" attribute is required');
|
|
||||||
}
|
|
||||||
var withVars = AttributeSplitter.parse(vars, { '*': { type: 'expression' } }, {
|
|
||||||
ordered: true,
|
|
||||||
errorHandler: function (message) {
|
|
||||||
_this.addError('Invalid variable declarations of "' + vars + '". Error: ' + message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var varDefs = [];
|
|
||||||
withVars.forEach(function (withVar, i) {
|
|
||||||
if (!varNameRegExp.test(withVar.name)) {
|
|
||||||
this.addError('Invalid variable name of "' + withVar.name + '" in "' + vars + '"');
|
|
||||||
}
|
|
||||||
varDefs.push((i > 0 ? template.indentStr(1) + ' ' : '') + withVar.name + (withVar.value ? '=' + withVar.value : '') + (i < withVars.length - 1 ? ',\n' : ';'));
|
|
||||||
}, this);
|
|
||||||
template.statement('(function() {').indent(function () {
|
|
||||||
template.statement('var ' + varDefs.join(''));
|
|
||||||
this.generateCodeForChildren(template);
|
|
||||||
}, this).line('}());');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(WithNode, require('../../compiler').Node);
|
|
||||||
module.exports = WithNode;
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var EscapeXmlContext = require('../../compiler/lib/EscapeXmlContext');
|
|
||||||
function WriteNode(props) {
|
|
||||||
WriteNode.$super.call(this, 'write');
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WriteNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var expression = this.getExpression();
|
|
||||||
var escapeXml;
|
|
||||||
if (this.hasProperty('escapeXml')) {
|
|
||||||
escapeXml = this.getProperty('escapeXml') !== false;
|
|
||||||
} else {
|
|
||||||
escapeXml = this.getProperty('escape-xml') !== false;
|
|
||||||
}
|
|
||||||
if (escapeXml === true) {
|
|
||||||
if (this.getEscapeXmlContext() === EscapeXmlContext.Attribute) {
|
|
||||||
expression = template.getStaticHelperFunction('escapeXmlAttr', 'xa') + '(' + expression + ')';
|
|
||||||
} else {
|
|
||||||
expression = template.getStaticHelperFunction('escapeXml', 'x') + '(' + expression + ')';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (expression) {
|
|
||||||
template.write(expression);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getExpression: function () {
|
|
||||||
return this.getProperty('expression') || this.getProperty('value') || this.getAttribute('expression') || this.getAttribute('value');
|
|
||||||
},
|
|
||||||
toString: function () {
|
|
||||||
return '<c:write expression="' + this.getExpression() + '">';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(WriteNode, require('../../compiler').Node);
|
|
||||||
module.exports = WriteNode;
|
|
||||||
@ -1,291 +0,0 @@
|
|||||||
{
|
|
||||||
"tags": {
|
|
||||||
"c-template": {
|
|
||||||
"attributes": {
|
|
||||||
"name": {
|
|
||||||
"allow-expressions": false,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"params": {
|
|
||||||
"allow-expressions": false,
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node-class": "./TemplateNode"
|
|
||||||
},
|
|
||||||
"*": {
|
|
||||||
"attributes": {
|
|
||||||
"c-space": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"c-whitespace": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"c-for": {
|
|
||||||
"allow-expressions": false,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"c-for-each": {
|
|
||||||
"allow-expressions": false,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"c-if": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"c-else": {
|
|
||||||
"type": "empty"
|
|
||||||
},
|
|
||||||
"c-else-if": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"c-attrs": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"c-when": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"c-with": {
|
|
||||||
"type": "custom"
|
|
||||||
},
|
|
||||||
"c-otherwise": {
|
|
||||||
"type": "empty"
|
|
||||||
},
|
|
||||||
"c-parse-body-text": {
|
|
||||||
"type": "boolean",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"c-trim-body-indent": {
|
|
||||||
"type": "boolean",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"c-strip": {
|
|
||||||
"type": "boolean",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"c-content": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"c-replace": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"c-input": {
|
|
||||||
"type": "expression"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"transformer": {
|
|
||||||
"path": "./CoreTagTransformer",
|
|
||||||
"priority": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-for": {
|
|
||||||
"node-class": "./ForNode",
|
|
||||||
"attributes": {
|
|
||||||
"each": {
|
|
||||||
"required": false,
|
|
||||||
"allow-expressions": false,
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"separator": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"status-var": {
|
|
||||||
"type": "identifier",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"for-loop": {
|
|
||||||
"type": "boolean",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"iterator": {
|
|
||||||
"type": "expression"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-write": {
|
|
||||||
"node-class": "./WriteNode",
|
|
||||||
"attributes": {
|
|
||||||
"value": {
|
|
||||||
"required": true,
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"escape-xml": {
|
|
||||||
"type": "boolean",
|
|
||||||
"allow-expressions": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-if": {
|
|
||||||
"node-class": "./IfNode",
|
|
||||||
"attributes": {
|
|
||||||
"test": {
|
|
||||||
"type": "expression"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-else": {
|
|
||||||
"node-class": "./ElseNode",
|
|
||||||
"transformer": {
|
|
||||||
"path": "./ElseTagTransformer",
|
|
||||||
"name": "ElseTagTransformer",
|
|
||||||
"properties": {
|
|
||||||
"type": "else"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-else-if": {
|
|
||||||
"attributes": {
|
|
||||||
"test": {
|
|
||||||
"type": "expression"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node-class": "./ElseIfNode",
|
|
||||||
"transformer": {
|
|
||||||
"path": "./ElseTagTransformer",
|
|
||||||
"name": "ElseIfTagTransformer",
|
|
||||||
"properties": {
|
|
||||||
"type": "else-if"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-invoke": {
|
|
||||||
"node-class": "./InvokeNode",
|
|
||||||
"attributes": {
|
|
||||||
"function": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false,
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
"*": {
|
|
||||||
"type": "string",
|
|
||||||
"allow-expressions": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-choose": {
|
|
||||||
"node-class": "./ChooseNode"
|
|
||||||
},
|
|
||||||
"c-when": {
|
|
||||||
"node-class": "./WhenNode",
|
|
||||||
"attributes": {
|
|
||||||
"test": {
|
|
||||||
"type": "expression"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-otherwise": {
|
|
||||||
"node-class": "./OtherwiseNode"
|
|
||||||
},
|
|
||||||
"c-def": {
|
|
||||||
"node-class": "./DefNode",
|
|
||||||
"attributes": {
|
|
||||||
"function": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"body-param": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-with": {
|
|
||||||
"node-class": "./WithNode",
|
|
||||||
"attributes": {
|
|
||||||
"vars": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-include": {
|
|
||||||
"node-class": "./IncludeNode",
|
|
||||||
"attributes": {
|
|
||||||
"template": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"template-data": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"resource": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"static": {
|
|
||||||
"type": "boolean",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"*": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-attr": {
|
|
||||||
"attributes": {
|
|
||||||
"name": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"namespace": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"prefix": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-var": {
|
|
||||||
"node-class": "./VarNode",
|
|
||||||
"attributes": {
|
|
||||||
"name": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "expression"
|
|
||||||
},
|
|
||||||
"static": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"string-value": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"boolean-value": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"number-value": {
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-require": {
|
|
||||||
"node-class": "./RequireNode",
|
|
||||||
"attributes": {
|
|
||||||
"module": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"var": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"c-assign": {
|
|
||||||
"node-class": "./AssignNode",
|
|
||||||
"attributes": {
|
|
||||||
"var": {
|
|
||||||
"type": "custom",
|
|
||||||
"allow-expressions": false
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "expression"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"text-transformer": {
|
|
||||||
"path": "./CoreTextTransformer"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
module.exports = {
|
|
||||||
process: function (input, context) {
|
|
||||||
context.write('<!--');
|
|
||||||
if (input.invokeBody) {
|
|
||||||
input.invokeBody();
|
|
||||||
}
|
|
||||||
context.write('-->');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var ExpressionParser = require('../../compiler').ExpressionParser;
|
|
||||||
function DocTypeNode(props) {
|
|
||||||
DocTypeNode.$super.call(this);
|
|
||||||
if (props) {
|
|
||||||
this.setProperties(props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DocTypeNode.prototype = {
|
|
||||||
doGenerateCode: function (template) {
|
|
||||||
var doctype = this.getAttribute('value') || this.getProperty('value');
|
|
||||||
template.text('<!DOCTYPE ');
|
|
||||||
ExpressionParser.parse(doctype, {
|
|
||||||
text: function (text, escapeXml) {
|
|
||||||
template.text(text);
|
|
||||||
},
|
|
||||||
expression: function (expression) {
|
|
||||||
template.write(expression);
|
|
||||||
},
|
|
||||||
error: function (message) {
|
|
||||||
this.addError('Invalid doctype: "' + doctype + '". ' + message);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
template.text('>');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
require('raptor-util').inherit(DocTypeNode, require('../../compiler').ElementNode);
|
|
||||||
module.exports = DocTypeNode;
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 eBay Software Foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
var DocTypeNode = require('./DocTypeNode');
|
|
||||||
function HtmlTagTransformer() {
|
|
||||||
}
|
|
||||||
HtmlTagTransformer.prototype = {
|
|
||||||
process: function (node, compiler) {
|
|
||||||
if (node.isElementNode()) {
|
|
||||||
var options = compiler.options || {};
|
|
||||||
var preserveWhitespace = options.preserveWhitespace || {};
|
|
||||||
var allowSelfClosing = options.allowSelfClosing || {};
|
|
||||||
var startTagOnly = options.startTagOnly || {};
|
|
||||||
var lookupKey = node.namespace ? node.namespace + ':' + node.localName : node.localName;
|
|
||||||
|
|
||||||
if (node.isPreserveWhitespace() == null) {
|
|
||||||
if (preserveWhitespace[lookupKey] === true) {
|
|
||||||
node.setPreserveWhitespace(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (allowSelfClosing[lookupKey] === true) {
|
|
||||||
node.setAllowSelfClosing(true);
|
|
||||||
}
|
|
||||||
if (compiler.options.xhtml !== true && startTagOnly[lookupKey] === true) {
|
|
||||||
node.setStartTagOnly(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.getQName() === 'html' && node.hasAttribute('html-doctype')) {
|
|
||||||
var doctype = node.getAttribute('html-doctype');
|
|
||||||
var docTypeNode = new DocTypeNode({
|
|
||||||
value: doctype,
|
|
||||||
pos: node.getPosition()
|
|
||||||
});
|
|
||||||
node.parentNode.insertBefore(docTypeNode, node);
|
|
||||||
node.removeAttribute('html-doctype');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
module.exports = HtmlTagTransformer;
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"tags": {
|
|
||||||
"html-html": {
|
|
||||||
"attributes": {
|
|
||||||
"doctype": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"html-doctype": {
|
|
||||||
"attributes": {
|
|
||||||
"value": {
|
|
||||||
"type": "custom"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node-class": "./DocTypeNode"
|
|
||||||
},
|
|
||||||
"*": {
|
|
||||||
"transformer": "./HtmlTagTransformer"
|
|
||||||
},
|
|
||||||
"html-comment": {
|
|
||||||
"renderer": "./CommentTag"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
render: function (input, context) {
|
|
||||||
var content = input.content[input.name];
|
|
||||||
if (content) {
|
|
||||||
if (content.value) {
|
|
||||||
context.write(content.value);
|
|
||||||
} else if (content.invokeBody) {
|
|
||||||
content.invokeBody();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (input.invokeBody) {
|
|
||||||
input.invokeBody();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
render: function (input, context) {
|
|
||||||
input._layout.handlePutTag(input);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
var extend = require('raptor-util').extend;
|
|
||||||
var raptorTemplates = require('../../');
|
|
||||||
module.exports = {
|
|
||||||
render: function (input, context) {
|
|
||||||
var content = {};
|
|
||||||
input.invokeBody({
|
|
||||||
handlePutTag: function (putTag) {
|
|
||||||
content[putTag.into] = putTag;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var viewModel = extend(input['*'] || {}, { layoutContent: content });
|
|
||||||
raptorTemplates.render(input.template, viewModel, context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
<raptor-taglib>
|
|
||||||
<tlib-version>1.0</tlib-version>
|
|
||||||
<namespace>raptor-templates/layout</namespace>
|
|
||||||
<namespace>layout</namespace>
|
|
||||||
<namespace>http://raptorjs.org/templates/layout</namespace>
|
|
||||||
|
|
||||||
<tag name="use" renderer="./UseTag">
|
|
||||||
<attribute name="template" type="path"/>
|
|
||||||
<attribute name="*" remove-dashes="true" />
|
|
||||||
<variable name="_layout"/>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag name="put" renderer="./PutTag">
|
|
||||||
<attribute name="into"/>
|
|
||||||
<attribute name="value"/>
|
|
||||||
<import-variable name="_layout"/>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
<tag name="placeholder" renderer="./PlaceholderTag">
|
|
||||||
<attribute name="name"/>
|
|
||||||
<import-variable expression="data.layoutContent" target-property="content"/>
|
|
||||||
</tag>
|
|
||||||
|
|
||||||
</raptor-taglib>
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
{
|
|
||||||
"tags": {
|
|
||||||
"layout-use": {
|
|
||||||
"renderer": "./UseTag",
|
|
||||||
"attributes": {
|
|
||||||
"template": {
|
|
||||||
"type": "path"
|
|
||||||
},
|
|
||||||
"*": {
|
|
||||||
"remove-dashes": true,
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"var": "_layout"
|
|
||||||
},
|
|
||||||
"layout-put": {
|
|
||||||
"renderer": "./PutTag",
|
|
||||||
"attributes": {
|
|
||||||
"into": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"value": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"import-var": {
|
|
||||||
"_layout": "_layout"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"layout-placeholder": {
|
|
||||||
"renderer": "./PlaceholderTag",
|
|
||||||
"attributes": {
|
|
||||||
"name": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"import-var": {
|
|
||||||
"content": "data.layoutContent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -15,11 +15,11 @@ function testRender(path, data, done, options) {
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
var compiledPath = nodePath.join(__dirname, path + '.actual.js');
|
var compiledPath = nodePath.join(__dirname, path + '.actual.js');
|
||||||
|
|
||||||
var compiler = require('../compiler').createCompiler(inputPath);
|
// var compiler = require('../compiler').createCompiler(inputPath);
|
||||||
var src = fs.readFileSync(inputPath, {encoding: 'utf8'});
|
// var src = fs.readFileSync(inputPath, {encoding: 'utf8'});
|
||||||
|
|
||||||
var compiledSrc = compiler.compile(src);
|
// var compiledSrc = compiler.compile(src);
|
||||||
fs.writeFileSync(compiledPath, compiledSrc, {encoding: 'utf8'});
|
// fs.writeFileSync(compiledPath, compiledSrc, {encoding: 'utf8'});
|
||||||
|
|
||||||
|
|
||||||
// console.log('\nCompiled (' + inputPath + '):\n---------\n' + compiledSrc);
|
// console.log('\nCompiled (' + inputPath + '):\n---------\n' + compiledSrc);
|
||||||
@ -385,5 +385,9 @@ describe('raptor-templates/rhtml' , function() {
|
|||||||
}, done);
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should support scanning a directory for tags", function(done) {
|
||||||
|
testRender("test-project/rhtml-templates/scanned-tags.rhtml", {}, done);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,183 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
var chai = require('chai');
|
|
||||||
chai.Assertion.includeStack = true;
|
|
||||||
require('chai').should();
|
|
||||||
var expect = require('chai').expect;
|
|
||||||
var nodePath = require('path');
|
|
||||||
var fs = require('fs');
|
|
||||||
var logger = require('raptor-logging').logger(module);
|
|
||||||
|
|
||||||
describe('raptor-templates/taglib-lookup' , function() {
|
|
||||||
|
|
||||||
beforeEach(function(done) {
|
|
||||||
for (var k in require.cache) {
|
|
||||||
if (require.cache.hasOwnProperty(k)) {
|
|
||||||
delete require.cache[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
require('raptor-logging').configureLoggers({
|
|
||||||
'raptor-templates': 'INFO'
|
|
||||||
});
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup core attributes for top-level template', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
// console.log('LOOKUP: ', Object.keys(lookup.attributes));
|
|
||||||
var ifAttr = lookup.getAttribute('div', 'c-if');
|
|
||||||
expect(ifAttr != null).to.equal(true);
|
|
||||||
expect(ifAttr.type).to.equal('expression');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup core tag for top-level template', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
var ifTag = lookup.getTag('c-if');
|
|
||||||
expect(ifTag != null).to.equal(true);
|
|
||||||
expect(ifTag.name).to.equal('c-if');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup core template for top-level template', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
// console.log(Object.keys(lookup.tags));
|
|
||||||
var templateTag = lookup.getTag('c-template');
|
|
||||||
expect(templateTag != null).to.equal(true);
|
|
||||||
expect(templateTag.name).to.equal('c-template');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup custom tag for top-level template', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
var tag = lookup.getTag('test-hello');
|
|
||||||
// console.log(Object.keys(lookup.tags));
|
|
||||||
expect(tag != null).to.equal(true);
|
|
||||||
expect(tag.name).to.equal('test-hello');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup custom attributes for top-level template', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
// console.log(Object.keys(lookup.attributes));
|
|
||||||
var attr = lookup.getAttribute('test-hello', 'name');
|
|
||||||
expect(attr != null).to.equal(true);
|
|
||||||
expect(attr.type).to.equal('string');
|
|
||||||
|
|
||||||
var attr2 = lookup.getAttribute('test-hello', 'splat');
|
|
||||||
expect(attr2 != null).to.equal(true);
|
|
||||||
expect(attr2.type).to.equal('number');
|
|
||||||
|
|
||||||
attr = lookup.getAttribute('test-hello', 'expr');
|
|
||||||
expect(attr != null).to.equal(true);
|
|
||||||
expect(attr.type).to.equal('expression');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow for dynamic attributes', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
// console.log(Object.keys(lookup.attributes));
|
|
||||||
var attr = lookup.getAttribute('test-hello', 'DYNAMIC');
|
|
||||||
expect(attr != null).to.equal(true);
|
|
||||||
expect(attr.type).to.equal('number');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should cache a lookup', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup1 = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
var lookup2 = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project'));
|
|
||||||
var lookup3 = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/empty'));
|
|
||||||
var lookup4 = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/nested'));
|
|
||||||
expect(lookup1).to.equal(lookup2);
|
|
||||||
expect(lookup2).to.equal(lookup3);
|
|
||||||
expect(lookup1).to.not.equal(lookup4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup nested tags', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/nested'));
|
|
||||||
var tag = lookup.getTag('nested-foo');
|
|
||||||
|
|
||||||
expect(tag != null).to.equal(true);
|
|
||||||
expect(tag.name).to.equal('nested-foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup attributes for nested tags', function() {
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/nested'));
|
|
||||||
// console.log(Object.keys(lookup.attributes));
|
|
||||||
var attr = lookup.getAttribute('nested-foo', 'attr1');
|
|
||||||
expect(attr != null).to.equal(true);
|
|
||||||
expect(attr.type).to.equal('string');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup tag transformers correctly for un-namespaced tags', function() {
|
|
||||||
var transformers = [];
|
|
||||||
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/nested'));
|
|
||||||
|
|
||||||
lookup.forEachTagTransformer('div', function(transformer) {
|
|
||||||
transformers.push(transformer);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(transformers.length).to.equal(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup tag transformers correctly for namespaced tag with transformer', function() {
|
|
||||||
var transformers;
|
|
||||||
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup;
|
|
||||||
// lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/nested'));
|
|
||||||
|
|
||||||
// transformers = [];
|
|
||||||
// lookup.forEachTagTransformer('nested-foo', function(transformer) {
|
|
||||||
// transformers.push(transformer);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// expect(transformers.length).to.equal(2);
|
|
||||||
|
|
||||||
lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/transformers'));
|
|
||||||
|
|
||||||
transformers = [];
|
|
||||||
lookup.forEachTagTransformer('transform-foo', function(transformer) {
|
|
||||||
transformers.push(transformer);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(transformers.length).to.equal(3);
|
|
||||||
expect(transformers[0].path.indexOf('foo')).to.not.equal(-1);
|
|
||||||
expect(transformers[1].path.indexOf('CoreTagTransformer')).to.not.equal(-1);
|
|
||||||
expect(transformers[2].path.indexOf('HtmlTagTransformer')).to.not.equal(-1);
|
|
||||||
|
|
||||||
transformers = [];
|
|
||||||
lookup.forEachTagTransformer('transform-bar', function(transformer) {
|
|
||||||
transformers.push(transformer);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(transformers.length).to.equal(3);
|
|
||||||
expect(transformers[0].path.indexOf('CoreTagTransformer')).to.not.equal(-1);
|
|
||||||
expect(transformers[1].path.indexOf('bar')).to.not.equal(-1);
|
|
||||||
expect(transformers[2].path.indexOf('HtmlTagTransformer')).to.not.equal(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should lookup tag transformers core tag with custom node', function() {
|
|
||||||
var transformers = [];
|
|
||||||
|
|
||||||
var taglibLookup = require('../compiler/lib/taglib-lookup');
|
|
||||||
var lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/nested'));
|
|
||||||
|
|
||||||
lookup.forEachTagTransformer('c-else', function(transformer) {
|
|
||||||
transformers.push(transformer);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(transformers.length).to.equal(3);
|
|
||||||
expect(transformers[0].path.indexOf('CoreTagTransformer')).to.not.equal(-1);
|
|
||||||
expect(transformers[1].path.indexOf('ElseTagTransformer')).to.not.equal(-1);
|
|
||||||
expect(transformers[2].path.indexOf('HtmlTagTransformer')).to.not.equal(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
@ -76,5 +76,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"tags-dir": "./scanned-tags"
|
||||||
}
|
}
|
||||||
6
test/test-project/rhtml-templates/scanned-tags.rhtml
Normal file
6
test/test-project/rhtml-templates/scanned-tags.rhtml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<scanned-a name="Frank"/>
|
||||||
|
<scanned-b name="Frank"/>
|
||||||
|
<scanned-c name="Frank"/>
|
||||||
|
<scanned-d name="Frank"/>
|
||||||
|
<scanned-e name="Frank"/>
|
||||||
|
<scanned-f name="Frank"/>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
scanned-a: Hello Frankscanned-b: Hello Frankscanned-c: Hello Frankscanned-d: Hello Frankscanned-e: Hello Frankscanned-f: Hello Frank
|
||||||
3
test/test-project/scanned-tags/scanned-a/renderer.js
Normal file
3
test/test-project/scanned-tags/scanned-a/renderer.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = function render(input, context) {
|
||||||
|
context.write('scanned-a: Hello ' + input.name);
|
||||||
|
};
|
||||||
1
test/test-project/scanned-tags/scanned-b/template.rhtml
Normal file
1
test/test-project/scanned-tags/scanned-b/template.rhtml
Normal file
@ -0,0 +1 @@
|
|||||||
|
scanned-b: Hello ${data.name}
|
||||||
8
test/test-project/scanned-tags/scanned-c/raptor-tag.json
Normal file
8
test/test-project/scanned-tags/scanned-c/raptor-tag.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"target-property": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
test/test-project/scanned-tags/scanned-c/renderer.js
Normal file
3
test/test-project/scanned-tags/scanned-c/renderer.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = function render(input, context) {
|
||||||
|
context.write('scanned-c: Hello ' + input.NAME);
|
||||||
|
};
|
||||||
11
test/test-project/scanned-tags/scanned-d/template.rhtml
Normal file
11
test/test-project/scanned-tags/scanned-d/template.rhtml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!--
|
||||||
|
TAG = {
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"target-property": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-->
|
||||||
|
scanned-d: Hello ${data.NAME}
|
||||||
12
test/test-project/scanned-tags/scanned-e/renderer.js
Normal file
12
test/test-project/scanned-tags/scanned-e/renderer.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
exports.TAG = {
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"target-property": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function render(input, context) {
|
||||||
|
context.write('scanned-e: Hello ' + input.NAME);
|
||||||
|
};
|
||||||
14
test/test-project/scanned-tags/scanned-f/renderer.js
Normal file
14
test/test-project/scanned-tags/scanned-f/renderer.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
TAG = {
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"target-property": "NAME"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = function render(input, context) {
|
||||||
|
context.write('scanned-f: Hello ' + input.NAME);
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user