var ok = require('assert').ok; var createError = require('raptor-util').createError; var forEachEntry = require('raptor-util').forEachEntry; function TaglibLookup() { this.namespaces = {}; this.tagTransformers = {}; this.tags = {}; this.textTransformers = []; this.functions = {}; this.attributes = {}; this.nestedTags = {}; this.taglibsById = {}; this.unresolvedAttributes = []; this._inputFiles = null; } TaglibLookup.prototype = { resolveNamespaceWithDefault: function(namespace, defaultTaglibId) { if (namespace === '*' || namespace === '') { return namespace; } if (namespace == null) { return defaultTaglibId; } var target = this.namespaces[namespace]; if (!target) { throw new Error('Invalid namespace of "' + namespace + '" in taglib "' + defaultTaglibId + '"'); } return target; }, resolveNamespace: function(namespace) { if (namespace == null || namespace === '') { return ''; } return this.taglibsById[namespace] ? namespace : this.namespaces[namespace]; }, resolveNamespaceForTag: function(tag) { return tag.namespace ? this.resolveNamespace(tag.namespace) : tag.taglib.id; }, isTaglib: function(namespace) { return this.taglibsById[namespace] !=null || this.namespaces[namespace] != null; }, addTaglib: function (taglib) { ok(taglib, '"taglib" is required'); ok(taglib.id, '"taglib.id" expected'); var id = taglib.id; if (this.taglibsById[id]) { // The taglib has already been added return; } var _this = this; taglib.namespaces.forEach(function(ns) { _this.namespaces[ns] = id; }); /* * Index all of the tags in the taglib by registering them * based on the tag URI and the tag name */ taglib.forEachTag(function (tag, i) { // Use the fully resolved namespace for the tag // For example: // core --> /development/raptor-templates/taglibs/core/core.rtld var tagNS = this.resolveNamespaceWithDefault(tag.namespace, id); tag.taglibId = id; var name = tag.name; var key = name.indexOf('*') === -1 ? tagNS + ':' + name : name; //The taglib will be registered using the combination of URI and tag name this.tags[key] = tag; //Register the tag using the combination of URI and tag name so that it can easily be looked up if (tag.hasTransformers()) { var tagTransformersForTags = this.tagTransformers[key] || (this.tagTransformers[key] = []); //A reference to the array of the tag transformers with the same key //Now add all of the transformers for the node (there will typically only be one...) tag.forEachTransformer(function (transformer) { if (!transformer) { throw createError(new Error('Transformer is null')); } tagTransformersForTags.push(transformer); }, this); } tag.forEachAttribute(function (attr) { if (attr.namespace) { this.unresolvedAttributes.push({ tag: tag, attr: attr }); } else { this.addAttribute(tag, attr); } }, this); }, this); /* * Now register all of the text transformers that are part of the provided taglibs */ taglib.textTransformers.forEach(function (textTransformer) { this.textTransformers.push(textTransformer); }, this); taglib.functions.forEach(function (func) { if (!func.name) { throw createError(new Error('Function name not set.')); } this.functions[taglib.id + ':' + func.name] = func; }, this); this.taglibsById[id] = taglib; }, finish: function() { for (var i=0; i