babel-plugin-vidom-jsx
Version:
[](https://travis-ci.org/dfilatov/babel-plugin-vidom-jsx/branches) [ • 6.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = _default;
var _pluginSyntaxJsx = _interopRequireDefault(require("@babel/plugin-syntax-jsx"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
var VIDOM = 'vidom',
ELEM_BUILDER = '_ve_';
function _default(_ref) {
var types = _ref.types;
var autoRequire, requireElem;
function buildElemExpr(tagExpr, argsExpr) {
return types.callExpression(autoRequire ? types.identifier(ELEM_BUILDER) : types.memberExpression(types.identifier(VIDOM), types.identifier('elem')), [tagExpr].concat(argsExpr));
}
function buildElemArgsExpr(attrs, children, file) {
var res = [],
objList = [];
var attrList = [],
attrsExpr,
keyExpr,
htmlExpr,
refExpr,
pushAttrs = function pushAttrs() {
if (!attrList.length) {
return;
}
objList.push(types.objectExpression(attrList));
attrList = [];
};
attrs.forEach(function (attr) {
if (types.isJSXSpreadAttribute(attr)) {
pushAttrs();
objList.push(attr.argument);
} else {
switch (attr.name.name) {
case 'key':
keyExpr = getValueExpr(attr.value);
break;
case 'html':
htmlExpr = getValueExpr(attr.value);
break;
case 'ref':
refExpr = getValueExpr(attr.value);
break;
default:
attrList.push(types.objectProperty(types.stringLiteral(attr.name.name), types.isJSXExpressionContainer(attr.value) ? attr.value.expression : attr.value || types.booleanLiteral(true)));
}
}
});
pushAttrs();
if (objList.length > 0) {
if (objList.length === 1) {
attrsExpr = objList[0];
} else {
if (!types.isObjectExpression(objList[0])) {
objList.unshift(types.objectExpression([]));
}
attrsExpr = types.callExpression(file.addHelper('extends'), objList);
}
}
res.push(keyExpr || null, attrsExpr || null, htmlExpr ? htmlExpr : normalizeChildren(children), refExpr || null, htmlExpr ? types.booleanLiteral(false) : null);
var notNullLen = res.length;
while (notNullLen > 0) {
if (res[notNullLen - 1] !== null) {
break;
}
notNullLen--;
}
return (notNullLen < res.length ? res.slice(0, notNullLen) : res).map(function (expr) {
return expr === null ? types.nullLiteral() : expr;
});
}
function getValueExpr(value) {
return types.isJSXExpressionContainer(value) ? value.expression : value;
}
function normalizeChildren(children) {
var res = children.reduce(function (acc, child) {
if (types.isJSXText(child)) {
child = cleanJSXText(child);
if (child) {
acc.push(child);
}
} else if (types.isJSXExpressionContainer(child)) {
if (!types.isJSXEmptyExpression(child.expression)) {
acc.push(child.expression);
}
} else {
acc.push(child);
}
return acc;
}, []);
return res.length > 0 ? res.length > 1 ? types.arrayExpression(res) : res[0] : null;
}
function cleanJSXText(node) {
var lines = node.value.split(/\r\n|\n|\r/);
var lastNonEmptyLine = 0;
lines.forEach(function (line, i) {
if (line.match(/[^ \t]/)) {
lastNonEmptyLine = i;
}
});
var str = '';
lines.forEach(function (line, i) {
var isFirstLine = i === 0,
isLastLine = i === lines.length - 1,
isLastNonEmptyLine = i === lastNonEmptyLine;
var trimmedLine = line.replace(/\t/g, ' ');
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, '');
}
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, '');
}
if (trimmedLine) {
if (!isLastNonEmptyLine) {
trimmedLine += ' ';
}
str += trimmedLine;
}
});
if (str) {
return types.stringLiteral(str);
}
}
function buildJSXIdentifierExpr(node, parent) {
if (types.isJSXIdentifier(node)) {
if (node.name === 'this' && types.isReferenced(node, parent)) {
return types.thisExpression();
}
if (node.name === node.name.toLowerCase() && !types.isJSXMemberExpression(parent)) {
return types.stringLiteral(node.name);
}
node.type = 'Identifier';
return node;
}
if (types.isJSXMemberExpression(node)) {
return types.memberExpression(buildJSXIdentifierExpr(node.object, node), buildJSXIdentifierExpr(node.property, node));
}
return node;
}
function buildJSXFragmentExpr() {
return types.stringLiteral('fragment');
}
return {
inherits: _pluginSyntaxJsx["default"],
visitor: {
JSXElement: function JSXElement(path, file) {
requireElem = true;
var _path$node = path.node,
_path$node$openingEle = _path$node.openingElement,
name = _path$node$openingEle.name,
attributes = _path$node$openingEle.attributes,
children = _path$node.children;
path.replaceWith(buildElemExpr(buildJSXIdentifierExpr(name, path.node), buildElemArgsExpr(attributes, children, file)));
},
JSXFragment: function JSXFragment(path, file) {
requireElem = true;
path.replaceWith(buildElemExpr(buildJSXFragmentExpr(), buildElemArgsExpr([], path.node.children, file)));
},
Program: {
enter: function enter(_, _ref2) {
var opts = _ref2.opts;
autoRequire = opts.autoRequire !== false;
requireElem = false;
},
exit: function exit(path) {
if (!requireElem) {
return;
}
if (autoRequire) {
var importDeclaration = types.importDeclaration([types.importSpecifier(types.identifier(ELEM_BUILDER), types.identifier('elem'))], types.stringLiteral(VIDOM));
path.unshiftContainer('body', importDeclaration);
}
}
}
}
};
}