var fs ; var req = require; try { fs = req('fs'); } catch(e) { } 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('../util/resolve'); // NOTE: different implementation for browser var propertyHandlers = require('property-handlers'); var safeVarName = /^[A-Za-z_$][A-Za-z0-9_]*$/; var bodyFunctionRegExp = /^([A-Za-z_$][A-Za-z0-9_]*)(?:\(([^)]*)\))?$/; function exists(path) { try { require.resolve(path); return true; } catch(e) { return false; } } function createDefaultTagDef() { return { attributes: { '*': { type: 'string', targetProperty: null, preserveName: false } } }; } 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; }, description: function() { }, setFlag: function(value) { attr.setFlag = value; }, ignore: function(value) { if (value === true) { attr.ignore = 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); if (tagObject.attributes == null) { // allow any attributes if no attributes are declared tagObject.attributes = { '*': 'string' }; } propertyHandlers(tagObject, { name: function(value) { tag.name = value; }, renderer: function(value) { var path = resolve(value, dirname); tag.renderer = path; }, template: function(value) { var path = nodePath.resolve(dirname, value); if (!exists(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); tag.nodeClass = path; }, preserveWhitespace: function(value) { tag.preserveWhitespace = !!value; }, 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); 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 }); }, bodyFunction: function(value) { var parts = bodyFunctionRegExp.exec(value); if (!parts) { throw new Error('Invalid value of "' + value + '" for "body-function". Expected value to be of the following form: ([param1, param2, ...])'); } var functionName = parts[1]; var params = parts[2]; if (params) { params = params.trim().split(/\s*,\s*/); for (var i=0; i 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); transformer.path = path; } }, 'text-transformer in ' + path); ok(transformer.path, '"path" is required for transformer'); taglib.addTextTransformer(transformer); } }, path); taglib.id = taglib.path = path; cache[path] = taglib; return taglib; } exports.load = load;