aboutsummaryrefslogtreecommitdiff
path: root/node_modules/babel-plugin-transform-vue-jsx/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/babel-plugin-transform-vue-jsx/index.js')
-rw-r--r--node_modules/babel-plugin-transform-vue-jsx/index.js224
1 files changed, 224 insertions, 0 deletions
diff --git a/node_modules/babel-plugin-transform-vue-jsx/index.js b/node_modules/babel-plugin-transform-vue-jsx/index.js
new file mode 100644
index 00000000..1a74a5a1
--- /dev/null
+++ b/node_modules/babel-plugin-transform-vue-jsx/index.js
@@ -0,0 +1,224 @@
+var esutils = require('esutils')
+var groupProps = require('./lib/group-props')
+var mustUseProp = require('./lib/must-use-prop')
+var addDefault = require('@babel/helper-module-imports').addDefault
+
+var isInsideJsxExpression = function (t, path) {
+ if (!path.parentPath) {
+ return false
+ }
+ if (t.isJSXExpressionContainer(path.parentPath)) {
+ return true
+ }
+ return isInsideJsxExpression(t, path.parentPath)
+}
+
+module.exports = function (babel) {
+ var t = babel.types
+
+ return {
+ inherits: require('@babel/plugin-syntax-jsx').default,
+ visitor: {
+ JSXNamespacedName (path) {
+ throw path.buildCodeFrameError(
+ 'Namespaced tags/attributes are not supported. JSX is not XML.\n' +
+ 'For attributes like xlink:href, use xlinkHref instead.'
+ )
+ },
+ JSXElement: {
+ exit (path, file) {
+ // turn tag into createElement call
+ var callExpr = buildElementCall(path.get('openingElement'), file)
+ if (path.node.children.length) {
+ // add children array as 3rd arg
+ callExpr.arguments.push(t.arrayExpression(path.node.children))
+ if (callExpr.arguments.length >= 3) {
+ callExpr._prettyCall = true
+ }
+ }
+ path.replaceWith(t.inherits(callExpr, path.node))
+ }
+ },
+ 'Program' (path) {
+ path.traverse({
+ 'ObjectMethod|ClassMethod' (path) {
+ const params = path.get('params')
+ // do nothing if there is (h) param
+ if (params.length && params[0].node.name === 'h') {
+ return
+ }
+ // do nothing if there is no JSX inside
+ const jsxChecker = {
+ hasJsx: false
+ }
+ path.traverse({
+ JSXElement () {
+ this.hasJsx = true
+ }
+ }, jsxChecker)
+ if (!jsxChecker.hasJsx) {
+ return
+ }
+ // do nothing if this method is a part of JSX expression
+ if (isInsideJsxExpression(t, path)) {
+ return
+ }
+ const isRender = path.node.key.name === 'render'
+ // inject h otherwise
+ path.get('body').unshiftContainer('body', t.variableDeclaration('const', [
+ t.variableDeclarator(
+ t.identifier('h'),
+ (
+ isRender
+ ? t.memberExpression(
+ t.identifier('arguments'),
+ t.numericLiteral(0),
+ true
+ )
+ : t.memberExpression(
+ t.thisExpression(),
+ t.identifier('$createElement')
+ )
+ )
+ )
+ ]))
+ },
+ JSXOpeningElement (path) {
+ const tag = path.get('name').node.name
+ const attributes = path.get('attributes')
+ const typeAttribute = attributes.find(attributePath => attributePath.node.name && attributePath.node.name.name === 'type')
+ const type = typeAttribute && t.isStringLiteral(typeAttribute.node.value) ? typeAttribute.node.value.value : null
+
+ attributes.forEach(attributePath => {
+ const attribute = attributePath.get('name')
+
+ if (!attribute.node) {
+ return
+ }
+
+ const attr = attribute.node.name
+
+ if (mustUseProp(tag, type, attr) && t.isJSXExpressionContainer(attributePath.node.value)) {
+ attribute.replaceWith(t.JSXIdentifier(`domProps-${attr}`))
+ }
+ })
+ }
+ })
+ }
+ }
+ }
+
+ function buildElementCall (path, file) {
+ path.parent.children = t.react.buildChildren(path.parent)
+ var tagExpr = convertJSXIdentifier(path.node.name, path.node)
+ var args = []
+
+ var tagName
+ if (t.isIdentifier(tagExpr)) {
+ tagName = tagExpr.name
+ } else if (t.isLiteral(tagExpr)) {
+ tagName = tagExpr.value
+ }
+
+ if (t.react.isCompatTag(tagName)) {
+ args.push(t.stringLiteral(tagName))
+ } else {
+ args.push(tagExpr)
+ }
+
+ var attribs = path.node.attributes
+ if (attribs.length) {
+ attribs = buildOpeningElementAttributes(attribs, path)
+ args.push(attribs)
+ }
+ return t.callExpression(t.identifier('h'), args)
+ }
+
+ function convertJSXIdentifier (node, parent) {
+ if (t.isJSXIdentifier(node)) {
+ if (node.name === 'this' && t.isReferenced(node, parent)) {
+ return t.thisExpression()
+ } else if (esutils.keyword.isIdentifierNameES6(node.name)) {
+ node.type = 'Identifier'
+ } else {
+ return t.stringLiteral(node.name)
+ }
+ } else if (t.isJSXMemberExpression(node)) {
+ return t.memberExpression(
+ convertJSXIdentifier(node.object, node),
+ convertJSXIdentifier(node.property, node)
+ )
+ }
+ return node
+ }
+
+ /**
+ * The logic for this is quite terse. It's because we need to
+ * support spread elements. We loop over all attributes,
+ * breaking on spreads, we then push a new object containing
+ * all prior attributes to an array for later processing.
+ */
+
+ function buildOpeningElementAttributes (attribs, path) {
+ var _props = []
+ var objs = []
+
+ function pushProps () {
+ if (!_props.length) return
+ objs.push(t.objectExpression(_props))
+ _props = []
+ }
+
+ while (attribs.length) {
+ var prop = attribs.shift()
+ if (t.isJSXSpreadAttribute(prop)) {
+ pushProps()
+ prop.argument._isSpread = true
+ objs.push(prop.argument)
+ } else {
+ _props.push(convertAttribute(prop))
+ }
+ }
+
+ pushProps()
+
+ objs = objs.map(function (o) {
+ return o._isSpread ? o : groupProps(o.properties, t)
+ })
+
+ if (objs.length === 1) {
+ // only one object
+ attribs = objs[0]
+ } else if (objs.length) {
+ // add prop merging helper
+ var helper = addDefault(path, 'babel-helper-vue-jsx-merge-props', { nameHint: '_mergeJSXProps' })
+ // spread it
+ attribs = t.callExpression(
+ helper,
+ [t.arrayExpression(objs)]
+ )
+ }
+ return attribs
+ }
+
+ function convertAttribute (node) {
+ var value = convertAttributeValue(node.value || t.booleanLiteral(true))
+ if (t.isStringLiteral(value) && !t.isJSXExpressionContainer(node.value)) {
+ value.value = value.value.replace(/\n\s+/g, ' ')
+ }
+ if (t.isValidIdentifier(node.name.name)) {
+ node.name.type = 'Identifier'
+ } else {
+ node.name = t.stringLiteral(node.name.name)
+ }
+ return t.inherits(t.objectProperty(node.name, value), node)
+ }
+
+ function convertAttributeValue (node) {
+ if (t.isJSXExpressionContainer(node)) {
+ return node.expression
+ } else {
+ return node
+ }
+ }
+}