plugin.js 6.5 KB

1
  1. "use strict";function _interopDefault(a){return a&&"object"==typeof a&&"default"in a?a["default"]:a}var syntaxJsx=_interopDefault(require("@babel/plugin-syntax-jsx")),helperModuleImports=require("@babel/helper-module-imports"),kebabcase=_interopDefault(require("lodash.kebabcase")),htmlTags=_interopDefault(require("html-tags")),svgTags=_interopDefault(require("svg-tags"));const xlinkRE=/^xlink([A-Z])/,rootAttributes=["staticClass","class","style","key","ref","refInFor","slot","scopedSlots","model"],prefixes=["props","domProps","on","nativeOn","hook","attrs"],domPropsValueElements=["input","textarea","option","select"],domPropsElements=[...domPropsValueElements,"video"],mustUseDomProps=(a,b,c)=>"value"===c&&domPropsValueElements.includes(a)&&"button"!==b||"selected"===c&&"option"===a||"checked"===c&&"input"===a||"muted"===c&&"video"===a,isDirective=a=>a.startsWith(`v-`)||a.startsWith("v")&&2<=a.length&&"A"<=a[1]&&"Z">=a[1],getTag=(a,b)=>{const c=b.get("name");if(a.isJSXIdentifier(c)){const d=c.get("name").node;return!b.scope.hasBinding(d)||htmlTags.includes(d)||svgTags.includes(d)?a.stringLiteral(d):a.identifier(d)}if(a.isJSXMemberExpression(c))return transformJSXMemberExpression(a,c);throw new Error(`getTag: ${c.type} is not supported`)},getChildren=(a,b)=>b.map(b=>{if(b.isJSXText())return transformJSXText(a,b);if(b.isJSXExpressionContainer())return transformJSXExpressionContainer(a,b);if(b.isJSXSpreadChild())return transformJSXSpreadChild(a,b);if(b.isCallExpression())return b.node;throw new Error(`getChildren: ${b.type} is not supported`)}).filter(b=>null!==b&&!a.isJSXEmptyExpression(b)),addAttribute=(a,b,c,d)=>{if(b[c]){let e=!1;a.isObjectProperty(d)&&("on"===c||"nativeOn"===c)&&b[c].properties.forEach(b=>{a.isObjectProperty(b)&&b.key.value===d.key.value&&(a.isArrayExpression(b.value)?b.value.elements.push(d.value):b.value=a.arrayExpression([b.value,d.value]),e=!0)}),e||b[c].properties.push(d)}else b[c]=a.objectExpression([d])},parseMagicDomPropsInfo=(a,b,c)=>{const d=a.isStringLiteral(c)&&c.value,e=domPropsElements.includes(d);let f="";if(e){const c=b.find(b=>a.isJSXAttribute(b)&&a.isJSXIdentifier(b.get("name"))&&a.isStringLiteral(b.get("value"))&&"type"===b.get("name.name").node);f=c&&c.get("value.value").node}return{tagName:d,canContainDomProps:e,elementType:f}},parseAttributeJSXAttribute=(a,b,c,d,e)=>{const f=b.get("name");let g,h,i,j;if(h=a.isJSXNamespacedName(f)?`${f.get("namespace.name").node}:${f.get("name.name").node}`:f.get("name").node,prefixes.includes(h)&&a.isJSXExpressionContainer(b.get("value")))return a.JSXSpreadAttribute(a.objectExpression([a.objectProperty(a.stringLiteral(h),b.get("value").node.expression)]));[h,...i]=h.split("_"),[h,j]=h.split(":"),g=prefixes.find(a=>h.startsWith(a))||"attrs",h=h.replace(new RegExp(`^${g}\-?`),""),h=h[0].toLowerCase()+h.substr(1);const k=b.get("value");let l;if(!k.node)l=a.booleanLiteral(!0);else if(a.isStringLiteral(k))l=k.node;else if(a.isJSXExpressionContainer(k))mustUseDomProps(d,e,h)&&(g="domProps"),l=k.get("expression").node;else throw new Error(`getAttributes (attribute value): ${k.type} is not supported`);l._argument=j,l._modifiers=i,rootAttributes.includes(h)?c[h]=l:(isDirective(h)?(h=kebabcase(h.substr(1)),g="directives"):h=[h,...i].join("_"),h.match(xlinkRE)&&(h=h.replace(xlinkRE,(a,b)=>"xlink:"+b.toLowerCase())),addAttribute(a,c,g,a.objectProperty(a.stringLiteral(h),l)))},parseAttributeJSXSpreadAttribute=(a,b,c,d)=>{const e=b.get("argument");return a.isObjectExpression(e)&&!e.get("properties").find(b=>!a.isObjectProperty(b)||!prefixes.includes(b.get("key.name").node))?e.get("properties").forEach(b=>{addAttribute(a,c,b.get("key.name").node,a.spreadElement(b.get("value").node))}):(d.push(c),d.push({type:"vueSpread",argument:e.node}),c={}),c},getAttributes=(a,b,c,d)=>{const e=[];let f={};const{tagName:g,canContainDomProps:h,elementType:i}=parseMagicDomPropsInfo(a,b,c);return b.forEach(b=>{if(a.isJSXAttribute(b)){const c=parseAttributeJSXAttribute(a,b,f,g,i);if(c){d.node.attributes.push(c);const b=d.get("attributes"),g=b[b.length-1];f=parseAttributeJSXSpreadAttribute(a,g,f,e),g.remove()}return}if(a.isJSXSpreadAttribute(b))return void(f=parseAttributeJSXSpreadAttribute(a,b,f,e));throw new Error(`getAttributes (attribute): ${b.type} is not supported`)}),0<e.length?(0<Object.keys(f).length&&e.push(f),a.arrayExpression(e.map(b=>"vueSpread"===b.type?b.argument:transformAttributes(a,b)))):Object.entries(f).length&&transformAttributes(a,f)},transformDirectives=(a,b)=>a.arrayExpression(b.properties.map(b=>a.objectExpression([a.objectProperty(a.identifier("name"),b.key),a.objectProperty(a.identifier("value"),b.value),...(b.value._argument?[a.objectProperty(a.identifier("arg"),a.stringLiteral(b.value._argument))]:[]),...(b.value._modifiers&&0<b.value._modifiers.length?[a.objectProperty(a.identifier("modifiers"),a.objectExpression(b.value._modifiers.map(b=>a.objectProperty(a.stringLiteral(b),a.booleanLiteral(!0)))))]:[])]))),transformAttributes=(a,b)=>a.objectExpression(Object.entries(b).map(([b,c])=>"directives"===b?a.objectProperty(a.stringLiteral(b),transformDirectives(a,c)):a.objectProperty(a.stringLiteral(b),c))),transformJSXElement=(a,b)=>{if(a.isJSXAttribute(b.container))throw new Error(`getAttributes (attribute value): ${b.type} is not supported`);const c=getTag(a,b.get("openingElement")),d=getChildren(a,b.get("children")),e=b.get("openingElement"),f=getAttributes(a,e.get("attributes"),c,e),g=[c];if(f)if(a.isArrayExpression(f)){const c=helperModuleImports.addDefault(b,"@vue/babel-helper-vue-jsx-merge-props",{nameHint:"_mergeJSXProps"});g.push(a.callExpression(c,[f]))}else g.push(f);return d.length&&g.push(a.arrayExpression(d)),a.callExpression(a.identifier("h"),g)},transformJSXMemberExpression=(a,b)=>{const c=b.get("object"),d=b.get("property"),e=c.isJSXMemberExpression()?transformJSXMemberExpression(a,c):a.identifier(c.get("name").node),f=a.identifier(d.get("name").node);return a.memberExpression(e,f)},transformJSXText=(a,b)=>{const c=b.node,d=c.value.split(/\r\n|\n|\r/);let e=0;for(let c=0;c<d.length;c++)d[c].match(/[^ \t]/)&&(e=c);let f="";for(let c=0;c<d.length;c++){const a=d[c],b=0==c,g=c==d.length-1,h=c==e;let i=a.replace(/\t/g," ");b||(i=i.replace(/^[ ]+/,"")),g||(i=i.replace(/[ ]+$/,"")),i&&(!h&&(i+=" "),f+=i)}return""===f?null:a.stringLiteral(f)},transformJSXExpressionContainer=(a,b)=>b.get("expression").node,transformJSXSpreadChild=(a,b)=>a.spreadElement(b.get("expression").node);var index=a=>{const b=a.types;return{name:"babel-plugin-transform-vue-jsx",inherits:syntaxJsx,visitor:{JSXElement:{exit(a){a.replaceWith(transformJSXElement(b,a))}}}}};module.exports=index;