'use strict'; var HtmlElement = require('./HtmlElement'); var path = require('path'); var removeDashes = require('../util/removeDashes'); var removeEscapeFunctions = require('../util/removeEscapeFunctions'); function removeExt(filename) { var ext = path.extname(filename); if (ext) { return filename.slice(0, 0 - ext.length); } else { return filename; } } function buildInputProps(node, context) { var tagDef = node.tagDef; var inputProps = {}; var builder = context.builder; node.forEachAttribute((attr) => { var attrName = attr.name; var attrDef = attr.def || context.taglibLookup.getAttribute(node.tagName, attr.name); var attrValue = removeEscapeFunctions(attr.value); if (!attrDef) { return; // Skip over attributes that are not supported } var propName; var parentPropName; if (attrDef.dynamicAttribute) { // Dynamic attributes are allowed attributes // that are not declared (i.e. "*" attributes) // if (attrDef.preserveName === false) { propName = removeDashes(attrName); } else { propName = attrName; } if (attrDef.targetProperty) { parentPropName = attrDef.targetProperty; } } else { // Attributes map to properties and we allow the taglib // author to control how an attribute name resolves // to a property name. if (attrDef.targetProperty) { propName = attrDef.targetProperty; } else if (attrDef.preserveName) { propName = attr.name; } else { propName = removeDashes(attr.name); } } if (parentPropName) { let parent = inputProps[parentPropName] = (inputProps[parentPropName] = {}); parent[propName] = attrValue; } else { inputProps[propName] = attrValue; } }); tagDef.forEachImportedVariable(function(importedVariable) { let propName = importedVariable.targetProperty; let propExpression = importedVariable.expression; inputProps[propName] = propExpression; }); if (node.body && node.body.length) { if (tagDef.bodyFunction) { let bodyFunction = tagDef.bodyFunction; let bodyFunctionName = bodyFunction.name; var bodyFunctionParams = bodyFunction.params.map(function(param) { return builder.identifier(param); }); inputProps[bodyFunctionName] = builder.functionDeclaration(bodyFunctionName, bodyFunctionParams, node.body); } else { var renderBodyFunction = context.builder.renderBodyFunction(node.body); inputProps.renderBody = renderBodyFunction; } } return context.builder.literal(inputProps); } class CustomTag extends HtmlElement { constructor(el, tagDef) { super(el); this.type = 'CustomTag'; this.tagDef = tagDef; } generateCode(codegen) { var loadRendererVar = codegen.addStaticVar('__renderer', '__helpers.r'); var tagVar = codegen.addStaticVar('__tag', '__helpers.t'); var builder = codegen.builder; var context = codegen.context; var tagDef = this.tagDef; var inputProps = buildInputProps(this, context); var rendererPath = tagDef.renderer; if (rendererPath) { let rendererRequirePath = context.getRequirePath(rendererPath); let requireRendererFunctionCall = builder.require(JSON.stringify(rendererRequirePath)); let loadRendererFunctionCall = builder.functionCall(loadRendererVar, [ requireRendererFunctionCall ]); let rendererVar = codegen.addStaticVar(removeExt(rendererPath), loadRendererFunctionCall); let tagArgs = [ 'out', rendererVar, inputProps ]; let tagFunctionCall = builder.functionCall(tagVar, tagArgs); return tagFunctionCall; } else if (tagDef.template) { let templateRequirePath = context.getRequirePath(tagDef.template); let templateVar = context.importTemplate(templateRequirePath); let renderMethod = builder.memberExpression(templateVar, builder.identifier('render')); let renderArgs = [ inputProps, 'out' ]; let renderFunctionCall = builder.functionCall(renderMethod, renderArgs); return renderFunctionCall; } } } module.exports = CustomTag;