UNPKG

@vtj/coder

Version:

VTJ 是一款基于 Vue3 + Typescript 的低代码页面可视化设计器。内置低代码引擎、渲染器和代码生成器,面向前端开发者,开箱即用。 无缝嵌入本地开发工程,不改变前端开发流程和编码习惯。

101 lines (99 loc) 15.7 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("@vtj/base"),T=require("prettier/standalone"),Z=require("prettier/plugins/html"),K=require("prettier/plugins/babel"),ee=require("prettier/plugins/postcss"),te=require("prettier/plugins/estree");function F(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const s=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,s.get?s:{enumerable:!0,get:()=>t[n]})}}return e.default=t,Object.freeze(e)}const ne=F(Z),D=F(K),L=F(ee),U=F(te);/**! * Copyright (c) 2025, VTJ.PRO All rights reserved. * @name @vtj/coder * @author CHC chenhuachun1549@dingtalk.com * @version 0.11.13 * @license <a href="https://vtj.pro/license.html">MIT License</a> */const se="0.11.13";/**! * Copyright (c) 2025, VTJ.PRO All rights reserved. * @name @vtj/core * @author CHC chenhuachun1549@dingtalk.com * @version 0.11.13 * @license <a href="https://vtj.pro/license.html">MIT License</a> */const re=["slot","template","component","img","div","p","h1","h2","h3","span","a"];f.mitt();const B={arrowParens:"always",bracketSpacing:!0,bracketSameLine:!0,endOfLine:"lf",htmlWhitespaceSensitivity:"css",insertPragma:!1,jsxBracketSameLine:!0,jsxSingleQuote:!0,printWidth:80,proseWrap:"preserve",quoteProps:"as-needed",requirePragma:!1,semi:!0,singleQuote:!0,tabWidth:2,trailingComma:"none",useTabs:!1,vueIndentScriptAndStyle:!0};async function R(t,e){return e?t:await T.format(t,{parser:"vue",...B,plugins:[ne,D,U,L]})}async function M(t,e){return e?t:await T.format(t,{parser:"babel-ts",...B,plugins:[D,U]})}async function I(t,e){return e?t:T.format(t,{parser:"scss",...B,plugins:[L]})}function S(t){return t&&t.type==="JSExpression"}function A(t){return typeof t=="object"&&t&&t.type==="JSFunction"}function v(t){return S(t)||A(t)}function V(t){return t.replace(new RegExp("this.","g"),"")}function J(t){return t.replace(/this\.context\??\./g,"")}function m(t,e=!0,n=!0,s=[]){let r=v(t)?t.value:e?JSON.stringify(t):t;return r=k(r,s),n?V(J(r)):J(r)}function k(t,e=[]){let n=t;for(const s of e)n=n.replace(new RegExp(`this.${s}.value`,"g"),`this.${s}`);return n}function H(t){let e=t.trim();if(e=/^\((\(|async|function)/.test(e)?e.substring(1,e.length-1):e,e.startsWith("{"))return e;if(e.startsWith("async function"))e=e.replace(/^async function/,"async");else if(e.startsWith("function"))e=e.replace(/^function/,"");else{const r=/^(async\s)?\([\w]*\)\s+\=\>\s([\w\W]+)/,i=e.match(r);i&&i[2]&&(i[2].startsWith("{")||(e=e.replace(i[2],`{ return ${i[2]} }`))),e=e.replace("=>","")}return e}function ie(t={}){return Object.entries(t).map(([e,n])=>`"${e}": ${m(n)}`)}function Q(t={},e=!1){const n=Object.keys(t);return e?n.map(s=>"."+s):n}function oe(t){let e="";for(var n in t)if(t.hasOwnProperty(n)){var s=t[n];e+=n+": "+s+";"}return e}function ce(t=[],e=[]){return t.filter(n=>!e.includes(n))}class ae{constructor(e,n){this.dsl=e,this.dependencies=n,this.libraryRegex=this.collectLibrary(),this.walk(e),this.walkNodes(e),this.members=this.getLibraryMember()}imports={};context={};style={};members=[];urlSchemas={};blockPlugins={};libraryRegex=[];collectLibrary(){return this.dependencies.filter(e=>!!e.library).map(e=>new RegExp(`(this.\\$libs.${e.library}.([\\w]+))`,"g"))}collectImport(e){const n=e.split(".");if(n.length===4){const s=n.pop(),r=n.join(".")+".",i=n.pop();if(s&&i){const c=this.dependencies.find(a=>a.library===i)?.package;c&&(this.imports[c]||(this.imports[c]=new Set)).add(s)}return{name:s,path:r,library:i}}return null}replaceLibraryPath(e){const{libraryRegex:n}=this;let s=e.value;for(const r of n){const i=e.value?.match(r)||[];for(const c of i){const a=this.collectImport(c);if(a){const p=a.path.replace(/\$/g,"\\$");s=s.replace(new RegExp(p,"g"),"")}}}return s}walk(e){const n=s=>{if(!s||typeof s!="object")return;if(Array.isArray(s)){for(let i of s)n(i);return}const r=Object.values(s);for(const i of r)v(i)?i.value=this.replaceLibraryPath(i):n(i)};n(e)}getLibraryMember(e=[]){let n=[...e];const s={...this.imports};delete s["uni-h5"],delete s["@dcloudio/uni-h5"],delete s["uni-ui"],delete s["@dcloudio/uni-ui"];for(const r of Object.values(s))n=n.concat(Array.from(r));return f.dedupArray(n)}collectContext(e,n){const s=new Set(n?.id?this.context[n.id]:[]),r=(e.directives||[]).find(a=>a.name==="vFor");let i=new Set(Array.from(s));if(r){const{item:a="item",index:p="index"}=r.iterator||{};i=new Set([a,p,...Array.from(i)])}const c=e.slot;if(c){const a=typeof c=="string"?[]:c.params||[],p=a.length?a:[`scope_${n?.id}`];i=new Set([...p,...Array.from(i)])}this.context[e.id]=i}collectStyle(e){e.id&&e.props?.style&&Object.keys(e.props.style).length&&!v(e.props.style)&&(this.style[`.${e.name}_${e.id}`]=e.props.style)}collectUrlSchema(e){typeof e.from=="object"&&e.from.type==="UrlSchema"&&(this.urlSchemas[e.name]=e.from)}collectBlockPlugin(e){typeof e.from=="object"&&e.from.type==="Plugin"&&(this.blockPlugins[e.name]=e.from)}walkNodes(e){const n=(s,r)=>{this.collectContext(s,r),this.collectStyle(s),this.collectUrlSchema(s),this.collectBlockPlugin(s),Array.isArray(s.children)&&s.children.forEach(i=>n(i,s))};Array.isArray(e.nodes)&&e.nodes.forEach(s=>n(s))}}function ue(t={}){return Object.entries(t).map(([e,n])=>{const s=m(n,!1);return`${e}:${s}`})}function le(t=[]){return t.map(e=>`${e.name}: { from: '${e.from||e.name}', default: ${m(e.default,!0,!1)} }`)}function pe(t=[]){const e=n=>n?`[${f.toArray(n).map(i=>i.replace(/\'|\"/gi,"")).join(",")}]`:void 0;return t.map(n=>typeof n=="string"?`${n}: {}`:(v(n.default)&&!n.default.value&&(n.default.value="undefined"),`${n.name}: { type:${e(n.type)}, required: ${m(!!n.required,!0,!1)}, default: ${m(n.default,!0,!1)} }`))}function fe(t=[]){return t.map(e=>`'${typeof e=="string"?e:e.name}'`)}function E(t={},e=[]){return Object.entries(t).map(([n,s])=>{let r=H(m(s,!1,!1));return r=k(r,e),r.startsWith("async")?`async ${n}${r.replace(/^async/,"")}`:`${n}${r}`})}function me(t=[],e=[]){const n=t.reduce((i,c)=>(c.id&&A(c.source)&&(i[`watcher_${c.id}`]=c.source),i),{}),s=E(n,e),r=t.map(i=>`watcher_${i.id}: { deep: ${i.deep}, immediate:${i.immediate}, handler${H(i.handler.value)} }`);return{computed:s,watches:r}}function he(t={}){return Object.values(t).map(e=>{if(e.type==="mock"){const n=A(e.mockTemplate)&&e.mockTemplate.value||"(params) => ({})";return`async ${e.name}(...args:any[]) { const mock = this.provider.createMock(${n}) return await mock.apply(this, args); }`}else{const n=A(e.transform)&&e.transform.value||"(res) => res";return`async ${e.name}(...args:any[]) { return await this.provider.apis['${e.ref}'].apply(this, args).then(${n}); }`}})}const de=["img","input","br","hr","area","base","col","embed","link","meta","param","source","track","wbr"],q=["vIf","vShow","vModel","vFor","vBind","vHtml"];function z(t,e,n=[],s={},r){const i=[];let c={},a=[];const p=[];let o=[];return ge(t).forEach(u=>{const h=[];for(const y of u.children){let{id:b,name:$,invisible:N,from:g}=y;if(N)continue;const w=$e($,e,g);w&&a.push(w),G(g)&&o.push({id:g.id,name:$});const{props:C,events:P,handlers:O}=ke(y,b,y.props,y.events,s,n),W=we(y.directives,n,p).join(" "),j=y.children?Pe(y.children,n,e,s,y):"";Object.assign(c,O);let _="";typeof j=="string"?_=j:(_=(j?.nodes||[]).join(` `),Object.assign(c,j?.methods||{}),a=a.concat(j?.components||[]),o=o.concat(j?.importBlocks||[]));const x=["@dcloudio/uni-h5","@dcloudio/uni-ui"].includes(g)?f.kebabCase($):X(g)||Y(g)?"component":$;h.push(de.includes(x)?`<${x} ${W} ${C} ${P} />`:`<${x} ${W} ${C} ${P}>${_?` `+_.trim():""}</${x}>`)}const d=Oe(u.slot,h.join(` `),r?.id);i.push(d)}),{nodes:i,methods:c,directives:ye(p),components:f.dedupArray(a),importBlocks:f.dedupArray(o,"id")}}function ye(t){return f.dedupArray(t).map(e=>`${e.startsWith("v")?e.substring(1):e}:${e}`)}function ge(t=[]){const e=new Map;for(const n of t){const s=typeof n.slot=="string"?n.slot:n.slot?.name,r=e.get(s);r?r.children.push(n):e.set(s,{slot:n.slot,children:[n]})}return e}function $e(t,e,n){if(re.includes(t))return null;const s=e.get(t);if(s&&s.alias){const r=s.parent?`${s.parent}.${s.alias}`:s.alias;return`${t}: ${r}`}return G(n)||s?t:null}function G(t){return!!t&&typeof t=="object"&&t.type==="Schema"}function X(t){return typeof t=="object"&&t.type==="UrlSchema"}function Y(t){return typeof t=="object"&&t.type==="Plugin"}function ve(t,e,n=[]){return t==="style"?v(e)?`:style="${m({...e,value:k(e.value,n)})}"`:"":t==="__class"&&v(e)?`:class="${m({...e,value:k(e.value,n)})}"`:typeof e=="string"?`${t}="${e}"`:v(e)?`:${t}="${m({...e,value:k(e.value,n)})}"`:f.isPlainObject(e)?`:${t}='{${ie(e).join(", ")}}'`:`:${t}='${JSON.stringify(e)}'`}function be(t,e={},n=[]){if(!!Object.keys(e.style||{}).length){const i=`${t.name}_${t.id}`;e.class?typeof e.class=="string"?e.class=[e.class,i].join(" "):(e.__class=e.class,e.class=i):e.class=i,v(e.style)||delete e.style}const r=t.from;return(X(r)||Y(r))&&(e.is={type:"JSExpression",value:t.name}),Object.entries(e).map(([i,c])=>ve(i,c,n))}function je(t,e,n,s,r){const i=Q(e.modifiers,!0);return r?`@${t}${i.join("")}="${n}"`:s&&s.length>0?`@${t}${i.join("")}="(...args:any[]) => ${n}"`:`@${t}${i.join("")}="${n}"`}function Se(t,e={},n={}){const s={},r=Array.from(n[t]||new Set([])),i=r.length?`({${r.join(", ")}}, args)`:"";return{binders:Object.entries(e).map(([a,p])=>{const o=p.handler.value.startsWith("this."),l=o?V(p.handler.value):`${f.camelCase(a)}_${t}${i}`;return o||(s[l]=r.length?{type:"JSFunction",value:`{ return (${p.handler.value}).apply(this, args); }`}:p.handler),je(a,p,l,r,o)}),handlers:s}}function ke(t,e,n={},s={},r={},i){const{binders:c,handlers:a}=Se(e,s,r);return{props:be(t,n,i).join(" "),handlers:a,binders:c,events:c.join(" ")}}function we(t=[],e=[],n=[]){const s=[],{vIf:r,vShow:i,vModels:c,vFor:a,vBind:p,vHtml:o,customDirectives:l}=Ce(t);if(r&&s.push(`v-if="${m(r.value,!0,!0,e)}"`),i&&s.push(`v-show="${m(i.value,!0,!0,e)}"`),p&&s.push(`v-bind="${m(p.value,!0,!0,e)}"`),c.forEach(u=>{const h=Q(u.modifiers,!0),d=u.arg?S(u.arg)?`:[${m(u.arg,!0,!0,e)}]`:`:${u.arg}`:"";s.push(`v-model${d}${h}="${m(u.value,!0,!0,e)}"`)}),a){const{item:u,index:h}={item:"item",index:"index",...a.iterator};s.push(`v-for="(${u}, ${h}) in ${m(a.value,!0,!0,e)}"`)}return o&&s.push(`v-html="${m(o.value,!0,!0,e)}"`),l&&l.length&&l.forEach(u=>{if(!u.name)return;let h="",d="";S(u.name)?(d=m(u.name,!0,!0,e),n.push(d)):d=u.name;const y=d?.startsWith("v")?f.kebabCase(d):f.kebabCase("v-"+d);if(h+=y,u.arg&&(S(u.arg)?h+=`:[${m(u.name,!0,!0,e)}]`:h+=`:${u.arg}`),u.modifiers){const b=Object.keys(u.modifiers);b.length&&(h+=b.map($=>"."+$))}u.value?s.push(`${h}="${m(u.value,!0,!0,e)}"`):s.push(h)}),s}function Ce(t=[]){const e=t.filter(o=>q.includes(o.name)),n=t.filter(o=>!q.includes(o.name)),s=e.find(o=>f.camelCase(o.name)==="vIf"),r=e.find(o=>f.camelCase(o.name)==="vFor"),i=e.find(o=>f.camelCase(o.name)==="vShow"),c=e.find(o=>f.camelCase(o.name)==="vBind"),a=e.find(o=>f.camelCase(o.name)==="vHtml"),p=e.filter(o=>f.camelCase(o.name)==="vModel");return{vIf:s,vFor:r,vShow:i,vModels:p,vBind:c,vHtml:a,customDirectives:n}}function Pe(t,e,n,s,r){return typeof t=="string"?t:S(t)?`{{ ${m(t,!1,!0,e)} }}`:Array.isArray(t)?z(t,n,e,s,r):""}function Oe(t,e,n){if(!t)return e;const s=typeof t=="string"?{name:t,params:[]}:{params:[],...t};return`<template ${`#${s.name}="${s.params?.length>0?`{${s.params?.join(",")}}`:`scope_${n}`}"`}> ${e} </template>`}function _e(t,e=[],n=[],s={},r="web"){const i=["@dcloudio/uni-h5","uni-h5","@dcloudio/uni-ui","uni-ui"],c={vue:["defineComponent","reactive"]},a=[];for(const o of e){const l=t.get(o.split(":")[0]);if(l&&l.package){const u=c[l.package]??(c[l.package]=[]),h=l.parent||(l.alias||"").split(".")[0]||l.name;u.push(h),r==="uniapp"&&i.includes(l.package)&&a.push(h)}}for(const[o,l]of Object.entries(s))(c[o]??(c[o]=[])).push(...Array.from(l)),r==="uniapp"&&i.includes(o)&&a.push(...Array.from(l));return{imports:Object.entries(c).filter(([o,l])=>r==="uniapp"?!i.includes(o)&&!!l.length:!!l.length).map(([o,l])=>`import { ${f.dedupArray(l).join(",")}} from '${o}';`).concat(n),uniComponents:a}}function xe(t={}){const e=[];for(const[n,s]of Object.entries(t))e.push(` ${n} { ${oe(s)} } `);return e.join(` `)}function Ee(t={}){const e=[];return Object.entries(t).forEach(([n,s])=>{e.push(`const ${n} = provider.defineUrlSchemaComponent('${s.url}');`)}),e}function Ae(t={}){const e=[];return Object.entries(t).forEach(([n,s])=>{e.push(`const ${n} = provider.definePluginComponent(${JSON.stringify(s)});`)}),e}function Fe(t,e,n="web"){const{dsl:s}=t,r=Object.keys(s.computed||{}),i=E(s.lifeCycles,r),c=E(s.computed,r),a=me(s.watch,r),p=he(s.dataSources),{methods:o,nodes:l,components:u,importBlocks:h,directives:d}=z(s.nodes||[],e,r,t.context),y=[...c,...a.computed],b=E({...o,...s.methods||{}},r),$=h.map(O=>`import ${O.name} from './${O.id}.vue';`);let{imports:N,uniComponents:g}=_e(e,u,$,t.imports,n);const w=Object.keys({...t.urlSchemas,...t.blockPlugins}),C=Ee(t.urlSchemas),P=Ae(t.blockPlugins);return{id:s.id,version:s.__VERSION__,name:s.name,state:ue(s.state).join(","),inject:le(s.inject).join(","),props:pe(s.props).join(","),emits:fe(s.emits).join(","),watch:a.watches.join(","),lifeCycles:i.join(","),computed:y.join(","),methods:[...p,...b].join(","),imports:` `+N.join(` `),components:ce(u,g).join(","),directives:d.join(","),returns:t.members.join(","),template:l.join(` `),css:s.css||"",style:xe(t.style),urlSchemas:C.join(` `),blockPlugins:P.join(` `),asyncComponents:w.join(","),uniComponents:g,renderer:n==="uniapp"?"@vtj/uni-app":"@vtj/renderer"}}const Ne=` // @ts-nocheck <%= imports %> import { useProvider } from '<%= renderer %>'; export default defineComponent({ name: '<%= name %>', <% if(inject) { %> inject: { <%= inject %>}, <% } %> <% if(components) { %> components: { <%= components %> }, <% } %> <% if(directives) { %> directives: { <%= directives %> }, <% } %> <% if(props) { %> props: { <%= props %> }, <% } %> <% if(emits) {%> emits: [<%= emits %>], <% } %> setup(props) { const provider = useProvider({ id: '<%= id %>', version: '<%= version %>' }); const state = reactive<Record<string, any>>({ <%= state %> }); <%= urlSchemas %> <%= blockPlugins %> return { state, props, provider <% if(asyncComponents) { %>, <%= asyncComponents %> <% }%> <% if(returns) { %>, <%= returns %> <% } %> }; }, <% if(computed) { %> computed: { <%= computed %> }, <% } %> <% if(methods) { %> methods: { <%= methods %> }, <% } %> <% if(watch) { %> watch: { <%= watch %> }, <% } %> <%= lifeCycles %> }); `.replace(/(\n|\r|\t)/g,""),Ie=` <template> <%= template %> </template> <script lang="ts"> <%= script %> <\/script> <style lang="scss" scoped> <%= css %> <%= style %> </style> `,Te=f.template(Ne),Be=f.template(Ie);async function Re(t,e=new Map,n=[],s="web",r){const i=new ae(f.cloneDeep(t),n),c=Fe(i,e,s),a=Te(c),p=Be({template:c.template,css:await I(c.css,r),script:await M(a,r),style:await I(c.style,r)});return await R(p,r).catch(o=>(o.content=p,Promise.reject(o)))}async function We(t){const e=` <template> <div> <h3>源码模式页面</h3> <div>文件路径:/.vtj/vue/${t.id}.vue</div> </div> </template> <script lang="ts" setup> <\/script> <style scoped lang="scss"> </style> `;return await R(e)}exports.VTJ_CODER_VERSION=se;exports.createEmptyPage=We;exports.cssFormatter=I;exports.generator=Re;exports.tsFormatter=M;exports.vueFormatter=R;