mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Code comments and other code cleanup
This commit is contained in:
parent
9116bb7009
commit
2c95b1ed20
@ -30,9 +30,7 @@ TypeConverter.convert = function (value, targetType, allowExpressions) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetType === 'expression' || targetType === 'object' || targetType === 'array') {
|
||||||
|
|
||||||
if (targetType === 'expression') {
|
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
value = 'null';
|
value = 'null';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,6 +150,10 @@ module.exports = makeClass({
|
|||||||
|
|
||||||
nestedTag.isNestedTag = true;
|
nestedTag.isNestedTag = true;
|
||||||
|
|
||||||
|
if (!nestedTag.targetProperty) {
|
||||||
|
nestedTag.targetProperty = nestedTag.name;
|
||||||
|
}
|
||||||
|
|
||||||
this.nestedTags[nestedTag.name] = nestedTag;
|
this.nestedTags[nestedTag.name] = nestedTag;
|
||||||
},
|
},
|
||||||
forEachNestedTag: function (callback, thisObj) {
|
forEachNestedTag: function (callback, thisObj) {
|
||||||
|
|||||||
@ -10,18 +10,50 @@ function AttrHandlers(attr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
AttrHandlers.prototype = {
|
AttrHandlers.prototype = {
|
||||||
|
/**
|
||||||
|
* The attribute type. One of the following:
|
||||||
|
* - string (the default)
|
||||||
|
* - expression (a JavaScript expression)
|
||||||
|
* - number
|
||||||
|
* - integer
|
||||||
|
* - int
|
||||||
|
* - boolean
|
||||||
|
* - float
|
||||||
|
* - double
|
||||||
|
* - object
|
||||||
|
* - array
|
||||||
|
*
|
||||||
|
*/
|
||||||
type: function(value) {
|
type: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.type = value;
|
attr.type = value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the target property to use when mapping
|
||||||
|
* the attribute to a property on the target object.
|
||||||
|
*/
|
||||||
targetProperty: function(value) {
|
targetProperty: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.targetProperty = value;
|
attr.targetProperty = value;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The "default-value" property allows a default value
|
||||||
|
* to be provided when the attribute is not declared
|
||||||
|
* on the custom tag.
|
||||||
|
*/
|
||||||
defaultValue: function(value) {
|
defaultValue: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.defaultValue = value;
|
attr.defaultValue = value;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The "pattern" property allows the attribute
|
||||||
|
* to be matched based on a simplified regular expression.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* "pattern": "myprefix-*"
|
||||||
|
*/
|
||||||
pattern: function(value) {
|
pattern: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
if (value === true) {
|
if (value === true) {
|
||||||
@ -29,29 +61,80 @@ AttrHandlers.prototype = {
|
|||||||
attr.pattern = patternRegExp;
|
attr.pattern = patternRegExp;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If "allow-expressions" is set to true (the default) then
|
||||||
|
* the the attribute value will be parsed to find any dynamic
|
||||||
|
* parts.
|
||||||
|
*/
|
||||||
allowExpressions: function(value) {
|
allowExpressions: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.allowExpressions = value;
|
attr.allowExpressions = value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, the Marko compiler maps an attribute
|
||||||
|
* to a property by removing all dashes from the attribute
|
||||||
|
* name and converting each character after a dash to
|
||||||
|
* an uppercase character (e.g. "my-attr" --> "myAttr").
|
||||||
|
*
|
||||||
|
* Setting "preserve-name" to true will prevent this from
|
||||||
|
* happening for the attribute.
|
||||||
|
*/
|
||||||
preserveName: function(value) {
|
preserveName: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.preserveName = value;
|
attr.preserveName = value;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Declares an attribute as required. Currently, this is
|
||||||
|
* not enforced and is only used for documentation purposes.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* "required": true
|
||||||
|
*/
|
||||||
required: function(value) {
|
required: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.required = value === true;
|
attr.required = value === true;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* This is the opposite of "preserve-name" and will result
|
||||||
|
* in dashes being removed from the attribute if set to true.
|
||||||
|
*/
|
||||||
removeDashes: function(value) {
|
removeDashes: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.removeDashes = value === true;
|
attr.removeDashes = value === true;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The description of the attribute. Only used for documentation.
|
||||||
|
*/
|
||||||
description: function() {
|
description: function() {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "set-flag" property allows a "flag" to be added to a Node instance
|
||||||
|
* at compile time if the attribute is found on the node. This is helpful
|
||||||
|
* if an attribute uses a pattern and a transformer wants to have a simple
|
||||||
|
* check to see if the Node has an attribute that matched the pattern.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* "set-flag": "myCustomFlag"
|
||||||
|
*
|
||||||
|
* A Node instance can be checked if it has a flag set as shown below:
|
||||||
|
*
|
||||||
|
* if (node.hasFlag('myCustomFlag')) { ... }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
setFlag: function(value) {
|
setFlag: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
attr.setFlag = value;
|
attr.setFlag = value;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* An attribute can be marked for ignore. Ignored attributes
|
||||||
|
* will be ignored during compilation.
|
||||||
|
*/
|
||||||
ignore: function(value) {
|
ignore: function(value) {
|
||||||
var attr = this.attr;
|
var attr = this.attr;
|
||||||
if (value === true) {
|
if (value === true) {
|
||||||
|
|||||||
@ -28,19 +28,71 @@ function removeDashes(str) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleVar(tag, value, path) {
|
||||||
|
var nestedVariable;
|
||||||
|
|
||||||
function TagHandlers(tag, dirname, path) {
|
if (typeof value === 'string') {
|
||||||
|
nestedVariable = {
|
||||||
|
name: value
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
nestedVariable = {};
|
||||||
|
|
||||||
|
propertyHandlers(value, {
|
||||||
|
|
||||||
|
name: function(value) {
|
||||||
|
nestedVariable.name = value;
|
||||||
|
},
|
||||||
|
|
||||||
|
nameFromAttribute: function(value) {
|
||||||
|
nestedVariable.nameFromAttribute = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}, path);
|
||||||
|
|
||||||
|
if (!nestedVariable.name && !nestedVariable.nameFromAttribute) {
|
||||||
|
throw new Error('The "name" or "name-from-attribute" attribute is required for a nested variable');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.addNestedVariable(nestedVariable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We load tag definition using this class. Properties in the taglib
|
||||||
|
* definition (which is just a JavaScript object with properties)
|
||||||
|
* are mapped to handler methods in an instance of this type.
|
||||||
|
*
|
||||||
|
* @param {Tag} tag The initially empty Tag instance that we populate
|
||||||
|
* @param {String} dirname The full file system path associated with the tag being loaded
|
||||||
|
* @param {String} path An informational path associated with this tag (used for error reporting)
|
||||||
|
*/
|
||||||
|
function TagHandlers(tag, dirname, path, taglib) {
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.dirname = dirname;
|
this.dirname = dirname;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.taglib = taglib;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagHandlers.prototype = {
|
TagHandlers.prototype = {
|
||||||
|
/**
|
||||||
|
* The tag name
|
||||||
|
* @param {String} value The tag name
|
||||||
|
*/
|
||||||
name: function(value) {
|
name: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
tag.name = value;
|
tag.name = value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the renderer JS module to use for this tag.
|
||||||
|
*
|
||||||
|
* NOTE: We use the equivalent of require.resolve to resolve the JS module
|
||||||
|
* and use the tag directory as the "from".
|
||||||
|
*
|
||||||
|
* @param {String} value The renderer path
|
||||||
|
*/
|
||||||
renderer: function(value) {
|
renderer: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
@ -48,6 +100,12 @@ TagHandlers.prototype = {
|
|||||||
|
|
||||||
tag.renderer = path;
|
tag.renderer = path;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tag can use a renderer or a template to do the rendering. If
|
||||||
|
* a template is provided then the value should be the path to the
|
||||||
|
* template to use to render the custom tag.
|
||||||
|
*/
|
||||||
template: function(value) {
|
template: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
@ -59,12 +117,32 @@ TagHandlers.prototype = {
|
|||||||
|
|
||||||
tag.template = path;
|
tag.template = path;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Object where each property maps to an attribute definition.
|
||||||
|
* The property key will be the attribute name and the property value
|
||||||
|
* will be the attribute definition. Example:
|
||||||
|
* {
|
||||||
|
* "attributes": {
|
||||||
|
* "foo": "string",
|
||||||
|
* "bar": "expression"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
attributes: function(value) {
|
attributes: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
var path = this.path;
|
var path = this.path;
|
||||||
|
|
||||||
handleAttributes(value, tag, path);
|
handleAttributes(value, tag, path);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A custom tag can be mapped to a compile-time Node that gets
|
||||||
|
* added to the parsed Abstract Syntax Tree (AST). The Node can
|
||||||
|
* then generate custom JS code at compile time. The value
|
||||||
|
* should be a path to a JS module that gets resolved using the
|
||||||
|
* equivalent of require.resolve(path)
|
||||||
|
*/
|
||||||
nodeClass: function(value) {
|
nodeClass: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
@ -72,10 +150,22 @@ TagHandlers.prototype = {
|
|||||||
var path = resolve(value, dirname);
|
var path = resolve(value, dirname);
|
||||||
tag.nodeClass = path;
|
tag.nodeClass = path;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* If the "preserve-whitespace" property is set to true then
|
||||||
|
* all whitespace nested below the custom tag in a template
|
||||||
|
* will be stripped instead of going through the normal whitespace
|
||||||
|
* removal rules.
|
||||||
|
*/
|
||||||
preserveWhitespace: function(value) {
|
preserveWhitespace: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
tag.preserveWhitespace = !!value;
|
tag.preserveWhitespace = !!value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a custom tag has an associated transformer then the transformer
|
||||||
|
* will be called on the compile-time Node. The transformer can manipulate
|
||||||
|
* the AST using the DOM-like API to change how the code gets generated.
|
||||||
|
*/
|
||||||
transformer: function(value) {
|
transformer: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
@ -84,11 +174,19 @@ TagHandlers.prototype = {
|
|||||||
var transformer = new Taglib.Transformer();
|
var transformer = new Taglib.Transformer();
|
||||||
|
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
|
// The value is a simple string type
|
||||||
|
// so treat the value as the path to the JS
|
||||||
|
// module for the transformer
|
||||||
value = {
|
value = {
|
||||||
path: value
|
path: value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transformer is a complex type and we need
|
||||||
|
* to process each property to load the Transformer
|
||||||
|
* definition.
|
||||||
|
*/
|
||||||
propertyHandlers(value, {
|
propertyHandlers(value, {
|
||||||
path: function(value) {
|
path: function(value) {
|
||||||
var path = resolve(value, dirname);
|
var path = resolve(value, dirname);
|
||||||
@ -119,12 +217,48 @@ TagHandlers.prototype = {
|
|||||||
tag.addTransformer(transformer);
|
tag.addTransformer(transformer);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "var" property is used to declared nested variables that get
|
||||||
|
* added as JavaScript variables at compile time.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
*
|
||||||
|
* "var": "myScopedVariable",
|
||||||
|
*
|
||||||
|
* "var": {
|
||||||
|
* "name": "myScopedVariable"
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* "var": {
|
||||||
|
* "name-from-attribute": "var"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
'var': function(value) {
|
'var': function(value) {
|
||||||
var tag = this.tag;
|
handleVar(this.tag, value, '"var" in tag ' + this.path);
|
||||||
tag.addNestedVariable({
|
|
||||||
name: value
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The "vars" property is equivalent to the "var" property
|
||||||
|
* except that it expects an array of nested variables.
|
||||||
|
*/
|
||||||
|
vars: function(value) {
|
||||||
|
var tag = this.tag;
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
value.forEach(function(v, i) {
|
||||||
|
handleVar(tag, v, '"vars"[' + i + '] in tag ' + self.path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* The "body-function" property" allows the nested body content to be mapped
|
||||||
|
* to a function at compile time. The body function gets mapped to a property
|
||||||
|
* of the tag renderer at render time. The body function can have any number
|
||||||
|
* of parameters.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* - "body-function": "_handleBody(param1, param2, param3)"
|
||||||
|
*/
|
||||||
bodyFunction: function(value) {
|
bodyFunction: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
var parts = bodyFunctionRegExp.exec(value);
|
var parts = bodyFunctionRegExp.exec(value);
|
||||||
@ -149,44 +283,27 @@ TagHandlers.prototype = {
|
|||||||
|
|
||||||
tag.setBodyFunction(functionName, params);
|
tag.setBodyFunction(functionName, params);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The "body-property" property can be used to map the body content
|
||||||
|
* to a String property on the renderer's input object.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* "body-property": "label"
|
||||||
|
*/
|
||||||
bodyProperty: function(value) {
|
bodyProperty: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
tag.setBodyProperty(value);
|
tag.setBodyProperty(value);
|
||||||
},
|
},
|
||||||
vars: function(value) {
|
/**
|
||||||
var tag = this.tag;
|
* The "import-var" property can be used to add a property to the
|
||||||
if (value) {
|
* input object of the tag renderer whose value is determined by
|
||||||
value.forEach(function(v, i) {
|
* a JavaScript expression.
|
||||||
var nestedVariable;
|
*
|
||||||
|
* Example:
|
||||||
if (typeof v === 'string') {
|
* "import-var": {
|
||||||
nestedVariable = {
|
* "myTargetProperty": "data.myCompileTimeJavaScriptExpression",
|
||||||
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) {
|
importVar: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
forEachEntry(value, function(varName, varValue) {
|
forEachEntry(value, function(varName, varValue) {
|
||||||
@ -211,12 +328,42 @@ TagHandlers.prototype = {
|
|||||||
tag.addImportedVariable(importedVar);
|
tag.addImportedVariable(importedVar);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* The tag type.
|
||||||
|
*/
|
||||||
type: function(value) {
|
type: function(value) {
|
||||||
var tag = this.tag;
|
var tag = this.tag;
|
||||||
tag.type = value;
|
tag.type = value;
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Declare a nested tag.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* {
|
||||||
|
* ...
|
||||||
|
* "nested-tags": {
|
||||||
|
* "tab": {
|
||||||
|
* "target-property": "tabs",
|
||||||
|
* "isRepeated": true
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
nestedTags: function(value) {
|
nestedTags: function(value) {
|
||||||
|
var tagPath = this.path;
|
||||||
|
var taglib = this.taglib;
|
||||||
|
var dirname = this.dirname;
|
||||||
|
var tag = this.tag;
|
||||||
|
|
||||||
|
forEachEntry(value, function(nestedTagName, nestedTagDef) {
|
||||||
|
var nestedTag = loadTag(
|
||||||
|
nestedTagDef,
|
||||||
|
nestedTagName + ' of ' + tagPath,
|
||||||
|
taglib,
|
||||||
|
dirname);
|
||||||
|
nestedTag.name = nestedTagName;
|
||||||
|
tag.addNestedTag(nestedTag);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -239,7 +386,7 @@ function loadTag(tagProps, path, taglib, dirname) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagHandlers = new TagHandlers(tag, dirname, path);
|
var tagHandlers = new TagHandlers(tag, dirname, path, taglib);
|
||||||
|
|
||||||
// We add a handler for any properties that didn't match
|
// We add a handler for any properties that didn't match
|
||||||
// one of the default property handlers. This is used to
|
// one of the default property handlers. This is used to
|
||||||
@ -288,10 +435,12 @@ function loadTag(tagProps, path, taglib, dirname) {
|
|||||||
tagProps[k] = value[k];
|
tagProps[k] = value[k];
|
||||||
delete value[k];
|
delete value[k];
|
||||||
} else {
|
} else {
|
||||||
|
// The property is not a shorthand attribute or shorthand
|
||||||
|
// tag so move it over to either the tag definition
|
||||||
|
// or the attribute definition or both the tag definition
|
||||||
|
// and attribute definition.
|
||||||
var propNameDashes = removeDashes(k);
|
var propNameDashes = removeDashes(k);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (loader.tagLoader.isSupportedProperty(propNameDashes) &&
|
if (loader.tagLoader.isSupportedProperty(propNameDashes) &&
|
||||||
loader.attributeLoader.isSupportedProperty(propNameDashes)) {
|
loader.attributeLoader.isSupportedProperty(propNameDashes)) {
|
||||||
// Move over all of the properties that are associated with a tag
|
// Move over all of the properties that are associated with a tag
|
||||||
@ -365,6 +514,8 @@ function loadTag(tagProps, path, taglib, dirname) {
|
|||||||
taglib,
|
taglib,
|
||||||
dirname);
|
dirname);
|
||||||
|
|
||||||
|
// We use the '[]' suffix to indicate that a nested tag
|
||||||
|
// can be repeated
|
||||||
var isNestedTagRepeated = false;
|
var isNestedTagRepeated = false;
|
||||||
if (part.endsWith('[]')) {
|
if (part.endsWith('[]')) {
|
||||||
isNestedTagRepeated = true;
|
isNestedTagRepeated = true;
|
||||||
|
|||||||
@ -55,6 +55,15 @@ function handleTag(taglibHandlers, tagName, path) {
|
|||||||
taglib.addTag(tag);
|
taglib.addTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We load a taglib definion using this class. Properties in the taglib
|
||||||
|
* definition (which is just a JavaScript object with properties)
|
||||||
|
* are mapped to handler methods in an instance of this type.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param {Taglib} taglib The initially empty Taglib instance that we will populate
|
||||||
|
* @param {String} path The file system path to the taglib that we are loading
|
||||||
|
*/
|
||||||
function TaglibHandlers(taglib, path) {
|
function TaglibHandlers(taglib, path) {
|
||||||
ok(taglib);
|
ok(taglib);
|
||||||
ok(path);
|
ok(path);
|
||||||
@ -66,12 +75,40 @@ function TaglibHandlers(taglib, path) {
|
|||||||
|
|
||||||
TaglibHandlers.prototype = {
|
TaglibHandlers.prototype = {
|
||||||
attributes: function(value) {
|
attributes: function(value) {
|
||||||
|
// The value of the "attributes" property will be an object
|
||||||
|
// where each property maps to an attribute definition. Since these
|
||||||
|
// attributes are on the taglib they will be "global" attribute
|
||||||
|
// defintions.
|
||||||
|
//
|
||||||
|
// The property key will be the attribute name and the property value
|
||||||
|
// will be the attribute definition. Example:
|
||||||
|
// {
|
||||||
|
// "attributes": {
|
||||||
|
// "foo": "string",
|
||||||
|
// "bar": "expression"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
var taglib = this.taglib;
|
var taglib = this.taglib;
|
||||||
var path = this.path;
|
var path = this.path;
|
||||||
|
|
||||||
handleAttributes(value, taglib, path);
|
handleAttributes(value, taglib, path);
|
||||||
},
|
},
|
||||||
tags: function(tags) {
|
tags: function(tags) {
|
||||||
|
// The value of the "tags" property will be an object
|
||||||
|
// where each property maps to an attribute definition. The property
|
||||||
|
// key will be the tag name and the property value
|
||||||
|
// will be the tag definition. Example:
|
||||||
|
// {
|
||||||
|
// "tags": {
|
||||||
|
// "foo": {
|
||||||
|
// "attributes": { ... }
|
||||||
|
// },
|
||||||
|
// "bar": {
|
||||||
|
// "attributes": { ... }
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for (var tagName in tags) {
|
for (var tagName in tags) {
|
||||||
if (tags.hasOwnProperty(tagName)) {
|
if (tags.hasOwnProperty(tagName)) {
|
||||||
handleTag(this, tagName, tags[tagName]);
|
handleTag(this, tagName, tags[tagName]);
|
||||||
@ -79,6 +116,12 @@ TaglibHandlers.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
tagsDir: function(dir) {
|
tagsDir: function(dir) {
|
||||||
|
// The "tags-dir" property is used to supporting scanning
|
||||||
|
// of a directory to discover custom tags. Scanning a directory
|
||||||
|
// is a much simpler way for a developer to create custom tags.
|
||||||
|
// Only one tag is allowed per directory and the directory name
|
||||||
|
// corresponds to the tag name. We only search for directories
|
||||||
|
// one level deep.
|
||||||
var taglib = this.taglib;
|
var taglib = this.taglib;
|
||||||
var path = this.path;
|
var path = this.path;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
@ -93,6 +136,14 @@ TaglibHandlers.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
taglibImports: function(imports) {
|
taglibImports: function(imports) {
|
||||||
|
// The "taglib-imports" property allows another taglib to be imported
|
||||||
|
// into this taglib so that the tags defined in the imported taglib
|
||||||
|
// will be part of this taglib.
|
||||||
|
//
|
||||||
|
// NOTE: If a taglib import refers to a package.json file then we read
|
||||||
|
// the package.json file and automatically import *all* of the
|
||||||
|
// taglibs from the installed modules found in the "dependencies"
|
||||||
|
// section
|
||||||
var taglib = this.taglib;
|
var taglib = this.taglib;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
|
|
||||||
@ -127,6 +178,8 @@ TaglibHandlers.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
textTransformer: function(value) {
|
textTransformer: function(value) {
|
||||||
|
// Marko allows a "text-transformer" to be registered. The provided
|
||||||
|
// text transformer will be called for any static text found in a template.
|
||||||
var taglib = this.taglib;
|
var taglib = this.taglib;
|
||||||
var path = this.path;
|
var path = this.path;
|
||||||
var dirname = this.dirname;
|
var dirname = this.dirname;
|
||||||
@ -150,8 +203,20 @@ TaglibHandlers.prototype = {
|
|||||||
ok(transformer.path, '"path" is required for transformer');
|
ok(transformer.path, '"path" is required for transformer');
|
||||||
|
|
||||||
taglib.addTextTransformer(transformer);
|
taglib.addTextTransformer(transformer);
|
||||||
},
|
}
|
||||||
'*': function(name, value) {
|
};
|
||||||
|
|
||||||
|
exports.loadTaglib = function(path) {
|
||||||
|
var taglibProps = taglibReader.readTaglib(path);
|
||||||
|
|
||||||
|
var taglib = new Taglib(path);
|
||||||
|
taglib.addInputFile(path);
|
||||||
|
|
||||||
|
var taglibHandlers = new TaglibHandlers(taglib, path);
|
||||||
|
|
||||||
|
// We register a wildcard handler to handle "@my-attr" and "<my-tag>"
|
||||||
|
// properties (shorthand syntax)
|
||||||
|
taglibHandlers['*'] = function(name, value) {
|
||||||
var taglib = this.taglib;
|
var taglib = this.taglib;
|
||||||
var path = this.path;
|
var path = this.path;
|
||||||
|
|
||||||
@ -169,16 +234,7 @@ TaglibHandlers.prototype = {
|
|||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
exports.loadTaglib = function(path) {
|
|
||||||
var taglibProps = taglibReader.readTaglib(path);
|
|
||||||
|
|
||||||
var taglib = new Taglib(path);
|
|
||||||
taglib.addInputFile(path);
|
|
||||||
|
|
||||||
var taglibHandlers = new TaglibHandlers(taglib, path);
|
|
||||||
|
|
||||||
propertyHandlers(taglibProps, taglibHandlers, path);
|
propertyHandlers(taglibProps, taglibHandlers, path);
|
||||||
|
|
||||||
|
|||||||
@ -12,10 +12,12 @@
|
|||||||
"target-property": "className"
|
"target-property": "className"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@footer <footer>": {
|
"nested-tags": {
|
||||||
"@class": {
|
"footer": {
|
||||||
"type": "string",
|
"@class": {
|
||||||
"target-property": "className"
|
"type": "string",
|
||||||
|
"target-property": "className"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user