mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Dynamic attribute support improved and other improvements
This commit is contained in:
parent
f599e0e7e0
commit
f8578b94db
@ -23,7 +23,7 @@ var XML_URI_ALT = 'http://www.w3.org/XML/1998/namespace';
|
||||
var ExpressionParser = require('./ExpressionParser');
|
||||
var forEachEntry = require('raptor-util').forEachEntry;
|
||||
|
||||
function ElementNode(localName, uri, prefix) {
|
||||
function ElementNode(localName, namespace, prefix) {
|
||||
ElementNode.$super.call(this, 'element');
|
||||
if (!this._elementNode) {
|
||||
this._elementNode = true;
|
||||
@ -31,7 +31,7 @@ function ElementNode(localName, uri, prefix) {
|
||||
this.attributesByNS = {};
|
||||
this.prefix = prefix;
|
||||
this.localName = this.tagName = localName;
|
||||
this.uri = uri;
|
||||
this.namespace = namespace;
|
||||
this.allowSelfClosing = false;
|
||||
this.startTagOnly = false;
|
||||
}
|
||||
@ -54,7 +54,7 @@ ElementNode.prototype = {
|
||||
},
|
||||
getAllAttributes: function () {
|
||||
var allAttrs = [];
|
||||
forEachEntry(this.attributesByNS, function (uri, attrs) {
|
||||
forEachEntry(this.attributesByNS, function (namespace, attrs) {
|
||||
forEachEntry(attrs, function (name, attr) {
|
||||
allAttrs.push(attr);
|
||||
});
|
||||
@ -63,7 +63,7 @@ ElementNode.prototype = {
|
||||
},
|
||||
forEachAttributeAnyNS: function (callback, thisObj) {
|
||||
var attributes = [];
|
||||
forEachEntry(this.attributesByNS, function (uri, attrs) {
|
||||
forEachEntry(this.attributesByNS, function (namespace, attrs) {
|
||||
forEachEntry(attrs, function (name, attr) {
|
||||
attributes.push(attr);
|
||||
});
|
||||
@ -71,8 +71,8 @@ ElementNode.prototype = {
|
||||
|
||||
attributes.forEach(callback, thisObj);
|
||||
},
|
||||
forEachAttributeNS: function (uri, callback, thisObj) {
|
||||
var attrs = this.attributesByNS[uri || ''];
|
||||
forEachAttributeNS: function (namespace, callback, thisObj) {
|
||||
var attrs = this.attributesByNS[namespace || ''];
|
||||
if (attrs) {
|
||||
forEachEntry(attrs, function (name, attr) {
|
||||
callback.call(thisObj, attr);
|
||||
@ -89,24 +89,24 @@ ElementNode.prototype = {
|
||||
getAttribute: function (name) {
|
||||
return this.getAttributeNS(null, name);
|
||||
},
|
||||
getAttributeNS: function (uri, localName) {
|
||||
var attrNS = this.attributesByNS[uri || ''];
|
||||
getAttributeNS: function (namespace, localName) {
|
||||
var attrNS = this.attributesByNS[namespace || ''];
|
||||
var attr = attrNS ? attrNS[localName] : undefined;
|
||||
return attr ? attr.value : undefined;
|
||||
},
|
||||
setAttribute: function (localName, value, escapeXml) {
|
||||
this.setAttributeNS(null, localName, value, null, escapeXml);
|
||||
},
|
||||
setAttributeNS: function (uri, localName, value, prefix, escapeXml) {
|
||||
var attrNS = this.attributesByNS[uri || ''] || (this.attributesByNS[uri || ''] = {});
|
||||
setAttributeNS: function (namespace, localName, value, prefix, escapeXml) {
|
||||
var attrNS = this.attributesByNS[namespace || ''] || (this.attributesByNS[namespace || ''] = {});
|
||||
attrNS[localName] = {
|
||||
localName: localName,
|
||||
value: value,
|
||||
prefix: prefix,
|
||||
uri: uri,
|
||||
namespace: namespace,
|
||||
escapeXml: escapeXml,
|
||||
qName: prefix ? prefix + ':' + localName : localName,
|
||||
name: uri ? uri + ':' + localName : localName,
|
||||
name: namespace ? namespace + ':' + localName : localName,
|
||||
toString: function () {
|
||||
return this.name;
|
||||
}
|
||||
@ -118,17 +118,17 @@ ElementNode.prototype = {
|
||||
removeAttribute: function (localName) {
|
||||
this.removeAttributeNS(null, localName);
|
||||
},
|
||||
removeAttributeNS: function (uri, localName) {
|
||||
var attrNS = this.attributesByNS[uri || ''] || (this.attributesByNS[uri || ''] = {});
|
||||
removeAttributeNS: function (namespace, localName) {
|
||||
var attrNS = this.attributesByNS[namespace || ''] || (this.attributesByNS[namespace || ''] = {});
|
||||
if (attrNS) {
|
||||
delete attrNS[localName];
|
||||
if (objects.isEmpty(attrNS)) {
|
||||
delete this.attributesByNS[uri || ''];
|
||||
delete this.attributesByNS[namespace || ''];
|
||||
}
|
||||
}
|
||||
},
|
||||
removeAttributesNS: function (uri) {
|
||||
delete this.attributesByNS[uri || ''];
|
||||
removeAttributesNS: function (namespace) {
|
||||
delete this.attributesByNS[namespace || ''];
|
||||
},
|
||||
isPreserveWhitespace: function () {
|
||||
var preserveSpace = ElementNode.$super.prototype.isPreserveWhitespace.call(this);
|
||||
@ -147,14 +147,14 @@ ElementNode.prototype = {
|
||||
hasAttributes: function () {
|
||||
return this.hasAttributesNS('');
|
||||
},
|
||||
hasAttributesNS: function (uri) {
|
||||
return this.attributesByNS[uri || ''] !== undefined;
|
||||
hasAttributesNS: function (namespace) {
|
||||
return this.attributesByNS[namespace || ''] !== undefined;
|
||||
},
|
||||
hasAttribute: function (localName) {
|
||||
return this.hasAttributeNS('', localName);
|
||||
},
|
||||
hasAttributeNS: function (uri, localName) {
|
||||
var attrsNS = this.attributesByNS[uri || ''];
|
||||
hasAttributeNS: function (namespace, localName) {
|
||||
var attrsNS = this.attributesByNS[namespace || ''];
|
||||
return attrsNS ? attrsNS.hasOwnProperty(localName) : false;
|
||||
},
|
||||
removePreserveSpaceAttr: function () {
|
||||
@ -179,8 +179,8 @@ ElementNode.prototype = {
|
||||
template.text('<' + name);
|
||||
this.forEachAttributeAnyNS(function (attr) {
|
||||
var prefix = attr.prefix;
|
||||
if (!prefix && attr.uri) {
|
||||
prefix = this.resolveNamespacePrefix(attr.uri);
|
||||
if (!prefix && attr.namespace) {
|
||||
prefix = this.resolveNamespacePrefix(attr.namespace);
|
||||
}
|
||||
if (prefix) {
|
||||
name = prefix + (attr.localName ? ':' + attr.localName : '');
|
||||
|
||||
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Probably one of the more amazing regular expressions you will ever see...
|
||||
*
|
||||
* Valid imports:
|
||||
* x, y, z from http://raptorjs.org/templates/core
|
||||
* x, y, z from core
|
||||
* x, y, z from core as my-core
|
||||
* * from core as c
|
||||
* core
|
||||
* core as my-core
|
||||
*/
|
||||
|
||||
var importRegExp = /^(?:(\*|(?:(?:@?[A-Za-z0-9_\-]+\s*,\s*)*@?[A-Za-z0-9_\-]+))\s+from\s+)?([^ ]*)(?:\s+as\s+([A-Za-z0-9_\-]+))?$/;
|
||||
function getImported(lookup, localName, imports) {
|
||||
if (lookup[localName] != null) {
|
||||
return lookup[localName];
|
||||
}
|
||||
var prefixEnd = localName.indexOf('-');
|
||||
var prefix;
|
||||
var namespace;
|
||||
var name;
|
||||
|
||||
if (prefixEnd != -1) {
|
||||
prefix = localName.substring(0, prefixEnd);
|
||||
name = localName.substring(prefixEnd + 1);
|
||||
namespace = imports._prefixes[prefix];
|
||||
if (namespace) {
|
||||
return {
|
||||
namespace: namespace,
|
||||
name: name,
|
||||
prefix: prefix
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function Imports(taglibs, importsStr) {
|
||||
this._tagImports = {};
|
||||
this._attrImports = {};
|
||||
this._prefixes = {};
|
||||
var parts = importsStr.trim().split(/\s*;\s*/);
|
||||
parts.forEach(function (part) {
|
||||
if (!part) {
|
||||
//Skip empty strings
|
||||
return;
|
||||
}
|
||||
var match = part.match(importRegExp), imports, importsLookup = {}, from, as;
|
||||
|
||||
if (!match) {
|
||||
throw new Error('Invalid import: "' + part + '"');
|
||||
} else {
|
||||
imports = match[1];
|
||||
from = match[2];
|
||||
as = match[3];
|
||||
if (!as) {
|
||||
as = from;
|
||||
}
|
||||
}
|
||||
|
||||
this._prefixes[as] = from;
|
||||
if (imports) {
|
||||
imports.split(/\s*,\s*/).forEach(function (importedTagName) {
|
||||
importsLookup[importedTagName] = true;
|
||||
});
|
||||
}
|
||||
taglibs.forEachTag(from, function (tag, taglib) {
|
||||
if (tag.namespace === from && (importsLookup['*'] || importsLookup[tag.name])) {
|
||||
/*
|
||||
* Import tags with a URI that matches the taglib URI
|
||||
*/
|
||||
this._tagImports[tag.name] = {
|
||||
namespace: from,
|
||||
name: tag.name,
|
||||
prefix: as
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Allow imports for attributes that can be assigned to tags with a different URI
|
||||
* e.g. <div c-if="someCondition"></div> --> <div c:if="someCondition"></div>
|
||||
*/
|
||||
tag.forEachAttribute(function (attr) {
|
||||
if (tag.namespace !== from && (importsLookup['*'] || importsLookup['@' + attr.name])) {
|
||||
this._attrImports[attr.name] = {
|
||||
namespace: from,
|
||||
name: attr.name,
|
||||
prefix: as
|
||||
};
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
}, this);
|
||||
}
|
||||
|
||||
Imports.prototype = {
|
||||
getImportedTag: function (localName) {
|
||||
return getImported(this._tagImports, localName, this);
|
||||
},
|
||||
getImportedAttribute: function (localName) {
|
||||
return getImported(this._attrImports, localName, this);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Imports;
|
||||
@ -71,92 +71,92 @@ Node.prototype = {
|
||||
setProperty: function (name, value) {
|
||||
this.setPropertyNS(null, name, value);
|
||||
},
|
||||
setPropertyNS: function (uri, name, value) {
|
||||
if (!uri) {
|
||||
uri = '';
|
||||
setPropertyNS: function (namespace, name, value) {
|
||||
if (!namespace) {
|
||||
namespace = '';
|
||||
}
|
||||
var namespacedProps = this.properties[uri];
|
||||
var namespacedProps = this.properties[namespace];
|
||||
if (!namespacedProps) {
|
||||
namespacedProps = this.properties[uri] = {};
|
||||
namespacedProps = this.properties[namespace] = {};
|
||||
}
|
||||
namespacedProps[name] = value;
|
||||
},
|
||||
setProperties: function (props) {
|
||||
this.setPropertiesNS(null, props);
|
||||
},
|
||||
setPropertiesNS: function (uri, props) {
|
||||
if (!uri) {
|
||||
uri = '';
|
||||
setPropertiesNS: function (namespace, props) {
|
||||
if (!namespace) {
|
||||
namespace = '';
|
||||
}
|
||||
forEachEntry(props, function (name, value) {
|
||||
this.setPropertyNS(uri, name, value);
|
||||
this.setPropertyNS(namespace, name, value);
|
||||
}, this);
|
||||
},
|
||||
getPropertyNamespaces: function () {
|
||||
return Object.keys(this.properties);
|
||||
},
|
||||
getProperties: function (uri) {
|
||||
getProperties: function (namespace) {
|
||||
return this.getPropertiesNS(null);
|
||||
},
|
||||
hasProperty: function (name) {
|
||||
return this.hasPropertyNS('', name);
|
||||
},
|
||||
hasPropertyNS: function (uri, name) {
|
||||
if (!uri) {
|
||||
uri = '';
|
||||
hasPropertyNS: function (namespace, name) {
|
||||
if (!namespace) {
|
||||
namespace = '';
|
||||
}
|
||||
var namespaceProps = this.properties[uri];
|
||||
var namespaceProps = this.properties[namespace];
|
||||
return namespaceProps.hasOwnProperty(name);
|
||||
},
|
||||
getPropertiesByNS: function () {
|
||||
return this.properties;
|
||||
},
|
||||
getPropertiesNS: function (uri) {
|
||||
if (!uri) {
|
||||
uri = '';
|
||||
getPropertiesNS: function (namespace) {
|
||||
if (!namespace) {
|
||||
namespace = '';
|
||||
}
|
||||
return this.properties[uri];
|
||||
return this.properties[namespace];
|
||||
},
|
||||
forEachProperty: function (callback, thisObj) {
|
||||
forEachEntry(this.properties, function (uri, properties) {
|
||||
forEachEntry(this.properties, function (namespace, properties) {
|
||||
forEachEntry(properties, function (name, value) {
|
||||
callback.call(thisObj, uri, name, value);
|
||||
callback.call(thisObj, namespace, name, value);
|
||||
}, this);
|
||||
}, this);
|
||||
},
|
||||
getProperty: function (name) {
|
||||
return this.getPropertyNS(null, name);
|
||||
},
|
||||
getPropertyNS: function (uri, name) {
|
||||
if (!uri) {
|
||||
uri = '';
|
||||
getPropertyNS: function (namespace, name) {
|
||||
if (!namespace) {
|
||||
namespace = '';
|
||||
}
|
||||
var namespaceProps = this.properties[uri];
|
||||
var namespaceProps = this.properties[namespace];
|
||||
return namespaceProps ? namespaceProps[name] : undefined;
|
||||
},
|
||||
removeProperty: function (name) {
|
||||
this.removePropertyNS('', name);
|
||||
},
|
||||
removePropertyNS: function (uri, name) {
|
||||
if (!uri) {
|
||||
uri = '';
|
||||
removePropertyNS: function (namespace, name) {
|
||||
if (!namespace) {
|
||||
namespace = '';
|
||||
}
|
||||
var namespaceProps = this.properties[uri];
|
||||
var namespaceProps = this.properties[namespace];
|
||||
if (namespaceProps) {
|
||||
delete namespaceProps[name];
|
||||
}
|
||||
if (isEmpty(namespaceProps)) {
|
||||
delete this.properties[uri];
|
||||
delete this.properties[namespace];
|
||||
}
|
||||
},
|
||||
removePropertiesNS: function (uri) {
|
||||
delete this.properties[uri];
|
||||
removePropertiesNS: function (namespace) {
|
||||
delete this.properties[namespace];
|
||||
},
|
||||
forEachPropertyNS: function (uri, callback, thisObj) {
|
||||
if (uri == null) {
|
||||
uri = '';
|
||||
forEachPropertyNS: function (namespace, callback, thisObj) {
|
||||
if (namespace == null) {
|
||||
namespace = '';
|
||||
}
|
||||
var props = this.properties[uri];
|
||||
var props = this.properties[namespace];
|
||||
if (props) {
|
||||
forEachEntry(props, function (name, value) {
|
||||
callback.call(thisObj, name, value);
|
||||
@ -506,16 +506,16 @@ Node.prototype = {
|
||||
}
|
||||
var existingNamespaceMappings = this.namespaceMappings;
|
||||
var prefixMappings = this.prefixMappings;
|
||||
forEachEntry(namespaceMappings, function (prefix, uri) {
|
||||
existingNamespaceMappings[prefix] = uri;
|
||||
prefixMappings[uri] = prefix;
|
||||
forEachEntry(namespaceMappings, function (prefix, namespace) {
|
||||
existingNamespaceMappings[prefix] = namespace;
|
||||
prefixMappings[namespace] = prefix;
|
||||
});
|
||||
},
|
||||
hasNamespacePrefix: function (uri) {
|
||||
return this.prefixMappings.hasOwnProperty(uri);
|
||||
hasNamespacePrefix: function (namespace) {
|
||||
return this.prefixMappings.hasOwnProperty(namespace);
|
||||
},
|
||||
resolveNamespacePrefix: function (uri) {
|
||||
var prefix = this.prefixMappings[uri];
|
||||
resolveNamespacePrefix: function (namespace) {
|
||||
var prefix = this.prefixMappings[namespace];
|
||||
return !prefix && this.parentNode ? this.parentNode.resolveNamespacePrefix() : prefix;
|
||||
},
|
||||
forEachNamespace: function (callback, thisObj) {
|
||||
|
||||
@ -18,7 +18,6 @@ var createError = require('raptor-util').createError;
|
||||
var sax = require('raptor-xml/sax');
|
||||
var TextNode = require('./TextNode');
|
||||
var ElementNode = require('./ElementNode');
|
||||
var Imports = require('./Imports');
|
||||
|
||||
function ParseTreeBuilder() {
|
||||
}
|
||||
@ -32,7 +31,6 @@ ParseTreeBuilder.prototype = {
|
||||
var parentNode = null;
|
||||
var rootNode = null;
|
||||
var prevTextNode = null;
|
||||
var imports;
|
||||
var parser = sax.createParser({
|
||||
trim: false,
|
||||
normalize: false,
|
||||
@ -63,29 +61,18 @@ ParseTreeBuilder.prototype = {
|
||||
},
|
||||
startElement: function (el) {
|
||||
prevTextNode = null;
|
||||
var importsAttr;
|
||||
var importedAttr;
|
||||
var importedTag;
|
||||
|
||||
var elementNode = new ElementNode(el.getLocalName(), el.getNamespaceURI(), el.getPrefix());
|
||||
elementNode.addNamespaceMappings(el.getNamespaceMappings());
|
||||
elementNode.pos = parser.getPos();
|
||||
|
||||
el.getAttributes().forEach(function (attr) {
|
||||
if (attr.getLocalName() === 'imports' && !attr.getNamespaceURI()) {
|
||||
importsAttr = attr.getValue();
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (parentNode) {
|
||||
parentNode.appendChild(elementNode);
|
||||
} else {
|
||||
rootNode = elementNode;
|
||||
if (importsAttr) {
|
||||
imports = new Imports(taglibs, importsAttr);
|
||||
}
|
||||
|
||||
if (el.getLocalName() === 'template' && !el.getNamespaceURI()) {
|
||||
rootNode.uri = 'core';
|
||||
rootNode.namespace = 'core';
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,18 +80,9 @@ ParseTreeBuilder.prototype = {
|
||||
var attrURI = attr.getNamespaceURI();
|
||||
var attrLocalName = attr.getLocalName();
|
||||
var attrPrefix = attr.getPrefix();
|
||||
if (!attrURI && imports && (importedAttr = imports.getImportedAttribute(attrLocalName))) {
|
||||
attrURI = importedAttr.uri;
|
||||
attrLocalName = importedAttr.name;
|
||||
attrPrefix = importedAttr.prefix;
|
||||
}
|
||||
elementNode.setAttributeNS(attrURI, attrLocalName, attr.getValue(), attrPrefix);
|
||||
}, this);
|
||||
if (!elementNode.uri && imports && (importedTag = imports.getImportedTag(elementNode.localName))) {
|
||||
elementNode.uri = importedTag.uri;
|
||||
elementNode.localName = importedTag.name;
|
||||
elementNode.prefix = importedTag.prefix;
|
||||
}
|
||||
|
||||
parentNode = elementNode;
|
||||
},
|
||||
endElement: function () {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
var ok = require('assert').ok;
|
||||
var createError = require('raptor-util').createError;
|
||||
var forEachEntry = require('raptor-util').forEachEntry;
|
||||
|
||||
function TaglibLookup() {
|
||||
this.namespaces = {};
|
||||
@ -175,6 +176,16 @@ TaglibLookup.prototype = {
|
||||
|
||||
return attr;
|
||||
},
|
||||
forEachTag: function (namespace, callback, thisObj) {
|
||||
var taglibId = this.resolveNamespace(namespace);
|
||||
var taglib = this.taglibsById[taglibId];
|
||||
if (!taglib) {
|
||||
return;
|
||||
}
|
||||
forEachEntry(taglib.tags, function (key, tag) {
|
||||
callback.call(thisObj, tag, taglib);
|
||||
});
|
||||
},
|
||||
forEachNodeTransformer: function (node, callback, thisObj) {
|
||||
/*
|
||||
* Based on the type of node we have to choose how to transform it
|
||||
|
||||
@ -176,7 +176,25 @@ TaglibXmlLoader.prototype = {
|
||||
_type: STRING,
|
||||
_targetProp: 'version'
|
||||
},
|
||||
'alias': {
|
||||
'uri': {
|
||||
_type: STRING,
|
||||
_set: function (taglib, name, value, context) {
|
||||
taglib.addNamespace(value);
|
||||
}
|
||||
},
|
||||
'namespace': {
|
||||
_type: STRING,
|
||||
_set: function (taglib, name, value, context) {
|
||||
taglib.addNamespace(value);
|
||||
}
|
||||
},
|
||||
'short-name': {
|
||||
_type: STRING,
|
||||
_set: function (taglib, name, value, context) {
|
||||
taglib.addNamespace(value);
|
||||
}
|
||||
},
|
||||
'prefix': {
|
||||
_type: STRING,
|
||||
_set: function (taglib, name, value, context) {
|
||||
taglib.addNamespace(value);
|
||||
@ -243,11 +261,22 @@ TaglibXmlLoader.prototype = {
|
||||
},
|
||||
'node-class': {
|
||||
_type: STRING,
|
||||
_targetProp: 'nodeClass'
|
||||
_set: function (tag, name, path) {
|
||||
tag.nodeClass = resolvePath(path);
|
||||
}
|
||||
},
|
||||
'dynamic-attributes': {
|
||||
_type: BOOLEAN,
|
||||
_targetProp: 'dynamicAttributes'
|
||||
_set: function(tag, name, isDynamicAttributes) {
|
||||
if (isDynamicAttributes === true || isDynamicAttributes === 'true') {
|
||||
var attr = new Attribute();
|
||||
attr.name = '*';
|
||||
attr.dynamicAttribute = true;
|
||||
attr.type = 'string';
|
||||
tag.addAttribute(attr);
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
'dynamic-attributes-remove-dashes': {
|
||||
_type: BOOLEAN,
|
||||
|
||||
@ -430,8 +430,8 @@ TemplateBuilder.prototype = {
|
||||
getErrors: function () {
|
||||
return this.compiler.getErrors();
|
||||
},
|
||||
getNodeClass: function (uri, localName) {
|
||||
return this.compiler.getNodeClass(uri, localName);
|
||||
getNodeClass: function (namespace, localName) {
|
||||
return this.compiler.getNodeClass(namespace, localName);
|
||||
},
|
||||
transformTree: function (node) {
|
||||
this.compiler.transformTree(node, this);
|
||||
|
||||
@ -45,6 +45,7 @@ TemplateCompiler.prototype = {
|
||||
function transformTreeHelper(node) {
|
||||
try {
|
||||
_this.taglibs.forEachNodeTransformer(node, function (transformer) {
|
||||
|
||||
if (!node.isTransformerApplied(transformer)) {
|
||||
//Check to make sure a transformer of a certain type is only applied once to a node
|
||||
node.setTransformerApplied(transformer);
|
||||
|
||||
@ -67,6 +67,9 @@ function buildAttribute(attr, attrProps, path) {
|
||||
invokeHandlers(attrProps, {
|
||||
type: function(value) {
|
||||
attr.type = value;
|
||||
},
|
||||
targetProperty: function(value) {
|
||||
attr.targetProperty = value;
|
||||
}
|
||||
}, path);
|
||||
|
||||
@ -108,12 +111,27 @@ function buildTag(tagObject, path, taglib, dirname) {
|
||||
|
||||
var attr = new Taglib.Attribute(namespace, localName);
|
||||
|
||||
if (typeof attrProps === 'string') {
|
||||
|
||||
attr.type = attrProps;
|
||||
if (attrProps == null) {
|
||||
attrProps = {
|
||||
type: 'string'
|
||||
};
|
||||
}
|
||||
else {
|
||||
buildAttribute(attr, attrProps, attrName + '@' + path);
|
||||
else if (typeof attrProps === 'string') {
|
||||
attrProps = {
|
||||
type: attrProps
|
||||
};
|
||||
}
|
||||
|
||||
buildAttribute(attr, attrProps, attrName + '@' + path);
|
||||
|
||||
if (localName === '*') {
|
||||
attr.dynamicAttribute = true;
|
||||
if (attr.targetProperty === undefined) {
|
||||
attr.targetProperty = '*';
|
||||
}
|
||||
else if (!attr.targetProperty) {
|
||||
attr.targetProperty = null;
|
||||
}
|
||||
}
|
||||
|
||||
tag.addAttribute(attr);
|
||||
|
||||
@ -82,7 +82,7 @@ exports.update = function(runtime, Context) {
|
||||
return this;
|
||||
},
|
||||
attrs: attrs,
|
||||
t: function (handler, props, body, dynamicAttributes, namespacedProps) {
|
||||
t: function (handler, props, body, namespacedProps) {
|
||||
if (!props) {
|
||||
props = {};
|
||||
}
|
||||
@ -90,9 +90,6 @@ exports.update = function(runtime, Context) {
|
||||
if (body) {
|
||||
props.invokeBody = body;
|
||||
}
|
||||
if (dynamicAttributes) {
|
||||
props.dynamicAttributes = dynamicAttributes;
|
||||
}
|
||||
if (namespacedProps) {
|
||||
extend(props, namespacedProps);
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ module.exports = {
|
||||
}
|
||||
var argProps = [];
|
||||
var propsToRemove = [];
|
||||
node.forEachProperty(function (uri, name, value) {
|
||||
if (uri === '' && name.startsWith('arg-')) {
|
||||
node.forEachProperty(function (namespace, name, value) {
|
||||
if (namespace === '' && name.startsWith('arg-')) {
|
||||
var argName = name.substring('arg-'.length);
|
||||
argProps.push(JSON.stringify(argName) + ': ' + value);
|
||||
propsToRemove.push(name);
|
||||
|
||||
@ -3,9 +3,8 @@
|
||||
|
||||
<tlib-version>1.0</tlib-version>
|
||||
|
||||
<uri>http://raptorjs.org/templates/async</uri>
|
||||
<short-name>async</short-name>
|
||||
<prefix>async</prefix>
|
||||
<namespace>http://raptorjs.org/templates/async</namespace>
|
||||
<namespace>async</namespace>
|
||||
|
||||
<tag>
|
||||
|
||||
|
||||
@ -3,9 +3,8 @@
|
||||
|
||||
<tlib-version>1.0</tlib-version>
|
||||
|
||||
<uri>http://raptorjs.org/templates/caching</uri>
|
||||
<short-name>caching</short-name>
|
||||
<prefix>caching</prefix>
|
||||
<namespace>http://raptorjs.org/templates/caching</namespace>
|
||||
<namespace>caching</namespace>
|
||||
|
||||
<tag>
|
||||
|
||||
|
||||
@ -49,22 +49,22 @@ CoreTagTransformer.prototype = {
|
||||
this.findNestedAttrs(node, compiler, template);
|
||||
var inputAttr;
|
||||
var forEachNode;
|
||||
var uri;
|
||||
var namespace;
|
||||
var tag;
|
||||
var nestedTag;
|
||||
var coreNS = compiler.taglibs.resolveNamespace('core');
|
||||
|
||||
function forEachProp(callback, thisObj) {
|
||||
node.forEachAttributeAnyNS(function (attr) {
|
||||
if (attr.uri === 'http://www.w3.org/2000/xmlns/' || attr.uri === 'http://www.w3.org/XML/1998/namespace' || attr.prefix == 'xmlns') {
|
||||
if (attr.namespace === 'http://www.w3.org/2000/xmlns/' || attr.namespace === 'http://www.w3.org/XML/1998/namespace' || attr.prefix == 'xmlns') {
|
||||
return; //Skip xmlns attributes
|
||||
}
|
||||
var prefix = attr.prefix;
|
||||
var attrUri = attr.uri;
|
||||
var attrUri = attr.namespace;
|
||||
var resolvedAttrNamespace = attrUri ? compiler.taglibs.resolveNamespace(attrUri) : null;
|
||||
attrUri = attr.prefix && resolvedAttrNamespace === tag.taglib.id ? null : attr.uri;
|
||||
attrUri = attr.prefix && resolvedAttrNamespace === tag.taglib.id ? null : attr.namespace;
|
||||
|
||||
var attrDef = compiler.taglibs.getAttribute(uri, node.localName, attrUri, attr.localName);
|
||||
var attrDef = compiler.taglibs.getAttribute(namespace, node.localName, attrUri, attr.localName);
|
||||
var type = attrDef ? attrDef.type || 'string' : 'string';
|
||||
|
||||
var taglibIdForTag = compiler.taglibs.resolveNamespaceForTag(tag);
|
||||
@ -77,8 +77,9 @@ CoreTagTransformer.prototype = {
|
||||
prefix = '';
|
||||
}
|
||||
|
||||
var isAttrForTaglib = compiler.taglibs.isTaglib(attrUri);
|
||||
if (!attrDef && (isAttrForTaglib || !tag.dynamicAttributes)) {
|
||||
|
||||
if (!attrDef) {
|
||||
// var isAttrForTaglib = compiler.taglibs.isTaglib(attrUri);
|
||||
//Tag doesn't allow dynamic attributes
|
||||
node.addError('The tag "' + tag.name + '" in taglib "' + taglibIdForTag + '" does not support attribute "' + attr + '"');
|
||||
return;
|
||||
@ -98,7 +99,9 @@ CoreTagTransformer.prototype = {
|
||||
|
||||
}
|
||||
var propName;
|
||||
if (attrDef) {
|
||||
if (attrDef.dynamicAttribute) {
|
||||
propName = attr.localName;
|
||||
} else {
|
||||
if (attrDef.targetProperty) {
|
||||
propName = attrDef.targetProperty;
|
||||
} else if (attrDef.preserveName) {
|
||||
@ -106,8 +109,6 @@ CoreTagTransformer.prototype = {
|
||||
} else {
|
||||
propName = removeDashes(attr.localName);
|
||||
}
|
||||
} else {
|
||||
propName = attr.localName;
|
||||
}
|
||||
callback.call(thisObj, attrUri, propName, value, prefix, attrDef);
|
||||
});
|
||||
@ -117,14 +118,14 @@ CoreTagTransformer.prototype = {
|
||||
callback.call(thisObj, '', staticProp.name, value, '', staticProp);
|
||||
});
|
||||
}
|
||||
uri = node.uri;
|
||||
if (!uri && node.isRoot() && node.localName === 'template') {
|
||||
uri = 'core';
|
||||
namespace = node.namespace;
|
||||
if (!namespace && node.isRoot() && node.localName === 'template') {
|
||||
namespace = 'core';
|
||||
}
|
||||
if (node.parentNode) {
|
||||
var parentUri = node.parentNode.uri;
|
||||
var parentUri = node.parentNode.namespace;
|
||||
var parentName = node.parentNode.localName;
|
||||
nestedTag = compiler.taglibs.getNestedTag(parentUri, parentName, uri, node.localName);
|
||||
nestedTag = compiler.taglibs.getNestedTag(parentUri, parentName, namespace, node.localName);
|
||||
if (nestedTag) {
|
||||
node.setWordWrapEnabled(false);
|
||||
node.parentNode.setProperty(nestedTag.targetProperty, node.getBodyContentExpression(template));
|
||||
@ -132,7 +133,7 @@ CoreTagTransformer.prototype = {
|
||||
return;
|
||||
}
|
||||
}
|
||||
tag = node.tag || compiler.taglibs.getTag(uri, node.localName);
|
||||
tag = node.tag || compiler.taglibs.getTag(namespace, node.localName);
|
||||
|
||||
var coreAttrHandlers = {
|
||||
'space': function(attr) {
|
||||
@ -265,7 +266,7 @@ CoreTagTransformer.prototype = {
|
||||
};
|
||||
|
||||
node.forEachAttributeAnyNS(function(attr) {
|
||||
var attrNS = attr.uri;
|
||||
var attrNS = attr.namespace;
|
||||
if (!attrNS) {
|
||||
return;
|
||||
}
|
||||
@ -273,7 +274,7 @@ CoreTagTransformer.prototype = {
|
||||
attrNS = compiler.taglibs.resolveNamespace(attrNS);
|
||||
|
||||
if (attrNS === coreNS) {
|
||||
node.removeAttributeNS(attr.uri, attr.localName);
|
||||
node.removeAttributeNS(attr.namespace, attr.localName);
|
||||
var handler = coreAttrHandlers[attr.localName];
|
||||
if (!handler) {
|
||||
node.addError('Unsupported attribute: ' + attr.qName);
|
||||
@ -301,15 +302,15 @@ CoreTagTransformer.prototype = {
|
||||
// be used to include the output of rendering a template
|
||||
IncludeNode.convertNode(node, tag.template);
|
||||
}
|
||||
forEachProp(function (uri, name, value, prefix, attrDef) {
|
||||
|
||||
if (attrDef) {
|
||||
node.setPropertyNS(uri, name, value);
|
||||
} else {
|
||||
if (tag.dynamicAttributesRemoveDashes === true) {
|
||||
forEachProp(function (namespace, name, value, prefix, attrDef) {
|
||||
if (attrDef.dynamicAttribute && attrDef.targetProperty) {
|
||||
if (attrDef.removeDashes === true) {
|
||||
name = removeDashes(name);
|
||||
}
|
||||
node.addDynamicAttribute(prefix ? prefix + ':' + name : name, value);
|
||||
node.setDynamicAttributesProperty(attrDef.targetProperty);
|
||||
} else {
|
||||
node.setPropertyNS(namespace, name, value);
|
||||
}
|
||||
});
|
||||
} else if (tag.nodeClass) {
|
||||
@ -317,19 +318,19 @@ CoreTagTransformer.prototype = {
|
||||
extend(node, NodeCompilerClass.prototype);
|
||||
NodeCompilerClass.call(node);
|
||||
node.setNodeClass(NodeCompilerClass);
|
||||
forEachProp(function (uri, name, value) {
|
||||
node.setPropertyNS(uri, name, value);
|
||||
forEachProp(function (namespace, name, value) {
|
||||
node.setPropertyNS(namespace, name, value);
|
||||
});
|
||||
}
|
||||
} else if (uri && compiler.isTaglib(uri)) {
|
||||
node.addError('Tag ' + node.toString() + ' is not allowed for taglib "' + uri + '"');
|
||||
} else if (namespace && compiler.isTaglib(namespace)) {
|
||||
node.addError('Tag ' + node.toString() + ' is not allowed for taglib "' + namespace + '"');
|
||||
}
|
||||
},
|
||||
findNestedAttrs: function (node, compiler, template) {
|
||||
var coreNS = compiler.taglibs.resolveNamespace('core');
|
||||
|
||||
node.forEachChild(function (child) {
|
||||
if (compiler.taglibs.resolveNamespace(child.uri) === coreNS && child.localName === 'attr') {
|
||||
if (compiler.taglibs.resolveNamespace(child.namespace) === coreNS && child.localName === 'attr') {
|
||||
this.handleAttr(child, compiler, template);
|
||||
}
|
||||
}, this);
|
||||
@ -343,7 +344,7 @@ CoreTagTransformer.prototype = {
|
||||
var hasValue = node.hasAttribute('value');
|
||||
var attrName = node.getAttribute('name');
|
||||
var attrValue = node.getAttribute('value');
|
||||
var attrUri = node.getAttribute('uri') || '';
|
||||
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 + '"' : ''));
|
||||
@ -351,7 +352,7 @@ CoreTagTransformer.prototype = {
|
||||
}
|
||||
node.removeAttribute('name');
|
||||
node.removeAttribute('value');
|
||||
node.removeAttribute('uri');
|
||||
node.removeAttribute('namespace');
|
||||
node.removeAttribute('prefix');
|
||||
if (node.hasAttributesAnyNS()) {
|
||||
var invalidAttrs = node.getAllAttributes().map(function (attr) {
|
||||
|
||||
@ -15,6 +15,9 @@
|
||||
*/
|
||||
'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);
|
||||
@ -60,12 +63,12 @@ IncludeNode.prototype = {
|
||||
} else if (resourcePath = this.getAttribute('resource')) {
|
||||
var isStatic = this.getProperty('static') !== false;
|
||||
if (isStatic) {
|
||||
var resource = require('raptor-resources').findResource(resourcePath);
|
||||
if (!resource.exists()) {
|
||||
this.addError('"each" attribute is required');
|
||||
resourcePath = nodePath.resolve(template.dirname, resourcePath);
|
||||
if (!fs.existsSync(resourcePath)) {
|
||||
this.addError('Resource not found: ' + resourcePath);
|
||||
return;
|
||||
}
|
||||
template.write(stringify(resource.readAsString()));
|
||||
template.write(stringify(fs.readFileSync(resourcePath, {encoding: 'utf8'})));
|
||||
}
|
||||
} else {
|
||||
this.addError('"template" or "resource" attribute is required');
|
||||
|
||||
@ -33,19 +33,24 @@ function addHandlerVar(template, renderer) {
|
||||
function getPropsStr(props, template) {
|
||||
var propsArray = [];
|
||||
if (props) {
|
||||
forEachEntry(props, function (name, value) {
|
||||
if (value instanceof Expression) {
|
||||
var expressionStr;
|
||||
template.indent(function () {
|
||||
expressionStr = value.expression.toString();
|
||||
});
|
||||
propsArray.push(template.indentStr(1) + stringify(name) + ': ' + expressionStr);
|
||||
} else if (typeof value === 'string' || typeof value === 'object') {
|
||||
propsArray.push(template.indentStr(1) + stringify(name) + ': ' + stringify(value));
|
||||
} else {
|
||||
propsArray.push(template.indentStr(1) + stringify(name) + ': ' + value);
|
||||
}
|
||||
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 {
|
||||
@ -76,6 +81,9 @@ TagHandlerNode.prototype = {
|
||||
}
|
||||
this.dynamicAttributes[name] = value;
|
||||
},
|
||||
setDynamicAttributesProperty: function(name) {
|
||||
this.dynamicAttributesProperty = name;
|
||||
},
|
||||
addPreInvokeCode: function (code) {
|
||||
this.preInvokeCode.push(code);
|
||||
},
|
||||
@ -135,12 +143,21 @@ TagHandlerNode.prototype = {
|
||||
template.indent().code(code).code('\n');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
template.contextMethodCall('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.getProperties()[_this.dynamicAttributesProperty] = template.makeExpression(getPropsStr(_this.dynamicAttributes, template));
|
||||
});
|
||||
}
|
||||
|
||||
template.code(getPropsStr(_this.getProperties(), template));
|
||||
}
|
||||
if (_this.hasChildren()) {
|
||||
@ -151,13 +168,6 @@ TagHandlerNode.prototype = {
|
||||
template.code(',\n').line('function(' + bodyParams.join(',') + ') {').indent(function () {
|
||||
_this.generateCodeForChildren(template);
|
||||
}).indent().code('}');
|
||||
} else {
|
||||
if (hasNamespacedProps || _this.dynamicAttributes) {
|
||||
template.code(',\n').indent().code('null');
|
||||
}
|
||||
}
|
||||
if (_this.dynamicAttributes) {
|
||||
template.code(',\n').indent().code(getPropsStr(_this.dynamicAttributes, template));
|
||||
} else {
|
||||
if (hasNamespacedProps) {
|
||||
template.code(',\n').indent().code('null');
|
||||
@ -166,11 +176,11 @@ TagHandlerNode.prototype = {
|
||||
if (hasNamespacedProps) {
|
||||
template.code(',\n').line('{').indent(function () {
|
||||
var first = true;
|
||||
forEachEntry(namespacedProps, function (uri, props) {
|
||||
forEachEntry(namespacedProps, function (namespace, props) {
|
||||
if (!first) {
|
||||
template.code(',\n');
|
||||
}
|
||||
template.code(template.indentStr() + '"' + uri + '": ' + getPropsStr(props, template));
|
||||
template.code(template.indentStr() + '"' + namespace + '": ' + getPropsStr(props, template));
|
||||
first = false;
|
||||
});
|
||||
}).indent().code('}');
|
||||
|
||||
@ -34,38 +34,7 @@ TemplateNode.prototype = {
|
||||
} else {
|
||||
params = null;
|
||||
}
|
||||
this.forEachProperty(function (uri, name, value) {
|
||||
if (!uri) {
|
||||
uri = this.uri;
|
||||
}
|
||||
if (name === 'functions' || name === 'importFunctions' || name === 'importHelperFunctions') {
|
||||
value.split(/\s*[,;]\s*/g).forEach(function (funcName) {
|
||||
var func = template.compiler.taglibs.getFunction(uri, funcName);
|
||||
if (!func) {
|
||||
this.addError('Function with name "' + funcName + '" not found in taglib "' + uri + '"');
|
||||
} else {
|
||||
template.addHelperFunction(func.functionClass, funcName, func.bindToContext === true);
|
||||
}
|
||||
}, this);
|
||||
} else if (name === 'importHelperObject') {
|
||||
var varName = value;
|
||||
if (!template.compiler.taglibs.isTaglib(uri)) {
|
||||
this.addError('Helper object not found for taglib "' + uri + '". Taglib with URI "' + uri + '" not found.');
|
||||
} else {
|
||||
var helperObject = template.compiler.taglibs.getHelperObject(uri);
|
||||
if (!helperObject) {
|
||||
this.addError('Helper object not found for taglib "' + uri + '"');
|
||||
} else {
|
||||
if (helperObject.className) {
|
||||
template.addVar(varName, 'context.o(' + JSON.stringify(helperObject.className) + ')');
|
||||
} else if (helperObject.moduleName) {
|
||||
template.addStaticVar(varName, 'require(' + JSON.stringify(helperObject.moduleName) + ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
|
||||
this.generateCodeForChildren(template);
|
||||
}
|
||||
};
|
||||
|
||||
@ -36,7 +36,7 @@ WithNode.prototype = {
|
||||
}
|
||||
});
|
||||
var varDefs = [];
|
||||
raptor.forEach(withVars, function (withVar, i) {
|
||||
withVars.forEach(function (withVar, i) {
|
||||
if (!varNameRegExp.test(withVar.name)) {
|
||||
this.addError('Invalid variable name of "' + withVar.name + '" in "' + vars + '"');
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
|
||||
<tlib-version>1.0</tlib-version>
|
||||
|
||||
<alias>http://raptorjs.org/templates/core</alias>
|
||||
<alias>core</alias>
|
||||
<alias>c</alias>
|
||||
<namespace>http://raptorjs.org/templates/core</namespace>
|
||||
<namespace>core</namespace>
|
||||
<namespace>c</namespace>
|
||||
|
||||
<tag id="template">
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ HtmlTagTransformer.prototype = {
|
||||
var preserveWhitespace = options.preserveWhitespace || {};
|
||||
var allowSelfClosing = options.allowSelfClosing || {};
|
||||
var startTagOnly = options.startTagOnly || {};
|
||||
var lookupKey = node.uri ? node.uri + ':' + node.localName : node.localName;
|
||||
var lookupKey = node.namespace ? node.namespace + ':' + node.localName : node.localName;
|
||||
if (node.isPreserveWhitespace() == null) {
|
||||
if (preserveWhitespace[lookupKey] === true) {
|
||||
node.setPreserveWhitespace(true);
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
|
||||
<tlib-version>1.0</tlib-version>
|
||||
|
||||
<alias>http://raptorjs.org/templates/html</alias>
|
||||
<alias>html</alias>
|
||||
<namespace>http://raptorjs.org/templates/html</namespace>
|
||||
<namespace>html</namespace>
|
||||
|
||||
<tag>
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<raptor-taglib>
|
||||
<tlib-version>1.0</tlib-version>
|
||||
<short-name>layout</short-name>
|
||||
<uri>http://raptorjs.org/templates/layout</uri>
|
||||
<namespace>layout</namespace>
|
||||
<namespace>http://raptorjs.org/templates/layout</namespace>
|
||||
|
||||
<tag name="use" renderer="raptor/templating/taglibs/layout/UseTag" dynamic-attributes="true" dynamic-attributes-remove-dashes="true">
|
||||
<attribute name="template"/>
|
||||
|
||||
@ -5,7 +5,7 @@ module.exports = {
|
||||
node.setProperty('templatePath', templatePath);
|
||||
function convertDependencyTags(parent) {
|
||||
parent.forEachChild(function (child) {
|
||||
if (child.isElementNode() && !child.uri) {
|
||||
if (child.isElementNode() && !child.namespace) {
|
||||
// Convert unnamespaced element nodes to "DependencyTag" nodes
|
||||
child.tag = compiler.taglibs.getTag('optimizer', 'dependency');
|
||||
if (child.localName !== 'dependency') {
|
||||
@ -29,7 +29,7 @@ module.exports = {
|
||||
});
|
||||
}
|
||||
node.forEachChild(function (child) {
|
||||
if (!child.uri && (child.tagName === 'dependencies' || child.tagName === 'includes')) {
|
||||
if (!child.namespace && (child.tagName === 'dependencies' || child.tagName === 'includes')) {
|
||||
child.tag = compiler.taglibs.getTag('optimizer', 'dependencies');
|
||||
convertDependencyTags(child);
|
||||
}
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
|
||||
|
||||
<tlib-version>1.0</tlib-version>
|
||||
<short-name>optimizer</short-name>
|
||||
<uri>http://raptorjs.org/templates/optimizer</uri>
|
||||
<namespace>optimizer</namespace>
|
||||
<namespace>http://raptorjs.org/templates/optimizer</namespace>
|
||||
|
||||
<tag>
|
||||
<name>page</name>
|
||||
|
||||
@ -156,7 +156,7 @@ WidgetsTagTransformer.prototype = {
|
||||
node.setAttribute('id', template.makeExpression('widget.elId(' + JSON.stringify(widgetElIdAttr) + ')'));
|
||||
}
|
||||
}
|
||||
if (node.localName === 'widget' && node.uri === widgetsNS) {
|
||||
if (node.localName === 'widget' && node.namespace === widgetsNS) {
|
||||
if (node.getAttribute('id') != null) {
|
||||
node.setProperty('scope', template.makeExpression('widget'));
|
||||
}
|
||||
|
||||
@ -57,13 +57,13 @@ describe('raptor-templates/compiler' , function() {
|
||||
testCompiler('test-project/custom-tag.rhtml');
|
||||
});
|
||||
|
||||
it('should compile a template with <c:invoke>', function() {
|
||||
testCompiler('test-project/tabs.rhtml');
|
||||
});
|
||||
// it.only('should compile a template with <c:invoke>', function() {
|
||||
// testCompiler('test-project/tabs.rhtml');
|
||||
// });
|
||||
|
||||
it.only('should compile a template with <c:include>', function() {
|
||||
testCompiler('test-project/test-templates/include.rhtml');
|
||||
});
|
||||
// it('should compile a template with <c:include>', function() {
|
||||
// testCompiler('test-project/test-templates/include.rhtml');
|
||||
// });
|
||||
|
||||
|
||||
});
|
||||
|
||||
@ -59,15 +59,15 @@ function testRender(path, data, done, options) {
|
||||
describe('raptor-templates' , function() {
|
||||
|
||||
beforeEach(function(done) {
|
||||
for (var k in require.cache) {
|
||||
if (require.cache.hasOwnProperty(k)) {
|
||||
delete require.cache[k];
|
||||
}
|
||||
}
|
||||
// for (var k in require.cache) {
|
||||
// if (require.cache.hasOwnProperty(k)) {
|
||||
// delete require.cache[k];
|
||||
// }
|
||||
// }
|
||||
|
||||
require('raptor-logging').configureLoggers({
|
||||
'raptor-templates': 'INFO'
|
||||
});
|
||||
// require('raptor-logging').configureLoggers({
|
||||
// 'raptor-templates': 'INFO'
|
||||
// });
|
||||
|
||||
done();
|
||||
});
|
||||
@ -206,7 +206,7 @@ describe('raptor-templates' , function() {
|
||||
});
|
||||
|
||||
it("should allow for an element to be replaced with the result of an expression", function(done) {
|
||||
testRender("test-project/test-templates/replace.rhtml", {message: "Hello World!"});
|
||||
testRender("test-project/test-templates/replace.rhtml", {message: "Hello World!"}, done);
|
||||
});
|
||||
|
||||
it("should allow for includes", function(done) {
|
||||
@ -221,27 +221,6 @@ describe('raptor-templates' , function() {
|
||||
testRender("test-project/test-templates/require.rhtml", {}, done);
|
||||
});
|
||||
|
||||
it("should allow for context helper functions", function(done) {
|
||||
|
||||
var context = require('raptor/templating').createContext();
|
||||
context.getAttributes().loggedInUser = {
|
||||
firstName: "John",
|
||||
lastName: "Doe"
|
||||
};
|
||||
|
||||
testRender("test-project/test-templates/context-helper-functions-shortname.rhtml", {}, context, done);
|
||||
|
||||
|
||||
testRender("test-project/test-templates/context-helper-functions-uri.rhtml", {}, context, done);
|
||||
});
|
||||
|
||||
it("should allow for template imports", function(done) {
|
||||
testRender("test-project/test-templates/imports1.rhtml", {showConditionalTab: false}, done);
|
||||
});
|
||||
|
||||
it("should allow for template simple imports", function(done) {
|
||||
testRender("test-project/test-templates/imports2.rhtml", {showConditionalTab: false}, done);
|
||||
});
|
||||
|
||||
// it("should handle errors correctly", function(done) {
|
||||
|
||||
@ -308,9 +287,13 @@ describe('raptor-templates' , function() {
|
||||
testRender("test-project/test-templates/conditional-attributes.rhtml", {}, done);
|
||||
});
|
||||
|
||||
it("should allow for dynamic attributes", function(done) {
|
||||
it("should allow for dynamic attributes to be passed to tag renderer using a custom property name", function(done) {
|
||||
testRender("test-project/test-templates/dynamic-attributes.rhtml", {}, done);
|
||||
});
|
||||
|
||||
it("should allow for dynamic attributes to be passed to tag renderer", function(done) {
|
||||
testRender("test-project/test-templates/dynamic-attributes2.rhtml", {}, done);
|
||||
});
|
||||
|
||||
// it("should allow for nodes to be converted to expressions", function(done) {
|
||||
// var ElementNode = require('raptor/templating/compiler/ElementNode');
|
||||
|
||||
@ -125,7 +125,7 @@ describe('raptor-templates/compiler/taglibs' , function() {
|
||||
transformers.push(transformer);
|
||||
});
|
||||
|
||||
expect(transformers.length).to.equal(1);
|
||||
expect(transformers.length).to.equal(2);
|
||||
});
|
||||
|
||||
it('should lookup tag transformers correctly for namespaced tag with transformer', function() {
|
||||
@ -139,7 +139,7 @@ describe('raptor-templates/compiler/taglibs' , function() {
|
||||
transformers.push(transformer);
|
||||
});
|
||||
|
||||
expect(transformers.length).to.equal(1);
|
||||
expect(transformers.length).to.equal(2);
|
||||
|
||||
lookup = taglibLookup.buildLookup(nodePath.join(__dirname, 'test-project/transformers'));
|
||||
|
||||
@ -148,18 +148,36 @@ describe('raptor-templates/compiler/taglibs' , function() {
|
||||
transformers.push(transformer);
|
||||
});
|
||||
|
||||
expect(transformers.length).to.equal(2);
|
||||
expect(transformers[0].name).to.equal('foo');
|
||||
expect(transformers[1].name).to.equal('CoreTagTransformer');
|
||||
expect(transformers.length).to.equal(3);
|
||||
expect(transformers[0].path.indexOf('HtmlTagTransformer')).to.not.equal(-1);
|
||||
expect(transformers[1].name).to.equal('foo');
|
||||
expect(transformers[2].name).to.equal('CoreTagTransformer');
|
||||
|
||||
transformers = [];
|
||||
lookup.forEachTagTransformer('transform', 'bar', function(transformer) {
|
||||
transformers.push(transformer);
|
||||
});
|
||||
|
||||
expect(transformers.length).to.equal(2);
|
||||
expect(transformers[0].name).to.equal('CoreTagTransformer');
|
||||
expect(transformers[1].name).to.equal('bar');
|
||||
expect(transformers.length).to.equal(3);
|
||||
expect(transformers[0].path.indexOf('HtmlTagTransformer')).to.not.equal(-1);
|
||||
expect(transformers[1].name).to.equal('CoreTagTransformer');
|
||||
expect(transformers[2].name).to.equal('bar');
|
||||
});
|
||||
|
||||
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].name).to.equal('HTagTransformer');
|
||||
expect(transformers[1].name).to.equal('CoreTagTransformer');
|
||||
expect(transformers[2].name).to.equal('ElseTagTransformer');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
15
test/test-project/dynamic-attributes-tag.js
Normal file
15
test/test-project/dynamic-attributes-tag.js
Normal file
@ -0,0 +1,15 @@
|
||||
exports.render = function(input, context) {
|
||||
context.write("test: " + input.test + "|");
|
||||
var dynamicAttributes = input.dynamicAttributes;
|
||||
|
||||
if (dynamicAttributes) {
|
||||
var keys = Object.keys(dynamicAttributes).sort();
|
||||
var entries = keys.map(function(key) {
|
||||
return key+"="+dynamicAttributes[key];
|
||||
});
|
||||
context.write("dynamic attributes: [" + entries.join(", ") + "]");
|
||||
}
|
||||
else {
|
||||
context.write("dynamic attributes: []");
|
||||
}
|
||||
};
|
||||
15
test/test-project/dynamic-attributes-tag2.js
Normal file
15
test/test-project/dynamic-attributes-tag2.js
Normal file
@ -0,0 +1,15 @@
|
||||
exports.render = function(input, context) {
|
||||
context.write("test: " + input.test + "|");
|
||||
var dynamicAttributes = input['*'];
|
||||
|
||||
if (dynamicAttributes) {
|
||||
var keys = Object.keys(dynamicAttributes).sort();
|
||||
var entries = keys.map(function(key) {
|
||||
return key+"="+dynamicAttributes[key];
|
||||
});
|
||||
context.write("dynamic attributes: [" + entries.join(", ") + "]");
|
||||
}
|
||||
else {
|
||||
context.write("dynamic attributes: []");
|
||||
}
|
||||
};
|
||||
@ -22,6 +22,23 @@
|
||||
"attributes": {
|
||||
"title": "string"
|
||||
}
|
||||
},
|
||||
"dynamic-attributes": {
|
||||
"renderer": "./dynamic-attributes-tag.js",
|
||||
"attributes": {
|
||||
"test": "string",
|
||||
"*": {
|
||||
"type": "string",
|
||||
"target-property": "dynamicAttributes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dynamic-attributes2": {
|
||||
"renderer": "./dynamic-attributes-tag2.js",
|
||||
"attributes": {
|
||||
"test": "string",
|
||||
"*": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
<hello>
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
<div></div><div class="some-class"></div><div></div>
|
||||
@ -1,13 +0,0 @@
|
||||
<c:template
|
||||
xmlns:c="core"
|
||||
xmlns:test="test"
|
||||
test:functions="user,isLoggedIn">
|
||||
|
||||
<c:if test="isLoggedIn()">
|
||||
Hello ${user().firstName} ${user().lastName}!
|
||||
</c:if>
|
||||
<c:if test="!isLoggedIn()">
|
||||
You are not logged in.
|
||||
</c:if>
|
||||
|
||||
</c:template>
|
||||
@ -1,13 +0,0 @@
|
||||
<c:template
|
||||
xmlns:c="core"
|
||||
xmlns:test="http://raptorjs.org/templates/test"
|
||||
test:functions="user,isLoggedIn">
|
||||
|
||||
<c:if test="isLoggedIn()">
|
||||
Hello ${user().firstName} ${user().lastName}!
|
||||
</c:if>
|
||||
<c:if test="!isLoggedIn()">
|
||||
You are not logged in.
|
||||
</c:if>
|
||||
|
||||
</c:template>
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
test: Hello|dynamic attributes: [class=my-class, id=myId]
|
||||
@ -0,0 +1,6 @@
|
||||
<template
|
||||
xmlns:c="http://raptorjs.org/templates/core"
|
||||
xmlns:test="http://raptorjs.org/templates/test">
|
||||
|
||||
<test:dynamic-attributes2 test="World" class="my-class" id="myId"/>
|
||||
</template>
|
||||
@ -0,0 +1 @@
|
||||
test: World|dynamic attributes: [class=my-class, id=myId]
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
A , B , C , <div>C</div>
|
||||
@ -1,21 +0,0 @@
|
||||
<template
|
||||
params="showConditionalTab"
|
||||
imports="
|
||||
@if from http://raptorjs.org/templates/core;
|
||||
* from test;">
|
||||
|
||||
<tabs>
|
||||
<tab title="Tab 1">
|
||||
Tab 1 content
|
||||
</tab>
|
||||
|
||||
<tab title="Tab 2">
|
||||
Tab 2 content
|
||||
</tab>
|
||||
|
||||
<tab title="Tab 3" if="showConditionalTab">
|
||||
Tab 3 content
|
||||
</tab>
|
||||
</tabs>
|
||||
|
||||
</template>
|
||||
@ -1,19 +0,0 @@
|
||||
<template
|
||||
params="showConditionalTab"
|
||||
imports="core;test">
|
||||
|
||||
<test-tabs>
|
||||
<test-tab title="Tab 1">
|
||||
Tab 1 content
|
||||
</test-tab>
|
||||
|
||||
<test-tab title="Tab 2">
|
||||
Tab 2 content
|
||||
</test-tab>
|
||||
|
||||
<test-tab title="Tab 3" c-if="showConditionalTab">
|
||||
Tab 3 content
|
||||
</test-tab>
|
||||
</test-tabs>
|
||||
|
||||
</template>
|
||||
@ -3,6 +3,6 @@
|
||||
params="">
|
||||
|
||||
BEGIN
|
||||
<c:include resource="/test-templates/include-resource-target.txt" static="true"/>
|
||||
<c:include resource="include-resource-target.txt" static="true"/>
|
||||
END
|
||||
</c:template>
|
||||
@ -0,0 +1 @@
|
||||
BEGIN Hello World! END
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
<html><head><title>Optimizer: Server Includes</title></head><body>Hello World! <script>$(function() { alert('test'); })</script></body></html>
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
<span title="Popover Title" data-content="Popover Content">Link Text</span><span title="Popover Title" data-content="Popover Content">Link Text</span>
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
<div class="over-50"></div><div></div><div class="over-50"></div><div class="#"></div><span class="under;-50\"></span><input type="checked" checked>Hello John! Over 50
|
||||
@ -1 +1 @@
|
||||
TBD
|
||||
Hello JOHN! You have 10 new messages.
|
||||
@ -0,0 +1 @@
|
||||
1 7 11<div>1) hello</div><div>2) hello</div><div>3) hello</div>
|
||||
Loading…
x
Reference in New Issue
Block a user