babel-plugin-brahmos
Advanced tools
Comparing version 0.3.0 to 0.4.0
{ | ||
"name": "babel-plugin-brahmos", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "Babel plugin to transform JSX to Brahmos Tagged Template literal", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
const jsx = require('@babel/plugin-syntax-jsx').default; | ||
const SVG_ATTRIBUTE_MAP = require('./svgAttributeMap'); | ||
@@ -71,2 +72,5 @@ const RESERVED_ATTRIBUTES = { | ||
'htmlFor': 'for', | ||
'acceptCharset': 'accept-charset', | ||
'httpEquiv': 'http-equiv', | ||
...SVG_ATTRIBUTE_MAP, | ||
}; | ||
@@ -89,8 +93,36 @@ | ||
/** | ||
* Check if svg has a dynamic part either as attribute or node part | ||
*/ | ||
function isSvgHasDynamicPart (part) { | ||
let hasDynamicPart = false; | ||
const setDynamicPart = (path) => { | ||
hasDynamicPart = true; | ||
path.stop(); | ||
}; | ||
const jsxElementVisitor = (path) => { | ||
const { openingElement } = path.node; | ||
const tagName = openingElement.name.name; | ||
if (!isHTMLElement(tagName)) { | ||
setDynamicPart(path); | ||
} | ||
}; | ||
part.traverse({ | ||
JSXSpreadAttribute: setDynamicPart, | ||
JSXExpressionContainer: setDynamicPart, | ||
JSXElement: jsxElementVisitor, | ||
}); | ||
return hasDynamicPart; | ||
} | ||
function BabelPluginBrahmos (babel) { | ||
const { types: t } = babel; | ||
function getTaggedTemplateCallExpression (node) { | ||
const { strings, expressions } = getLiteralParts(node); | ||
function getTaggedTemplateCallExpression (path) { | ||
const { strings, expressions } = getLiteralParts(path); | ||
/** | ||
@@ -111,3 +143,7 @@ * we do not need a tagged expression if there is a single expression and two empty string part | ||
function getLiteralParts (rootNode, strings = [], expressions = [], stringPart = []) { | ||
function getLiteralParts (rootPath) { | ||
const strings = []; | ||
const expressions = []; | ||
let stringPart = []; | ||
function pushToStrings (tail) { | ||
@@ -125,8 +161,17 @@ const string = stringPart.join(''); | ||
function createAttributeExpression (name, value) { | ||
return t.objectExpression([createObjectProperty(name, value)]); | ||
return t.objectExpression([createAttributeProperty(name, value)]); | ||
} | ||
function createObjectProperty (name, value) { | ||
function createAttributeProperty (name, value) { | ||
value = value || t.booleanLiteral(true); // if value is not present it means the prop is of boolean type with true value | ||
const propName = t.identifier(name.name); | ||
let attrNameStr = name.name; | ||
// if attribute has svg attribute mapping use that, otherwise use plain attribute | ||
attrNameStr = SVG_ATTRIBUTE_MAP[attrNameStr] || attrNameStr; | ||
const propName = attrNameStr.match('-|:') | ||
? t.stringLiteral(attrNameStr) | ||
: t.identifier(attrNameStr); | ||
const propValue = t.isJSXExpressionContainer(value) ? value.expression : value; | ||
@@ -186,4 +231,8 @@ return t.objectProperty(propName, propValue, false, propName.name === propValue.name); | ||
function recurseNode (node) { | ||
if (t.isJSXElement(node)) { | ||
function recursePath (path, isSVGPart) { | ||
const { node } = path; | ||
if (Array.isArray(path)) { | ||
path.forEach(recursePath); | ||
} else if (t.isJSXElement(node)) { | ||
const { openingElement, children } = node; | ||
@@ -193,3 +242,5 @@ const { attributes, name } = openingElement; | ||
if (isHTMLElement(tagName)) { | ||
isSVGPart = isSVGPart || tagName === 'svg'; | ||
if (isHTMLElement(tagName) && !(tagName === 'svg' && isSvgHasDynamicPart(path))) { | ||
// Handle opening tag | ||
@@ -239,5 +290,3 @@ stringPart.push(`<${tagName} `); | ||
// handle children | ||
children.forEach(child => { | ||
recurseNode(child); | ||
}); | ||
path.get('children').forEach(recursePath); | ||
@@ -247,3 +296,5 @@ // handle closing tag | ||
} else { | ||
const componentName = name; | ||
const componentName = name.name === 'svg' | ||
? t.stringLiteral(name.name) | ||
: jsxToObject(name); | ||
@@ -256,4 +307,4 @@ // add props | ||
} else { | ||
const { name, value } = attribute; | ||
props.push(createObjectProperty(name, value)); | ||
let { name, value } = attribute; | ||
props.push(createAttributeProperty(name, value)); | ||
} | ||
@@ -263,3 +314,3 @@ }); | ||
const createElementArguments = [ | ||
jsxToObject(componentName), | ||
componentName, | ||
t.objectExpression(props), | ||
@@ -269,3 +320,3 @@ ]; | ||
if (children && children.length) { | ||
createElementArguments.push(getTaggedTemplateCallExpression(children)); | ||
createElementArguments.push(getTaggedTemplateCallExpression(path.get('children'))); | ||
} | ||
@@ -283,10 +334,8 @@ | ||
pushToExpressions(node.expression); | ||
} else if (Array.isArray(node)) { | ||
node.forEach((nodeItem) => recurseNode(nodeItem)); | ||
} else if (t.isJSXFragment(node)) { | ||
node.children.forEach((nodeItem) => recurseNode(nodeItem)); | ||
path.get('children').forEach(recursePath); | ||
} | ||
} | ||
recurseNode(rootNode); | ||
recursePath(rootPath); | ||
@@ -303,4 +352,3 @@ // add the last template element | ||
function visitorCallback (path) { | ||
const { node } = path; | ||
const tagExpression = getTaggedTemplateCallExpression(node); | ||
const tagExpression = getTaggedTemplateCallExpression(path); | ||
path.replaceWith(tagExpression); | ||
@@ -307,0 +355,0 @@ } |
68973
7
374