@fluenti/vite-plugin 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vite`),t=require(`@fluenti/core/compiler`),n=require(`@fluenti/core/config`),r=require(`node:path`),i=require(`node:module`),a=require(`node:fs`),o=require(`@fluenti/core/transform`),s=require(`@fluenti/core`);var c=`dev`;function l(e){c=e===`build`?`build`:`dev`}function u(e){if(typeof e==`object`&&e&&`environment`in e){let t=e.environment;if(typeof t==`object`&&t)return t}}function d(e){return e?.mode===`build`||c===`build`||process.env.NODE_ENV===`production`}async function f(e){try{let{DEFAULT_FLUENTI_CONFIG:t,loadConfigSync:n}=(0,i.createRequire)((0,r.join)(e.cwd,`package.json`))(`@fluenti/core/config`),o;try{o=n(void 0,e.cwd)}catch{o=t}(0,a.mkdirSync)((0,r.resolve)(e.cwd,o.compileOutDir),{recursive:!0}),(0,a.mkdirSync)((0,r.resolve)(e.cwd,o.catalogDir),{recursive:!0})}catch{}if(!(e.onBeforeCompile&&await e.onBeforeCompile()===!1)){if(e.compileOnly)try{let{runCompile:t}=(0,i.createRequire)((0,r.join)(e.cwd,`package.json`))(`@fluenti/cli`);await t(e.cwd),console.log(`[fluenti] Compiling... done`),e.onAfterCompile&&await e.onAfterCompile(),e.onSuccess?.();return}catch(t){let n=t instanceof Error?t:Error(String(t));if(e.throwOnError)throw n;console.warn(`[fluenti] Compile failed:`,n.message),e.onError?.(n);return}try{let{runExtract:t,runCompile:n}=(0,i.createRequire)((0,r.join)(e.cwd,`package.json`))(`@fluenti/cli`);await t(e.cwd),await n(e.cwd,{parallel:e.parallelCompile}),console.log(`[fluenti] Extracting and compiling... done`),e.onAfterCompile&&await e.onAfterCompile(),e.onSuccess?.();return}catch(t){let n=t instanceof Error?t:Error(String(t));if(n.message.includes(`Cannot find module`)){let t=`[fluenti] @fluenti/cli is required for auto-compile.
2
2
  Install it as a devDependency:
3
3
  pnpm add -D @fluenti/cli
4
- See: https://fluenti.dev/start/introduction/`;if(e.throwOnError)throw Error(t);console.warn(t),e.onError?.(Error(t));return}if(e.throwOnError)throw n;console.warn(`[fluenti] Extract/compile failed:`,n.message),e.onError?.(n)}}}function p(e,t=300){let n=null,r=!1,i=!1;async function a(){r=!0;try{await f(e)}finally{r=!1,i&&(i=!1,o())}}function o(){n!==null&&clearTimeout(n),n=setTimeout(()=>{n=null,r?i=!0:a()},t)}return o}function m(e,t){return g(e,`dynamic`,t)}function h(e,t){return g(e,`static`,t)}function g(e,n,r){let i=r?.hashFn??t.hashMessage,a=(0,o.parseSourceModule)(e);if(!a||a.type!==`Program`)return{code:e,needsCatalogImport:!1,usedHashes:new Set};let s=_(a),c=[],l=new Set;if((0,o.walkSourceAst)(a,t=>{let r=y(e,t,s,n,l,i);if(r){c.push(r);return}S(t,l,i)}),c.length===0)return{code:e,needsCatalogImport:!1,usedHashes:l};let u=e;for(let e=c.length-1;e>=0;e--){let{start:t,end:n,replacement:r}=c[e];u=u.slice(0,t)+r+u.slice(n)}return{code:u,needsCatalogImport:!0,usedHashes:l}}function _(e){let t=new Set,n=new Set,r=new Set,i=new Set;for(let t of e.body)if(ee(t))for(let e of t.specifiers){if(!te(e))continue;let t=U(e);t&&(t===`useI18n`&&n.add(e.local.name),t===`getI18n`&&r.add(e.local.name),t===`unref`&&i.add(e.local.name))}return(0,o.walkSourceAst)(e,e=>{if(!ne(e)||!e.init||!F(e.id))return;if(R(e.init)&&B(e.init.callee)&&n.has(e.init.callee.name)){v(e.id,t);return}let i=e.init.type===`AwaitExpression`?e.init.argument:null;i&&R(i)&&B(i.callee)&&r.has(i.callee.name)&&v(e.id,t)}),{tracked:t,unref:i}}function v(e,t){for(let n of e.properties)!L(n)||n.computed||!B(n.key)||n.key.name!==`t`||B(n.value)&&t.add(n.value.name)}function y(e,t,n,r,i,a){if(!R(t)||t.start==null||t.end==null)return;let o=b(e,t,n,a);if(!o)return;let{catalogId:s}=o;i.add(s);let c=a(s),l=r===`dynamic`?`__catalog[${JSON.stringify(s)}]`:`_${c}`,u=o.valuesSource?`${l}(${o.valuesSource})`:l;return{start:t.start,end:t.end,replacement:u}}function b(e,t,n,r){if(t.arguments.length===0)return;let i=t.callee,a=B(i)&&(n.tracked.has(i.name)||i.name===`$t`),o=z(i)&&!i.computed&&B(i.property)&&(i.property.name===`$t`||i.property.name===`t`&&B(i.object)&&(i.object.name===`_ctx`||i.object.name===`$setup`)),s=R(i)&&B(i.callee)&&n.unref.has(i.callee.name)&&i.arguments.length===1&&B(i.arguments[0])&&n.tracked.has(i.arguments[0].name);if(!a&&!o&&!s)return;let c=x(t.arguments[0],r);if(!c)return;let l=t.arguments[1]&&t.arguments[1].start!=null&&t.arguments[1].end!=null?e.slice(t.arguments[1].start,t.arguments[1].end):void 0;return l===void 0?{catalogId:c}:{catalogId:c,valuesSource:l}}function x(e,t){let n=N(e);if(n!==void 0)return t(n);if(!I(e))return;let r,i,a;for(let t of e.properties){if(!L(t)||t.computed)continue;let e=P(t.key);if(!e)continue;let n=N(t.value);n!==void 0&&(e===`id`&&(r=n),e===`message`&&(i=n),e===`context`&&(a=n))}if(r)return r;if(i)return t(i,a)}function S(e,t,n){if(!V(e))return;let r=M(e.openingElement.name);if(r){if(r===`Trans`){let r=O(e.openingElement,`__id`)??O(e.openingElement,`id`);if(r){t.add(r);return}let i=O(e.openingElement,`__message`),a=O(e.openingElement,`context`);i&&t.add(n(i,a));return}if(r===`Plural`){let r=C(e.openingElement,n);r&&t.add(r);return}if(r===`Select`){let r=w(e.openingElement,n);r&&t.add(r)}}}function C(e,t){let n=O(e,`id`);if(n)return n;let r=O(e,`context`),i=k(e,`offset`),a=[O(e,`zero`)===void 0?void 0:`=0 {${O(e,`zero`)}}`,O(e,`one`)===void 0?void 0:`one {${O(e,`one`)}}`,O(e,`two`)===void 0?void 0:`two {${O(e,`two`)}}`,O(e,`few`)===void 0?void 0:`few {${O(e,`few`)}}`,O(e,`many`)===void 0?void 0:`many {${O(e,`many`)}}`,O(e,`other`)===void 0?void 0:`other {${O(e,`other`)}}`].filter(Boolean);if(a.length!==0)return t(`{count, plural,${typeof i==`number`?` offset:${i}`:``} ${a.join(` `)}}`,r)}function w(e,t){let n=O(e,`id`);if(n)return n;let r=O(e,`context`),i=T(e);if(!(!i||i.other===void 0))return t(`{value, select, ${[...Object.keys(i).filter(e=>e!==`other`).sort(),`other`].map(e=>`${e} {${i[e]}}`).join(` `)}}`,r)}function T(e){let t=D(e,`options`);if(t){let n=O(e,`other`);return{...t,...n===void 0?{}:{other:n}}}let n={};for(let t of e.attributes){if(!H(t))continue;let e=t.name.name;if([`value`,`id`,`context`,`comment`,`options`].includes(e))continue;let r=j(t);r!==void 0&&(n[e]=r)}return Object.keys(n).length>0?n:void 0}function E(e){if(!I(e))return;let t={};for(let n of e.properties){if(!L(n)||n.computed)return;let e=P(n.key),r=N(n.value);if(!e||r===void 0)return;t[e]=r}return t}function D(e,t){let n=A(e,t);if(n?.value&&n.value.type===`JSXExpressionContainer`)return E(n.value.expression)}function O(e,t){return j(A(e,t))}function k(e,t){let n=A(e,t);if(!n?.value||n.value.type!==`JSXExpressionContainer`)return;let r=n.value.expression;return r.type===`NumericLiteral`?r.value:void 0}function A(e,t){return e.attributes.find(e=>H(e)&&e.name.name===t)}function j(e){if(e?.value){if(e.value.type===`StringLiteral`)return e.value.value;if(e.value.type===`JSXExpressionContainer`)return N(e.value.expression)}}function M(e){return e.type===`JSXIdentifier`?e.name:void 0}function N(e){if(e.type===`StringLiteral`)return e.value;if(e.type===`TemplateLiteral`){let t=e;if(t.expressions.length===0&&t.quasis.length===1)return t.quasis[0].value.cooked??t.quasis[0].value.raw}}function P(e){if(B(e))return e.name;if(e.type===`StringLiteral`)return e.value}function ee(e){return e.type===`ImportDeclaration`}function te(e){return e.type===`ImportSpecifier`}function ne(e){return e.type===`VariableDeclarator`}function F(e){return e.type===`ObjectPattern`}function I(e){return e.type===`ObjectExpression`}function L(e){return e.type===`ObjectProperty`}function R(e){return e.type===`CallExpression`}function z(e){return e.type===`MemberExpression`}function B(e){return e?.type===`Identifier`}function V(e){return e.type===`JSXElement`}function H(e){return e.type===`JSXAttribute`}function U(e){let t=e.imported;if(t.type===`Identifier`)return t.name;if(t.type===`StringLiteral`)return t.value}function W(e,n,r,i){if(n===`dynamic`)return`import { __catalog } from 'virtual:fluenti/runtime';\n${e}`;let a=i??t.hashMessage;return`import { ${[...r].map(e=>`_${a(e)}`).join(`, `)} } from 'virtual:fluenti/messages';\n${e}`}function G(e){return JSON.stringify(e)}function K(e){if(e.includes("`")||e.includes(`$`))throw Error(`[fluenti] vite-plugin: catalogDir must not contain backticks or $ characters, got ${JSON.stringify(e)}`)}var q=`virtual:fluenti/runtime`,J=`virtual:fluenti/messages`,Y=`\0virtual:fluenti/runtime`,X=`\0virtual:fluenti/messages`;function Z(e){if(e===q)return Y;if(e===J)return X}function Q(e,t){if(e===Y)return re(t);if(e===X)return ie(t)}function re(e){let{locales:t,runtimeGenerator:n,catalogDir:r}=e;K(r);for(let e of t)(0,s.validateLocale)(e,`vite-plugin`);if(!n)throw Error(`[fluenti] vite-plugin: runtimeGenerator is required. Use a framework-specific plugin (e.g. @fluenti/vue/vite-plugin).`);return n.generateRuntime(ae(e))}function ie(e){let{rootDir:t,catalogDir:n,catalogExtension:i,defaultBuildLocale:o,sourceLocale:c}=e,l=o||c;(0,s.validateLocale)(l,`vite-plugin`),K(n);let u=(0,r.resolve)((0,r.resolve)(t,n),l+i);return(0,a.existsSync)(u)||console.warn(`[fluenti] Compiled catalog for locale "${l}" not found at ${u}. Run "fluenti compile" first.`),`export * from ${G(u)}\n`}function ae(e){let{rootDir:t,catalogDir:n,catalogExtension:r,locales:i,sourceLocale:a,defaultBuildLocale:o}=e;return{rootDir:t,catalogDir:n,catalogExtension:r,locales:i,sourceLocale:a,defaultBuildLocale:o}}var oe=`virtual:fluenti/messages/`,se=`\0virtual:fluenti/messages/`;function $(e,t){return typeof e==`object`?{...n.DEFAULT_FLUENTI_CONFIG,...e}:(0,n.loadConfigSync)(typeof e==`string`?e:void 0,t)}function ce(n,r,i){let a,s=process.cwd();function c(e){let t=e??s;return a||=$(n.config,t),a}let g=n.framework;function _(e){let n=c(e),r=n.compileOutDir.replace(/^\.\//,``),i=n.catalogExtension??`.js`,a=n.splitting??!1;a&&a!==`dynamic`&&a!==`static`&&console.warn(`[fluenti] Invalid splitting value "${a}". Expected 'dynamic', 'static', or false. Falling back to 'dynamic'.`);let o=a===`static`?`static`:a?`dynamic`:!1,s=n.sourceLocale;return{config:n,catalogDir:r,catalogExtension:i,splitting:o,sourceLocale:s,localeCodes:(0,t.resolveLocaleCodes)(n.locales),defaultBuildLocale:n.defaultBuildLocale??s}}let v={name:`fluenti:virtual`,configResolved(e){s=e.root,a=$(n.config,s),l(e.command)},resolveId(e){if(e.startsWith(oe))return`\0`+e;let{splitting:t}=_();if(t){let t=Z(e);if(t)return t}},load(e){let{catalogDir:t,catalogExtension:n,splitting:r,localeCodes:a,sourceLocale:o,defaultBuildLocale:c}=_();if(e.startsWith(se)){let r=e.slice(26);return a.includes(r)?`export { default } from '${`${t}/${r}${n}`}'`:void 0}if(r){let r=Q(e,{rootDir:s,catalogDir:t,catalogExtension:n,locales:a,sourceLocale:o,defaultBuildLocale:c,framework:g,runtimeGenerator:i});if(r)return r}}},y=(0,o.createTransformPipeline)({framework:g}),b={name:`fluenti:script-transform`,enforce:`pre`,transform(e,t){if(t.includes(`node_modules`)||!t.match(/\.(vue|tsx|jsx|ts|js)(\?|$)/)||t.includes(`.vue`)&&!t.includes(`type=script`))return;let n=g===`vue`&&t.includes(`.vue`),r=`@fluenti/${g}/components`,i=e,a=!1;if(t.match(/\.[jt]sx(\?|$)/)&&/<Trans[\s>]/.test(i)){let e=y.transformTrans(i);e.transformed&&(i=e.code,a=!0)}if(t.match(/\.[jt]sx(\?|$)/)&&(g===`react`||g===`solid`)&&/<(Plural|Select)[\s/>]/.test(i)){let e=y.transformPluralSelect(i,r);e.transformed&&(i=e.code,a=!0)}if((0,o.hasScopeTransformCandidate)(i)){let e=y.transformScope(i,{componentModuleImport:r,...n?{allowTopLevelImportedT:!0}:{}});if(e.transformed)return{code:e.code,map:null}}return a?{code:i,map:null}:void 0}},x={name:`fluenti:build-split`,transform(e,t){let{splitting:n,config:r}=_();if(!n||!d(u(this))||t.includes(`node_modules`)||!t.match(/\.(vue|tsx|jsx|ts|js)(\?|$)/))return;let i=n===`static`?`static`:`dynamic`,a=r.idGenerator?{hashFn:r.idGenerator}:void 0,o=i===`static`?h(e,a):m(e,a);if(o.needsCatalogImport)return{code:W(o.code,i,o.usedHashes,r.idGenerator),map:null}}},S={name:`fluenti:build-compile`,async buildStart(){let{config:e}=_();d(u(this))&&(e.buildAutoCompile??!0)&&(e.onBeforeCompile&&await e.onBeforeCompile()===!1||(await f({cwd:s,throwOnError:!0,compileOnly:!0}),e.onAfterCompile&&await e.onAfterCompile()))}},C={name:`fluenti:dev`,configureServer(t){let{config:n,catalogDir:r}=_(t.config.root);if(!(n.devAutoCompile??!0))return;let i=(0,e.createFilter)(n.include??[`src/**/*.{vue,tsx,jsx,ts,js}`],[...n.exclude??[],`**/node_modules/**`,`**/${r}/**`]),a={cwd:t.config.root,onSuccess:()=>{}};n.parallelCompile&&(a.parallelCompile=!0),n.onBeforeCompile&&(a.onBeforeCompile=n.onBeforeCompile),n.onAfterCompile&&(a.onAfterCompile=n.onAfterCompile);let o=p(a,n.devAutoCompileDelay??500);o(),t.watcher.on(`change`,e=>{i(e)&&o()})},hotUpdate({file:e}){let{catalogDir:t}=_();if(e.includes(t)){let e=[...this.environment.moduleGraph.urlToModuleMap.entries()].filter(([e])=>e.includes(`virtual:fluenti`)).map(([,e])=>e);if(e.length>0)return e}}};return[v,...r,b,S,x,C]}exports.createFluentiPlugins=ce,Object.defineProperty(exports,`createRuntimeGenerator`,{enumerable:!0,get:function(){return o.createRuntimeGenerator}}),exports.getPluginEnvironment=u,exports.isBuildMode=d,exports.loadVirtualSplitModule=Q,exports.resolveVirtualSplitId=Z,exports.setResolvedMode=l;
5
- //# sourceMappingURL=index.cjs.map
4
+ See: https://fluenti.dev/start/introduction/`;if(e.throwOnError)throw Error(t);console.warn(t),e.onError?.(Error(t));return}if(e.throwOnError)throw n;console.warn(`[fluenti] Extract/compile failed:`,n.message),e.onError?.(n)}}}function p(e,t=300){let n=null,r=!1,i=!1;async function a(){r=!0;try{await f(e)}finally{r=!1,i&&(i=!1,o())}}function o(){n!==null&&clearTimeout(n),n=setTimeout(()=>{n=null,r?i=!0:a()},t)}return o}function m(e,t){return g(e,`dynamic`,t)}function h(e,t){return g(e,`static`,t)}function g(e,n,r){let i=r?.hashFn??t.hashMessage,a=(0,o.parseSourceModule)(e);if(!a||a.type!==`Program`)return{code:e,needsCatalogImport:!1,usedHashes:new Set};let s=_(a),c=[],l=new Set;if((0,o.walkSourceAst)(a,t=>{let r=y(e,t,s,n,l,i);if(r){c.push(r);return}S(t,l,i)}),c.length===0)return{code:e,needsCatalogImport:!1,usedHashes:l};let u=e;for(let e=c.length-1;e>=0;e--){let{start:t,end:n,replacement:r}=c[e];u=u.slice(0,t)+r+u.slice(n)}return{code:u,needsCatalogImport:!0,usedHashes:l}}function _(e){let t=new Set,n=new Set,r=new Set,i=new Set;for(let t of e.body)if(ee(t))for(let e of t.specifiers){if(!te(e))continue;let t=U(e);t&&(t===`useI18n`&&n.add(e.local.name),t===`getI18n`&&r.add(e.local.name),t===`unref`&&i.add(e.local.name))}return(0,o.walkSourceAst)(e,e=>{if(!ne(e)||!e.init||!F(e.id))return;if(R(e.init)&&B(e.init.callee)&&n.has(e.init.callee.name)){v(e.id,t);return}let i=e.init.type===`AwaitExpression`?e.init.argument:null;i&&R(i)&&B(i.callee)&&r.has(i.callee.name)&&v(e.id,t)}),{tracked:t,unref:i}}function v(e,t){for(let n of e.properties)!L(n)||n.computed||!B(n.key)||n.key.name!==`t`||B(n.value)&&t.add(n.value.name)}function y(e,t,n,r,i,a){if(!R(t)||t.start==null||t.end==null)return;let o=b(e,t,n,a);if(!o)return;let{catalogId:s}=o;i.add(s);let c=a(s),l=r===`dynamic`?`__catalog[${JSON.stringify(s)}]`:`_${c}`,u=o.valuesSource?`${l}(${o.valuesSource})`:l;return{start:t.start,end:t.end,replacement:u}}function b(e,t,n,r){if(t.arguments.length===0)return;let i=t.callee,a=B(i)&&(n.tracked.has(i.name)||i.name===`$t`),o=z(i)&&!i.computed&&B(i.property)&&(i.property.name===`$t`||i.property.name===`t`&&B(i.object)&&(i.object.name===`_ctx`||i.object.name===`$setup`)),s=R(i)&&B(i.callee)&&n.unref.has(i.callee.name)&&i.arguments.length===1&&B(i.arguments[0])&&n.tracked.has(i.arguments[0].name);if(!a&&!o&&!s)return;let c=x(t.arguments[0],r);if(!c)return;let l=t.arguments[1]&&t.arguments[1].start!=null&&t.arguments[1].end!=null?e.slice(t.arguments[1].start,t.arguments[1].end):void 0;return l===void 0?{catalogId:c}:{catalogId:c,valuesSource:l}}function x(e,t){let n=N(e);if(n!==void 0)return t(n);if(!I(e))return;let r,i,a;for(let t of e.properties){if(!L(t)||t.computed)continue;let e=P(t.key);if(!e)continue;let n=N(t.value);n!==void 0&&(e===`id`&&(r=n),e===`message`&&(i=n),e===`context`&&(a=n))}if(r)return r;if(i)return t(i,a)}function S(e,t,n){if(!V(e))return;let r=M(e.openingElement.name);if(r){if(r===`Trans`){let r=O(e.openingElement,`__id`)??O(e.openingElement,`id`);if(r){t.add(r);return}let i=O(e.openingElement,`__message`),a=O(e.openingElement,`context`);i&&t.add(n(i,a));return}if(r===`Plural`){let r=C(e.openingElement,n);r&&t.add(r);return}if(r===`Select`){let r=w(e.openingElement,n);r&&t.add(r)}}}function C(e,t){let n=O(e,`id`);if(n)return n;let r=O(e,`context`),i=k(e,`offset`),a=[O(e,`zero`)===void 0?void 0:`=0 {${O(e,`zero`)}}`,O(e,`one`)===void 0?void 0:`one {${O(e,`one`)}}`,O(e,`two`)===void 0?void 0:`two {${O(e,`two`)}}`,O(e,`few`)===void 0?void 0:`few {${O(e,`few`)}}`,O(e,`many`)===void 0?void 0:`many {${O(e,`many`)}}`,O(e,`other`)===void 0?void 0:`other {${O(e,`other`)}}`].filter(Boolean);if(a.length!==0)return t(`{count, plural,${typeof i==`number`?` offset:${i}`:``} ${a.join(` `)}}`,r)}function w(e,t){let n=O(e,`id`);if(n)return n;let r=O(e,`context`),i=T(e);if(!(!i||i.other===void 0))return t(`{value, select, ${[...Object.keys(i).filter(e=>e!==`other`).sort(),`other`].map(e=>`${e} {${i[e]}}`).join(` `)}}`,r)}function T(e){let t=D(e,`options`);if(t){let n=O(e,`other`);return{...t,...n===void 0?{}:{other:n}}}let n={};for(let t of e.attributes){if(!H(t))continue;let e=t.name.name;if([`value`,`id`,`context`,`comment`,`options`].includes(e))continue;let r=j(t);r!==void 0&&(n[e]=r)}return Object.keys(n).length>0?n:void 0}function E(e){if(!I(e))return;let t={};for(let n of e.properties){if(!L(n)||n.computed)return;let e=P(n.key),r=N(n.value);if(!e||r===void 0)return;t[e]=r}return t}function D(e,t){let n=A(e,t);if(n?.value&&n.value.type===`JSXExpressionContainer`)return E(n.value.expression)}function O(e,t){return j(A(e,t))}function k(e,t){let n=A(e,t);if(!n?.value||n.value.type!==`JSXExpressionContainer`)return;let r=n.value.expression;return r.type===`NumericLiteral`?r.value:void 0}function A(e,t){return e.attributes.find(e=>H(e)&&e.name.name===t)}function j(e){if(e?.value){if(e.value.type===`StringLiteral`)return e.value.value;if(e.value.type===`JSXExpressionContainer`)return N(e.value.expression)}}function M(e){return e.type===`JSXIdentifier`?e.name:void 0}function N(e){if(e.type===`StringLiteral`)return e.value;if(e.type===`TemplateLiteral`){let t=e;if(t.expressions.length===0&&t.quasis.length===1)return t.quasis[0].value.cooked??t.quasis[0].value.raw}}function P(e){if(B(e))return e.name;if(e.type===`StringLiteral`)return e.value}function ee(e){return e.type===`ImportDeclaration`}function te(e){return e.type===`ImportSpecifier`}function ne(e){return e.type===`VariableDeclarator`}function F(e){return e.type===`ObjectPattern`}function I(e){return e.type===`ObjectExpression`}function L(e){return e.type===`ObjectProperty`}function R(e){return e.type===`CallExpression`}function z(e){return e.type===`MemberExpression`}function B(e){return e?.type===`Identifier`}function V(e){return e.type===`JSXElement`}function H(e){return e.type===`JSXAttribute`}function U(e){let t=e.imported;if(t.type===`Identifier`)return t.name;if(t.type===`StringLiteral`)return t.value}function W(e,n,r,i){if(n===`dynamic`)return`import { __catalog } from 'virtual:fluenti/runtime';\n${e}`;let a=i??t.hashMessage;return`import { ${[...r].map(e=>`_${a(e)}`).join(`, `)} } from 'virtual:fluenti/messages';\n${e}`}function G(e){return JSON.stringify(e)}function K(e){if(e.includes("`")||e.includes(`$`))throw Error(`[fluenti] vite-plugin: catalogDir must not contain backticks or $ characters, got ${JSON.stringify(e)}`)}var q=`virtual:fluenti/runtime`,J=`virtual:fluenti/messages`,Y=`\0virtual:fluenti/runtime`,X=`\0virtual:fluenti/messages`;function Z(e){if(e===q)return Y;if(e===J)return X}function Q(e,t){if(e===Y)return re(t);if(e===X)return ie(t)}function re(e){let{locales:t,runtimeGenerator:n,catalogDir:r}=e;K(r);for(let e of t)(0,s.validateLocale)(e,`vite-plugin`);if(!n)throw Error(`[fluenti] vite-plugin: runtimeGenerator is required. Use a framework-specific plugin (e.g. @fluenti/vue/vite-plugin).`);return n.generateRuntime(ae(e))}function ie(e){let{rootDir:t,catalogDir:n,catalogExtension:i,defaultBuildLocale:o,sourceLocale:c}=e,l=o||c;(0,s.validateLocale)(l,`vite-plugin`),K(n);let u=(0,r.resolve)((0,r.resolve)(t,n),l+i);return(0,a.existsSync)(u)||console.warn(`[fluenti] Compiled catalog for locale "${l}" not found at ${u}. Run "fluenti compile" first.`),`export * from ${G(u)}\n`}function ae(e){let{rootDir:t,catalogDir:n,catalogExtension:r,locales:i,sourceLocale:a,defaultBuildLocale:o}=e;return{rootDir:t,catalogDir:n,catalogExtension:r,locales:i,sourceLocale:a,defaultBuildLocale:o}}var oe=`virtual:fluenti/messages/`,se=`\0virtual:fluenti/messages/`;function $(e,t){return typeof e==`object`?{...n.DEFAULT_FLUENTI_CONFIG,...e}:(0,n.loadConfigSync)(typeof e==`string`?e:void 0,t)}function ce(n,r,i){let a,s=process.cwd();function c(e){let t=e??s;return a||=$(n.config,t),a}let g=n.framework;function _(e){let n=c(e),r=n.compileOutDir.replace(/^\.\//,``),i=n.catalogExtension??`.js`,a=n.splitting??!1;a&&a!==`dynamic`&&a!==`static`&&console.warn(`[fluenti] Invalid splitting value "${a}". Expected 'dynamic', 'static', or false. Falling back to 'dynamic'.`);let o=a===`static`?`static`:a?`dynamic`:!1,s=n.sourceLocale;return{config:n,catalogDir:r,catalogExtension:i,splitting:o,sourceLocale:s,localeCodes:(0,t.resolveLocaleCodes)(n.locales),defaultBuildLocale:n.defaultBuildLocale??s}}let v={name:`fluenti:virtual`,configResolved(e){s=e.root,a=$(n.config,s),l(e.command)},resolveId(e){if(e.startsWith(oe))return`\0`+e;let{splitting:t}=_();if(t){let t=Z(e);if(t)return t}},load(e){let{catalogDir:t,catalogExtension:n,splitting:r,localeCodes:a,sourceLocale:o,defaultBuildLocale:c}=_();if(e.startsWith(se)){let r=e.slice(26);return a.includes(r)?`export { default } from '${`${t}/${r}${n}`}'`:void 0}if(r){let r=Q(e,{rootDir:s,catalogDir:t,catalogExtension:n,locales:a,sourceLocale:o,defaultBuildLocale:c,framework:g,runtimeGenerator:i});if(r)return r}}},y=(0,o.createTransformPipeline)({framework:g}),b={name:`fluenti:script-transform`,enforce:`pre`,transform(e,t){if(t.includes(`node_modules`)||!t.match(/\.(vue|tsx|jsx|ts|js)(\?|$)/)||t.includes(`.vue`)&&!t.includes(`type=script`))return;let n=g===`vue`&&t.includes(`.vue`),r=`@fluenti/${g}/components`,i=e,a=!1;if(t.match(/\.[jt]sx(\?|$)/)&&/<Trans[\s>]/.test(i)){let e=y.transformTrans(i);e.transformed&&(i=e.code,a=!0)}if(t.match(/\.[jt]sx(\?|$)/)&&(g===`react`||g===`solid`)&&/<(Plural|Select)[\s/>]/.test(i)){let e=y.transformPluralSelect(i,r);e.transformed&&(i=e.code,a=!0)}if((0,o.hasScopeTransformCandidate)(i)){let e=y.transformScope(i,{componentModuleImport:r,...n?{allowTopLevelImportedT:!0}:{}});if(e.transformed)return{code:e.code,map:null}}return a?{code:i,map:null}:void 0}},x={name:`fluenti:build-split`,transform(e,t){let{splitting:n,config:r}=_();if(!n||!d(u(this))||t.includes(`node_modules`)||!t.match(/\.(vue|tsx|jsx|ts|js)(\?|$)/))return;let i=n===`static`?`static`:`dynamic`,a=r.idGenerator?{hashFn:r.idGenerator}:void 0,o=i===`static`?h(e,a):m(e,a);if(o.needsCatalogImport)return{code:W(o.code,i,o.usedHashes,r.idGenerator),map:null}}},S={name:`fluenti:build-compile`,async buildStart(){let{config:e}=_();d(u(this))&&(e.buildAutoCompile??!0)&&(e.onBeforeCompile&&await e.onBeforeCompile()===!1||(await f({cwd:s,throwOnError:!0,compileOnly:!0}),e.onAfterCompile&&await e.onAfterCompile()))}},C={name:`fluenti:dev`,configureServer(t){let{config:n,catalogDir:r}=_(t.config.root);if(!(n.devAutoCompile??!0))return;let i=(0,e.createFilter)(n.include??[`src/**/*.{vue,tsx,jsx,ts,js}`],[...n.exclude??[],`**/node_modules/**`,`**/${r}/**`]),a={cwd:t.config.root,onSuccess:()=>{}};n.parallelCompile&&(a.parallelCompile=!0),n.onBeforeCompile&&(a.onBeforeCompile=n.onBeforeCompile),n.onAfterCompile&&(a.onAfterCompile=n.onAfterCompile);let o=p(a,n.devAutoCompileDelay??500);o(),t.watcher.on(`change`,e=>{i(e)&&o()})},hotUpdate({file:e}){let{catalogDir:t}=_();if(e.includes(t)){let e=[...this.environment.moduleGraph.urlToModuleMap.entries()].filter(([e])=>e.includes(`virtual:fluenti`)).map(([,e])=>e);if(e.length>0)return e}}};return[v,...r,b,S,x,C]}exports.createFluentiPlugins=ce,Object.defineProperty(exports,`createRuntimeGenerator`,{enumerable:!0,get:function(){return o.createRuntimeGenerator}}),exports.getPluginEnvironment=u,exports.isBuildMode=d,exports.loadVirtualSplitModule=Q,exports.resolveVirtualSplitId=Z,exports.setResolvedMode=l;
package/dist/index.js CHANGED
@@ -530,5 +530,3 @@ function ge(t, r, i) {
530
530
  }
531
531
  //#endregion
532
532
  export { ge as createFluentiPlugins, u as createRuntimeGenerator, _ as getPluginEnvironment, v as isBuildMode, Q as loadVirtualSplitModule, Z as resolveVirtualSplitId, g as setResolvedMode };
533
-
534
- //# sourceMappingURL=index.js.map
@@ -1,2 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@fluenti/core/compiler`),t=require(`@vue/compiler-sfc`);var n=1,r=2,i=5,a=6,o=7;function s(e){return e.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`)}function c(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function l(e){return`[${e.map(e=>{let t=s(e.rawAttrs).replace(/"/g,`&quot;`);return`{ tag: '${s(e.tag)}', rawAttrs: '${t}' }`}).join(`, `)}]`}function u(t,n){return`{ id: '${s(n?.id??(0,e.hashMessage)(t,n?.context))}', message: '${s(t)}' }`}function d(e){return typeof e==`string`?e:e.content??``}function f(e,t){for(let n of e){if(n.type===o&&n.name===`bind`&&(typeof n.arg?.content==`string`?n.arg.content:void 0)===t)return{kind:`dynamic`};if(n.type===a&&n.name===t)return{kind:`static`,value:typeof n.value?.content==`string`?n.value.content:``}}return{kind:`missing`}}function p(e,t){for(let n of e)if(n.type===o&&n.name===`bind`&&(typeof n.arg?.content==`string`?n.arg.content:void 0)===t)return typeof n.exp?.content==`string`?n.exp.content:void 0}function m(e){let t=[],a=``;for(let o of e)if(o.type===r)a+=typeof o.content==`string`?o.content:``;else if(o.type===i)a+=o.loc.source;else if(o.type===n&&o.tag){let e=t.length,n=(o.props??[]).map(e=>e.loc.source).join(` `);if((o.isSelfClosing??!1)||!o.children?.length)t.push({tag:o.tag,rawAttrs:n,selfClosing:!0,innerContent:``}),a+=`<${e}/>`;else{let r=o.children[0],i=o.children[o.children.length-1],s=o.loc.source.slice(r.loc.start.offset-o.loc.start.offset,i.loc.end.offset-o.loc.start.offset);t.push({tag:o.tag,rawAttrs:n,selfClosing:!1,innerContent:s}),a+=`<${e}>${s}</${e}>`}}return{message:a,elements:t,hasElements:t.length>0}}function h(e){let t=[],n=``;for(let a of e)if(a.type===r)n+=typeof a.content==`string`?a.content:``;else if(a.type===i){let e=(typeof a.content==`object`&&a.content&&typeof a.content.content==`string`?a.content.content:``).trim(),r;if(/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e))r=e;else if(/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(e)&&!e.endsWith(`.`)){let t=e.split(`.`);r=t[t.length-1]}else r=String(t.length);t.push(`${r}: ${e}`),n+=`{${r}}`}return{message:n,vars:t}}function g(e,t){return e.filter(e=>!t.has(e)).map(e=>e.loc.source).join(` `)}var _=new Set([`tag`,`id`,`context`,`comment`]);function v(e,t){let n=e.props??[],r=n.find(e=>e.type===o&&e.name===`t`&&(e.modifiers??[]).length>0);if(!r)return;let i=(r.modifiers??[]).map(d);if(i.length===1&&i[0]===`plural`)return;let s=i.find(e=>e!==`plural`);if(!s)return;let c=n.find(e=>e.type===a&&e.name===s);if(!c)return;let l=u(typeof c.value?.content==`string`?c.value.content:``),f=g(n,new Set([r,c])),p=f?` ${f}`:``,m=e.tag;if(e.isSelfClosing){let n=`<${m}${p} :${s}="$t(${l})" />`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:n})}else{let n=e.children??[],r=n.length>0?n[0].loc.start.offset:e.loc.source.indexOf(`>`)+e.loc.start.offset+1,i=`<${m}${p} :${s}="$t(${l})">`;t.push({start:e.loc.start.offset,end:r,replacement:i})}}function y(e,t){let n=e.props??[],i=n.find(e=>e.type===o&&e.name===`t`);if(!i)return;let s=(i.modifiers??[]).map(d),c=s.filter(e=>e!==`plural`);if(c.length>0){let e=c[0];if(n.some(t=>t.type===a&&t.name===e))return}let f=s.includes(`plural`),p=typeof i.exp?.content==`string`?i.exp.content:void 0,_=new Set([`plural`]),v=s.filter(e=>!_.has(e)),y=typeof i.arg?.content==`string`?i.arg.content:void 0,b=y?[y,...v].join(`.`):void 0,x=e.tag,S=e.children??[],C=g(n,new Set([i])),w=C?` ${C}`:``;if(f&&p){let n=S.filter(e=>e.type===r).map(e=>(typeof e.content==`string`?e.content:``).trim()).join(``).split(`|`).map(e=>e.trim()),i=`<${x}${w}>{{ $t(${u(`{${p}, plural, ${(n.length===2?[`one`,`other`]:[`one`,`other`,`zero`,`few`,`many`].slice(0,n.length)).map((e,t)=>`${e} {${n[t]??``}}`).join(` `)}}`,{id:b})}, { ${p} }) }}</${x}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:i});return}let T=m(S);if(T.hasElements){let n=`<${x}${w} v-html="$vtRich(${u(T.message.trim(),{id:b})}, ${l(T.elements)})"></${x}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:n});return}let{message:E,vars:D}=h(S),O=E.trim();if(!O&&!b)return;let k=u(O,{id:b}),A;A=D.length>0?`<${x}${w}>{{ $t(${k}, { ${D.join(`, `)} }) }}</${x}>`:`<${x}${w}>{{ $t(${k}) }}</${x}>`,t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:A})}function b(e,t){if(e.tag!==`Trans`)return;let n=e.props??[],i=e.children??[];if(i.length===0||!i.some(e=>e.type===r?(typeof e.content==`string`?e.content:``).trim().length>0:!0)||n.some(e=>e.type===a&&e.name===`message`))return;let s=f(n,`id`);if(s.kind===`dynamic`)return;let c=f(n,`context`);if(!s.value&&c.kind===`dynamic`)return;let d=f(n,`tag`).value??`span`,p=new Set;for(let e of n)if(e.type===a&&_.has(e.name)&&p.add(e),e.type===o&&e.name===`bind`){let t=typeof e.arg?.content==`string`?e.arg.content:void 0;t&&_.has(t)&&p.add(e)}let h=g(n,p),v=h?` ${h}`:``,y=m(i);if(y.hasElements){let n=`<${d}${v} v-html="$vtRich(${u(y.message.trim(),{id:s.value,context:c.value})}, ${l(y.elements)})"></${d}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:n});return}let b=`<${d}${v}>{{ $t(${u(i.map(e=>e.type===r&&typeof e.content==`string`?e.content:``).join(``).trim(),{id:s.value,context:c.value})}) }}</${d}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:b})}var x=[`zero`,`one`,`two`,`few`,`many`,`other`];function S(e,t){if(e.tag!==`Plural`)return;let i=e.props??[],s=f(i,`id`),c=f(i,`context`);if(s.kind===`dynamic`||!s.value&&c.kind===`dynamic`)return;let d=p(i,`value`);if(!d)return;let h=f(i,`tag`).value??`span`,v=e.children??[],y=[];for(let e of v)if(e.type===n&&e.tag===`template`){let t=(e.props??[]).find(e=>e.type===o&&e.name===`slot`);if(t){let n=typeof t.arg?.content==`string`?t.arg.content:void 0;n&&y.push({cat:n,children:e.children??[]})}}if(y.length>0){let n=[],f=[];for(let e of x){let t=y.find(t=>t.cat===e);if(!t)continue;let i=m(t.children),a;if(i.hasElements){let e=n.length;a=i.message.replace(/<(\d+)(\/?)>/g,(t,n,r)=>`<${e+Number(n)}${r}>`).replace(/<\/(\d+)>/g,(t,n)=>`</${e+Number(n)}>`),n.push(...i.elements)}else a=t.children.map(e=>e.type===r&&typeof e.content==`string`?e.content:``).join(``).trim();let o=e===`zero`?`=0`:e;f.push(`${o} {${a}}`)}if(f.length===0)return;let p=u(`{count, plural, ${f.join(` `)}}`,{id:s.value,context:c.value}),v=new Set([..._,`tag`]),b=new Set;for(let e of i)if(e.type===a&&v.has(e.name)&&b.add(e),e.type===o&&e.name===`bind`){let t=typeof e.arg?.content==`string`?e.arg.content:void 0;(t===`value`||t&&v.has(t))&&b.add(e)}let S=g(i,b),C=S?` ${S}`:``,w;w=n.length>0?`<${h}${C} v-html="$vtRich(${p}, ${l(n)}, { count: ${d} })"></${h}>`:`<${h}${C} v-text="$t(${p}, { count: ${d} })"></${h}>`,t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:w});return}let b=[],S=new Set;for(let e of x){let t=i.find(t=>t.type===a&&t.name===e);if(t){let n=typeof t.value?.content==`string`?t.value.content:``,r=e===`zero`?`=0`:e;b.push(`${r} {${n}}`),S.add(t)}}if(b.length===0)return;let C=u(`{count, plural, ${b.join(` `)}}`,{id:s.value,context:c.value}),w=new Set(S);for(let e of i)if(e.type===a&&(e.name===`tag`||_.has(e.name))&&w.add(e),e.type===o&&e.name===`bind`){let t=typeof e.arg?.content==`string`?e.arg.content:void 0;(t===`value`||t&&_.has(t))&&w.add(e)}let T=g(i,w),E=`<${h}${T?` ${T}`:``} v-text="$t(${C}, { count: ${d} })"></${h}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:E})}function C(e){let t=[];function r(e){if(e.type===n){if(e.tag===`Trans`){b(e,t);return}if(e.tag===`Plural`){S(e,t);return}if((e.props??[]).some(e=>e.type===o&&e.name===`t`)){v(e,t),y(e,t);return}}for(let t of e.children??[])r(t)}return r(e),t}function w(e){if(!/<template[\s>]/.test(e)||e.lastIndexOf(`</template>`)<0)return e;let n=/\bv-t\b/.test(e),r=/<Trans[\s>]/.test(e),i=/<Plural[\s/>]/.test(e);if(!n&&!r&&!i)return e;let{descriptor:a}=(0,t.parse)(e,{pad:!1});if(!a.template?.ast)return e;let o=C(a.template.ast);if(o.length===0)return e;o.sort((e,t)=>t.start-e.start);let s=e;for(let e of o)s=s.slice(0,e.start)+e.replacement+s.slice(e.end);return s}exports.escapeRegExp=c,exports.transformVtDirectives=w;
2
- //# sourceMappingURL=sfc-transform.cjs.map
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@fluenti/core/compiler`),t=require(`@vue/compiler-sfc`);var n=1,r=2,i=5,a=6,o=7;function s(e){return e.replace(/\\/g,`\\\\`).replace(/'/g,`\\'`)}function c(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function l(e){return`[${e.map(e=>{let t=s(e.rawAttrs).replace(/"/g,`&quot;`);return`{ tag: '${s(e.tag)}', rawAttrs: '${t}' }`}).join(`, `)}]`}function u(t,n){return`{ id: '${s(n?.id??(0,e.hashMessage)(t,n?.context))}', message: '${s(t)}' }`}function d(e){return typeof e==`string`?e:e.content??``}function f(e,t){for(let n of e){if(n.type===o&&n.name===`bind`&&(typeof n.arg?.content==`string`?n.arg.content:void 0)===t)return{kind:`dynamic`};if(n.type===a&&n.name===t)return{kind:`static`,value:typeof n.value?.content==`string`?n.value.content:``}}return{kind:`missing`}}function p(e,t){for(let n of e)if(n.type===o&&n.name===`bind`&&(typeof n.arg?.content==`string`?n.arg.content:void 0)===t)return typeof n.exp?.content==`string`?n.exp.content:void 0}function m(e){let t=[],a=``;for(let o of e)if(o.type===r)a+=typeof o.content==`string`?o.content:``;else if(o.type===i)a+=o.loc.source;else if(o.type===n&&o.tag){let e=t.length,n=(o.props??[]).map(e=>e.loc.source).join(` `);if((o.isSelfClosing??!1)||!o.children?.length)t.push({tag:o.tag,rawAttrs:n,selfClosing:!0,innerContent:``}),a+=`<${e}/>`;else{let r=o.children[0],i=o.children[o.children.length-1],s=o.loc.source.slice(r.loc.start.offset-o.loc.start.offset,i.loc.end.offset-o.loc.start.offset);t.push({tag:o.tag,rawAttrs:n,selfClosing:!1,innerContent:s}),a+=`<${e}>${s}</${e}>`}}return{message:a,elements:t,hasElements:t.length>0}}function h(e){let t=[],n=``;for(let a of e)if(a.type===r)n+=typeof a.content==`string`?a.content:``;else if(a.type===i){let e=(typeof a.content==`object`&&a.content&&typeof a.content.content==`string`?a.content.content:``).trim(),r;if(/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e))r=e;else if(/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(e)&&!e.endsWith(`.`)){let t=e.split(`.`);r=t[t.length-1]}else r=String(t.length);t.push(`${r}: ${e}`),n+=`{${r}}`}return{message:n,vars:t}}function g(e,t){return e.filter(e=>!t.has(e)).map(e=>e.loc.source).join(` `)}var _=new Set([`tag`,`id`,`context`,`comment`]);function v(e,t){let n=e.props??[],r=n.find(e=>e.type===o&&e.name===`t`&&(e.modifiers??[]).length>0);if(!r)return;let i=(r.modifiers??[]).map(d);if(i.length===1&&i[0]===`plural`)return;let s=i.find(e=>e!==`plural`);if(!s)return;let c=n.find(e=>e.type===a&&e.name===s);if(!c)return;let l=u(typeof c.value?.content==`string`?c.value.content:``),f=g(n,new Set([r,c])),p=f?` ${f}`:``,m=e.tag;if(e.isSelfClosing){let n=`<${m}${p} :${s}="$t(${l})" />`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:n})}else{let n=e.children??[],r=n.length>0?n[0].loc.start.offset:e.loc.source.indexOf(`>`)+e.loc.start.offset+1,i=`<${m}${p} :${s}="$t(${l})">`;t.push({start:e.loc.start.offset,end:r,replacement:i})}}function y(e,t){let n=e.props??[],i=n.find(e=>e.type===o&&e.name===`t`);if(!i)return;let s=(i.modifiers??[]).map(d),c=s.filter(e=>e!==`plural`);if(c.length>0){let e=c[0];if(n.some(t=>t.type===a&&t.name===e))return}let f=s.includes(`plural`),p=typeof i.exp?.content==`string`?i.exp.content:void 0,_=new Set([`plural`]),v=s.filter(e=>!_.has(e)),y=typeof i.arg?.content==`string`?i.arg.content:void 0,b=y?[y,...v].join(`.`):void 0,x=e.tag,S=e.children??[],C=g(n,new Set([i])),w=C?` ${C}`:``;if(f&&p){let n=S.filter(e=>e.type===r).map(e=>(typeof e.content==`string`?e.content:``).trim()).join(``).split(`|`).map(e=>e.trim()),i=`<${x}${w}>{{ $t(${u(`{${p}, plural, ${(n.length===2?[`one`,`other`]:[`one`,`other`,`zero`,`few`,`many`].slice(0,n.length)).map((e,t)=>`${e} {${n[t]??``}}`).join(` `)}}`,{id:b})}, { ${p} }) }}</${x}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:i});return}let T=m(S);if(T.hasElements){let n=`<${x}${w} v-html="$vtRich(${u(T.message.trim(),{id:b})}, ${l(T.elements)})"></${x}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:n});return}let{message:E,vars:D}=h(S),O=E.trim();if(!O&&!b)return;let k=u(O,{id:b}),A;A=D.length>0?`<${x}${w}>{{ $t(${k}, { ${D.join(`, `)} }) }}</${x}>`:`<${x}${w}>{{ $t(${k}) }}</${x}>`,t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:A})}function b(e,t){if(e.tag!==`Trans`)return;let n=e.props??[],i=e.children??[];if(i.length===0||!i.some(e=>e.type===r?(typeof e.content==`string`?e.content:``).trim().length>0:!0)||n.some(e=>e.type===a&&e.name===`message`))return;let s=f(n,`id`);if(s.kind===`dynamic`)return;let c=f(n,`context`);if(!s.value&&c.kind===`dynamic`)return;let d=f(n,`tag`).value??`span`,p=new Set;for(let e of n)if(e.type===a&&_.has(e.name)&&p.add(e),e.type===o&&e.name===`bind`){let t=typeof e.arg?.content==`string`?e.arg.content:void 0;t&&_.has(t)&&p.add(e)}let h=g(n,p),v=h?` ${h}`:``,y=m(i);if(y.hasElements){let n=`<${d}${v} v-html="$vtRich(${u(y.message.trim(),{id:s.value,context:c.value})}, ${l(y.elements)})"></${d}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:n});return}let b=`<${d}${v}>{{ $t(${u(i.map(e=>e.type===r&&typeof e.content==`string`?e.content:``).join(``).trim(),{id:s.value,context:c.value})}) }}</${d}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:b})}var x=[`zero`,`one`,`two`,`few`,`many`,`other`];function S(e,t){if(e.tag!==`Plural`)return;let i=e.props??[],s=f(i,`id`),c=f(i,`context`);if(s.kind===`dynamic`||!s.value&&c.kind===`dynamic`)return;let d=p(i,`value`);if(!d)return;let h=f(i,`tag`).value??`span`,v=e.children??[],y=[];for(let e of v)if(e.type===n&&e.tag===`template`){let t=(e.props??[]).find(e=>e.type===o&&e.name===`slot`);if(t){let n=typeof t.arg?.content==`string`?t.arg.content:void 0;n&&y.push({cat:n,children:e.children??[]})}}if(y.length>0){let n=[],f=[];for(let e of x){let t=y.find(t=>t.cat===e);if(!t)continue;let i=m(t.children),a;if(i.hasElements){let e=n.length;a=i.message.replace(/<(\d+)(\/?)>/g,(t,n,r)=>`<${e+Number(n)}${r}>`).replace(/<\/(\d+)>/g,(t,n)=>`</${e+Number(n)}>`),n.push(...i.elements)}else a=t.children.map(e=>e.type===r&&typeof e.content==`string`?e.content:``).join(``).trim();let o=e===`zero`?`=0`:e;f.push(`${o} {${a}}`)}if(f.length===0)return;let p=u(`{count, plural, ${f.join(` `)}}`,{id:s.value,context:c.value}),v=new Set([..._,`tag`]),b=new Set;for(let e of i)if(e.type===a&&v.has(e.name)&&b.add(e),e.type===o&&e.name===`bind`){let t=typeof e.arg?.content==`string`?e.arg.content:void 0;(t===`value`||t&&v.has(t))&&b.add(e)}let S=g(i,b),C=S?` ${S}`:``,w;w=n.length>0?`<${h}${C} v-html="$vtRich(${p}, ${l(n)}, { count: ${d} })"></${h}>`:`<${h}${C} v-text="$t(${p}, { count: ${d} })"></${h}>`,t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:w});return}let b=[],S=new Set;for(let e of x){let t=i.find(t=>t.type===a&&t.name===e);if(t){let n=typeof t.value?.content==`string`?t.value.content:``,r=e===`zero`?`=0`:e;b.push(`${r} {${n}}`),S.add(t)}}if(b.length===0)return;let C=u(`{count, plural, ${b.join(` `)}}`,{id:s.value,context:c.value}),w=new Set(S);for(let e of i)if(e.type===a&&(e.name===`tag`||_.has(e.name))&&w.add(e),e.type===o&&e.name===`bind`){let t=typeof e.arg?.content==`string`?e.arg.content:void 0;(t===`value`||t&&_.has(t))&&w.add(e)}let T=g(i,w),E=`<${h}${T?` ${T}`:``} v-text="$t(${C}, { count: ${d} })"></${h}>`;t.push({start:e.loc.start.offset,end:e.loc.end.offset,replacement:E})}function C(e){let t=[];function r(e){if(e.type===n){if(e.tag===`Trans`){b(e,t);return}if(e.tag===`Plural`){S(e,t);return}if((e.props??[]).some(e=>e.type===o&&e.name===`t`)){v(e,t),y(e,t);return}}for(let t of e.children??[])r(t)}return r(e),t}function w(e){if(!/<template[\s>]/.test(e)||e.lastIndexOf(`</template>`)<0)return e;let n=/\bv-t\b/.test(e),r=/<Trans[\s>]/.test(e),i=/<Plural[\s/>]/.test(e);if(!n&&!r&&!i)return e;let{descriptor:a}=(0,t.parse)(e,{pad:!1});if(!a.template?.ast)return e;let o=C(a.template.ast);if(o.length===0)return e;o.sort((e,t)=>t.start-e.start);let s=e;for(let e of o)s=s.slice(0,e.start)+e.replacement+s.slice(e.end);return s}exports.escapeRegExp=c,exports.transformVtDirectives=w;
@@ -307,5 +307,3 @@ function w(e) {
307
307
  }
308
308
  //#endregion
309
309
  export { c as escapeRegExp, w as transformVtDirectives };
310
-
311
- //# sourceMappingURL=sfc-transform.js.map
@@ -20,4 +20,3 @@ export declare function transformForStaticSplit(code: string, options?: BuildTra
20
20
  * Inject the catalog import statement at the top of the module.
21
21
  */
22
22
  export declare function injectCatalogImport(code: string, strategy: 'dynamic' | 'static', hashes: Set<string>, hashFn?: HashFunction): string;
23
- //# sourceMappingURL=build-transform.d.ts.map
@@ -31,4 +31,3 @@ export declare function runExtractCompile(options: DevRunnerOptions): Promise<vo
31
31
  * - Never runs concurrently.
32
32
  */
33
33
  export declare function createDebouncedRunner(options: DevRunnerOptions, delay?: number): () => void;
34
- //# sourceMappingURL=dev-runner.d.ts.map
@@ -10,4 +10,3 @@ export { setResolvedMode, isBuildMode, getPluginEnvironment } from './mode-detec
10
10
  * Framework packages call this with their framework-specific plugins and runtime generator.
11
11
  */
12
12
  export declare function createFluentiPlugins(options: FluentiCoreOptions, frameworkPlugins: Plugin[], runtimeGenerator?: RuntimeGenerator): Plugin[];
13
- //# sourceMappingURL=index.d.ts.map
@@ -21,4 +21,3 @@ export declare function getPluginEnvironment(pluginContext: unknown): {
21
21
  export declare function isBuildMode(environment?: {
22
22
  mode?: string;
23
23
  }): boolean;
24
- //# sourceMappingURL=mode-detect.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export { createRuntimeGenerator } from '@fluenti/core/transform';
2
2
  export type { RuntimePrimitives } from '@fluenti/core/transform';
3
- //# sourceMappingURL=runtime-template.d.ts.map
@@ -1,3 +1,2 @@
1
1
  export declare function escapeRegExp(str: string): string;
2
2
  export declare function transformVtDirectives(sfc: string): string;
3
- //# sourceMappingURL=sfc-transform.d.ts.map
@@ -14,4 +14,3 @@ export interface FluentiCoreOptions {
14
14
  /** Framework identifier for scope transform and runtime key (e.g. 'vue', 'solid', 'react', 'svelte') */
15
15
  framework: string;
16
16
  }
17
- //# sourceMappingURL=types.d.ts.map
@@ -11,4 +11,3 @@ export interface VirtualModuleOptions {
11
11
  }
12
12
  export declare function resolveVirtualSplitId(id: string): string | undefined;
13
13
  export declare function loadVirtualSplitModule(id: string, options: VirtualModuleOptions): string | undefined;
14
- //# sourceMappingURL=virtual-modules.d.ts.map
@@ -54,4 +54,3 @@ interface RichTextResult {
54
54
  }
55
55
  export declare function extractRichTextFromChildren(children: ASTNode[]): RichTextResult;
56
56
  export {};
57
- //# sourceMappingURL=vt-transform.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluenti/vite-plugin",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "type": "module",
5
5
  "description": "Vite plugin for Fluenti — build-time transforms, virtual modules, code splitting",
6
6
  "homepage": "https://fluenti.dev",
@@ -61,7 +61,7 @@
61
61
  "llms*.txt"
62
62
  ],
63
63
  "dependencies": {
64
- "@fluenti/core": "0.6.1"
64
+ "@fluenti/core": "0.6.3"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "vite": "^5 || ^6 || ^8"
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/mode-detect.ts","../src/dev-runner.ts","../src/build-transform.ts","../src/virtual-modules.ts","../src/index.ts"],"sourcesContent":["/**\n * Detect whether Vite is running in build or dev mode.\n * Supports Vite 7 (configResolved) and Vite 8+ (environment API).\n */\n\nlet resolvedMode: 'build' | 'dev' = 'dev'\n\n/** Called from configResolved hook to capture the mode early */\nexport function setResolvedMode(command: string): void {\n resolvedMode = command === 'build' ? 'build' : 'dev'\n}\n\n/** Get the current resolved mode */\nexport function getResolvedMode(): 'build' | 'dev' {\n return resolvedMode\n}\n\n/**\n * Safely extract the environment object from a Vite plugin context.\n * Handles Vite 8+ environment API without direct `(this as any)` casts at call sites.\n */\nexport function getPluginEnvironment(pluginContext: unknown): { mode?: string } | undefined {\n if (\n typeof pluginContext === 'object' &&\n pluginContext !== null &&\n 'environment' in pluginContext\n ) {\n const env = (pluginContext as Record<string, unknown>)['environment']\n if (typeof env === 'object' && env !== null) {\n return env as { mode?: string }\n }\n }\n return undefined\n}\n\n/**\n * Check if we're in build mode.\n * Tries environment API (Vite 8+), then falls back to configResolved capture,\n * then falls back to NODE_ENV.\n */\nexport function isBuildMode(environment?: { mode?: string }): boolean {\n // Vite 8+: environment.mode === 'build'\n if (environment?.mode === 'build') return true\n\n // Vite 7: captured from configResolved\n if (resolvedMode === 'build') return true\n\n // Last resort: NODE_ENV\n if (process.env['NODE_ENV'] === 'production') return true\n\n return false\n}\n","import { join, resolve } from 'node:path'\nimport { createRequire } from 'node:module'\nimport { mkdirSync } from 'node:fs'\n\nexport interface DevRunnerOptions {\n cwd: string\n onSuccess?: () => void\n onError?: (err: Error) => void\n /** If true, reject the promise on failure instead of swallowing the error */\n throwOnError?: boolean\n /** Run only compile (skip extract). Useful for production builds where source is unchanged. */\n compileOnly?: boolean\n /** Enable parallel compilation across locales using worker threads */\n parallelCompile?: boolean\n /** Called before compile runs. Return false to skip compilation. */\n onBeforeCompile?: () => boolean | void | Promise<boolean | void>\n /** Called after compile completes successfully */\n onAfterCompile?: () => void | Promise<void>\n}\n\n/**\n * Run compile in-process via `@fluenti/cli`.\n *\n * In `compileOnly` mode, only compilation is performed (extract is skipped).\n * In dev mode, both extract and compile run in sequence.\n *\n * If `@fluenti/cli` is not installed, shows an install guide instead of\n * falling back to shell-out — keeping the process boundary clean.\n */\nexport async function runExtractCompile(options: DevRunnerOptions): Promise<void> {\n // Ensure compileOutDir exists on first run (auto-init for zero-config DX)\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { DEFAULT_FLUENTI_CONFIG, loadConfigSync } = projectRequire('@fluenti/core/config') as {\n DEFAULT_FLUENTI_CONFIG: { compileOutDir: string; catalogDir: string }\n loadConfigSync: (path?: string, cwd?: string) => { compileOutDir: string; catalogDir: string }\n }\n let config: { compileOutDir: string; catalogDir: string }\n try {\n config = loadConfigSync(undefined, options.cwd)\n } catch {\n config = DEFAULT_FLUENTI_CONFIG\n }\n mkdirSync(resolve(options.cwd, config.compileOutDir), { recursive: true })\n mkdirSync(resolve(options.cwd, config.catalogDir), { recursive: true })\n } catch {\n // Non-critical — directories may already exist or config may not be available\n }\n\n if (options.onBeforeCompile) {\n const result = await options.onBeforeCompile()\n if (result === false) return\n }\n\n if (options.compileOnly) {\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { runCompile } = projectRequire('@fluenti/cli')\n await runCompile(options.cwd)\n console.log('[fluenti] Compiling... done')\n if (options.onAfterCompile) await options.onAfterCompile()\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n if (options.throwOnError) throw error\n console.warn('[fluenti] Compile failed:', error.message)\n options.onError?.(error)\n return\n }\n }\n\n // Dev mode: in-process extract + compile\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { runExtract, runCompile } = projectRequire('@fluenti/cli')\n await runExtract(options.cwd)\n await runCompile(options.cwd, { parallel: options.parallelCompile })\n console.log('[fluenti] Extracting and compiling... done')\n if (options.onAfterCompile) await options.onAfterCompile()\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n const isNotInstalled = error.message.includes('Cannot find module')\n\n if (isNotInstalled) {\n const msg =\n '[fluenti] @fluenti/cli is required for auto-compile.\\n' +\n ' Install it as a devDependency:\\n' +\n ' pnpm add -D @fluenti/cli\\n' +\n ' See: https://fluenti.dev/start/introduction/'\n if (options.throwOnError) throw new Error(msg)\n console.warn(msg)\n options.onError?.(new Error(msg))\n return\n }\n\n if (options.throwOnError) throw error\n console.warn('[fluenti] Extract/compile failed:', error.message)\n options.onError?.(error)\n }\n}\n\n/**\n * Create a debounced runner that collapses rapid calls.\n *\n * - If called while idle, schedules a run after `delay` ms.\n * - If called while a run is in progress, marks a pending rerun.\n * - Never runs concurrently.\n */\nexport function createDebouncedRunner(\n options: DevRunnerOptions,\n delay = 300,\n): () => void {\n let timer: ReturnType<typeof setTimeout> | null = null\n let running = false\n let pendingRerun = false\n\n async function execute(): Promise<void> {\n running = true\n try {\n await runExtractCompile(options)\n } finally {\n running = false\n if (pendingRerun) {\n pendingRerun = false\n schedule()\n }\n }\n }\n\n function schedule(): void {\n if (timer !== null) {\n clearTimeout(timer)\n }\n timer = setTimeout(() => {\n timer = null\n if (running) {\n pendingRerun = true\n } else {\n execute()\n }\n }, delay)\n }\n\n return schedule\n}\n","/**\n * Build-mode transform for code-splitting.\n *\n * Strategy 'dynamic': rewrites supported translation calls to __catalog._<hash> references.\n * Strategy 'static': rewrites to direct named imports from compiled locale modules.\n */\n\nimport { hashMessage as defaultHashMessage } from '@fluenti/core/compiler'\nimport { parseSourceModule, walkSourceAst, type SourceNode } from '@fluenti/core/transform'\n\nexport type HashFunction = (message: string, context?: string) => string\n\nexport interface BuildTransformResult {\n code: string\n needsCatalogImport: boolean\n usedHashes: Set<string>\n}\n\nexport interface BuildTransformOptions {\n /** Custom hash function for message IDs (defaults to @fluenti/core hashMessage) */\n hashFn?: HashFunction\n}\n\ntype SplitStrategy = 'dynamic' | 'static'\n\ninterface IdentifierNode extends SourceNode {\n type: 'Identifier'\n name: string\n}\n\ninterface StringLiteralNode extends SourceNode {\n type: 'StringLiteral'\n value: string\n}\n\ninterface NumericLiteralNode extends SourceNode {\n type: 'NumericLiteral'\n value: number\n}\n\ninterface TemplateElementNode extends SourceNode {\n type: 'TemplateElement'\n value: { cooked: string | null; raw: string }\n}\n\ninterface TemplateLiteralNode extends SourceNode {\n type: 'TemplateLiteral'\n expressions: SourceNode[]\n quasis: TemplateElementNode[]\n}\n\ninterface ImportDeclarationNode extends SourceNode {\n type: 'ImportDeclaration'\n source: StringLiteralNode\n specifiers: SourceNode[]\n}\n\ninterface ImportSpecifierNode extends SourceNode {\n type: 'ImportSpecifier'\n imported: IdentifierNode | StringLiteralNode\n local: IdentifierNode\n}\n\ninterface CallExpressionNode extends SourceNode {\n type: 'CallExpression'\n callee: SourceNode\n arguments: SourceNode[]\n}\n\ninterface AwaitExpressionNode extends SourceNode {\n type: 'AwaitExpression'\n argument: SourceNode\n}\n\ninterface VariableDeclaratorNode extends SourceNode {\n type: 'VariableDeclarator'\n id: SourceNode\n init?: SourceNode | null\n}\n\ninterface ProgramNode extends SourceNode {\n type: 'Program'\n body: SourceNode[]\n}\n\ninterface ObjectExpressionNode extends SourceNode {\n type: 'ObjectExpression'\n properties: SourceNode[]\n}\n\ninterface ObjectPropertyNode extends SourceNode {\n type: 'ObjectProperty'\n key: SourceNode\n value: SourceNode\n computed?: boolean\n}\n\ninterface ObjectPatternNode extends SourceNode {\n type: 'ObjectPattern'\n properties: SourceNode[]\n}\n\ninterface MemberExpressionNode extends SourceNode {\n type: 'MemberExpression'\n object: SourceNode\n property: SourceNode\n computed?: boolean\n}\n\ninterface JSXElementNode extends SourceNode {\n type: 'JSXElement'\n openingElement: JSXOpeningElementNode\n}\n\ninterface JSXOpeningElementNode extends SourceNode {\n type: 'JSXOpeningElement'\n name: SourceNode\n attributes: SourceNode[]\n}\n\ninterface JSXIdentifierNode extends SourceNode {\n type: 'JSXIdentifier'\n name: string\n}\n\ninterface JSXAttributeNode extends SourceNode {\n type: 'JSXAttribute'\n name: JSXIdentifierNode\n value?: SourceNode | null\n}\n\ninterface JSXExpressionContainerNode extends SourceNode {\n type: 'JSXExpressionContainer'\n expression: SourceNode\n}\n\ninterface SplitReplacement {\n start: number\n end: number\n replacement: string\n}\n\ninterface SplitTarget {\n catalogId: string\n valuesSource?: string\n}\n\ninterface RuntimeBindings {\n tracked: Set<string>\n unref: Set<string>\n}\n\nexport function transformForDynamicSplit(code: string, options?: BuildTransformOptions): BuildTransformResult {\n return transformForSplitStrategy(code, 'dynamic', options)\n}\n\nexport function transformForStaticSplit(code: string, options?: BuildTransformOptions): BuildTransformResult {\n return transformForSplitStrategy(code, 'static', options)\n}\n\nfunction transformForSplitStrategy(\n code: string,\n strategy: SplitStrategy,\n options?: BuildTransformOptions,\n): BuildTransformResult {\n const hashFn = options?.hashFn ?? defaultHashMessage\n const ast = parseSourceModule(code)\n if (!ast || ast.type !== 'Program') {\n return { code, needsCatalogImport: false, usedHashes: new Set() }\n }\n\n const bindings = collectTrackedRuntimeBindings(ast as ProgramNode)\n const replacements: SplitReplacement[] = []\n const usedHashes = new Set<string>()\n\n walkSourceAst(ast, (node) => {\n const replacement = extractCallReplacement(code, node, bindings, strategy, usedHashes, hashFn)\n if (replacement) {\n replacements.push(replacement)\n return\n }\n\n collectComponentUsage(node, usedHashes, hashFn)\n })\n\n if (replacements.length === 0) {\n return { code, needsCatalogImport: false, usedHashes }\n }\n\n let result = code\n for (let i = replacements.length - 1; i >= 0; i--) {\n const { start, end, replacement } = replacements[i]!\n result = result.slice(0, start) + replacement + result.slice(end)\n }\n\n return { code: result, needsCatalogImport: true, usedHashes }\n}\n\nfunction collectTrackedRuntimeBindings(program: ProgramNode): RuntimeBindings {\n const tracked = new Set<string>()\n const useI18nBindings = new Set<string>()\n const getI18nBindings = new Set<string>()\n const unrefBindings = new Set<string>()\n\n for (const statement of program.body) {\n if (!isImportDeclaration(statement)) continue\n for (const specifier of statement.specifiers) {\n if (!isImportSpecifier(specifier)) continue\n const importedName = readImportedName(specifier)\n if (!importedName) continue\n if (importedName === 'useI18n') {\n useI18nBindings.add(specifier.local.name)\n }\n if (importedName === 'getI18n') {\n getI18nBindings.add(specifier.local.name)\n }\n if (importedName === 'unref') {\n unrefBindings.add(specifier.local.name)\n }\n }\n }\n\n walkSourceAst(program, (node) => {\n if (!isVariableDeclarator(node) || !node.init || !isObjectPattern(node.id)) return\n\n if (isCallExpression(node.init) && isIdentifier(node.init.callee) && useI18nBindings.has(node.init.callee.name)) {\n addTrackedObjectPatternBindings(node.id, tracked)\n return\n }\n\n const awaitedCall = node.init.type === 'AwaitExpression'\n ? (node.init as AwaitExpressionNode).argument\n : null\n\n if (\n awaitedCall\n && isCallExpression(awaitedCall)\n && isIdentifier(awaitedCall.callee)\n && getI18nBindings.has(awaitedCall.callee.name)\n ) {\n addTrackedObjectPatternBindings(node.id, tracked)\n }\n })\n\n return { tracked, unref: unrefBindings }\n}\n\nfunction addTrackedObjectPatternBindings(pattern: ObjectPatternNode, tracked: Set<string>): void {\n for (const property of pattern.properties) {\n if (!isObjectProperty(property) || property.computed) continue\n if (!isIdentifier(property.key) || property.key.name !== 't') continue\n if (isIdentifier(property.value)) {\n tracked.add(property.value.name)\n }\n }\n}\n\nfunction extractCallReplacement(\n code: string,\n node: SourceNode,\n bindings: RuntimeBindings,\n strategy: SplitStrategy,\n usedHashes: Set<string>,\n hashFn: HashFunction,\n): SplitReplacement | undefined {\n if (!isCallExpression(node) || node.start == null || node.end == null) {\n return undefined\n }\n\n const splitTarget = resolveSplitTarget(code, node, bindings, hashFn)\n if (!splitTarget) {\n return undefined\n }\n\n const { catalogId } = splitTarget\n usedHashes.add(catalogId)\n const exportHash = hashFn(catalogId)\n const replacementTarget = strategy === 'dynamic'\n ? `__catalog[${JSON.stringify(catalogId)}]`\n : `_${exportHash}`\n const replacement = splitTarget.valuesSource\n ? `${replacementTarget}(${splitTarget.valuesSource})`\n : replacementTarget\n\n return {\n start: node.start,\n end: node.end,\n replacement,\n }\n}\n\nfunction resolveSplitTarget(\n code: string,\n call: CallExpressionNode,\n bindings: RuntimeBindings,\n hashFn: HashFunction,\n): SplitTarget | undefined {\n if (call.arguments.length === 0) return undefined\n\n const callee = call.callee\n const isTrackedIdentifierCall = isIdentifier(callee) && (bindings.tracked.has(callee.name) || callee.name === '$t')\n const isTemplateMemberCall = isMemberExpression(callee)\n && !callee.computed\n && isIdentifier(callee.property)\n && (\n callee.property.name === '$t'\n || (\n callee.property.name === 't'\n && isIdentifier(callee.object)\n && (callee.object.name === '_ctx' || callee.object.name === '$setup')\n )\n )\n const isVueUnrefCall = isCallExpression(callee)\n && isIdentifier(callee.callee)\n && bindings.unref.has(callee.callee.name)\n && callee.arguments.length === 1\n && isIdentifier(callee.arguments[0])\n && bindings.tracked.has(callee.arguments[0].name)\n\n if (!isTrackedIdentifierCall && !isTemplateMemberCall && !isVueUnrefCall) {\n return undefined\n }\n\n const catalogId = extractCatalogId(call.arguments[0]!, hashFn)\n if (!catalogId) return undefined\n\n const valuesSource = call.arguments[1] && call.arguments[1]!.start != null && call.arguments[1]!.end != null\n ? code.slice(call.arguments[1]!.start, call.arguments[1]!.end)\n : undefined\n\n return valuesSource === undefined\n ? { catalogId }\n : { catalogId, valuesSource }\n}\n\nfunction extractCatalogId(argument: SourceNode, hashFn: HashFunction): string | undefined {\n const staticString = readStaticString(argument)\n if (staticString !== undefined) {\n return hashFn(staticString)\n }\n\n if (!isObjectExpression(argument)) {\n return undefined\n }\n\n let id: string | undefined\n let message: string | undefined\n let context: string | undefined\n\n for (const property of argument.properties) {\n if (!isObjectProperty(property) || property.computed) continue\n const key = readPropertyKey(property.key)\n if (!key) continue\n\n const value = readStaticString(property.value)\n if (value === undefined) continue\n\n if (key === 'id') id = value\n if (key === 'message') message = value\n if (key === 'context') context = value\n }\n\n if (id) return id\n if (message) return hashFn(message, context)\n return undefined\n}\n\nfunction collectComponentUsage(node: SourceNode, usedHashes: Set<string>, hashFn: HashFunction): void {\n if (!isJsxElement(node)) return\n\n const componentName = readJsxName(node.openingElement.name)\n if (!componentName) return\n\n if (componentName === 'Trans') {\n const id = readJsxStaticAttribute(node.openingElement, '__id') ?? readJsxStaticAttribute(node.openingElement, 'id')\n if (id) {\n usedHashes.add(id)\n return\n }\n\n const message = readJsxStaticAttribute(node.openingElement, '__message')\n const context = readJsxStaticAttribute(node.openingElement, 'context')\n if (message) {\n usedHashes.add(hashFn(message, context))\n }\n return\n }\n\n if (componentName === 'Plural') {\n const messageId = buildPluralMessageId(node.openingElement, hashFn)\n if (messageId) {\n usedHashes.add(messageId)\n }\n return\n }\n\n if (componentName === 'Select') {\n const messageId = buildSelectMessageId(node.openingElement, hashFn)\n if (messageId) {\n usedHashes.add(messageId)\n }\n }\n}\n\nfunction buildPluralMessageId(openingElement: JSXOpeningElementNode, hashFn: HashFunction): string | undefined {\n const id = readJsxStaticAttribute(openingElement, 'id')\n if (id) return id\n\n const context = readJsxStaticAttribute(openingElement, 'context')\n const offsetRaw = readJsxStaticNumber(openingElement, 'offset')\n const forms = [\n readJsxStaticAttribute(openingElement, 'zero') === undefined ? undefined : `=0 {${readJsxStaticAttribute(openingElement, 'zero')}}`,\n readJsxStaticAttribute(openingElement, 'one') === undefined ? undefined : `one {${readJsxStaticAttribute(openingElement, 'one')}}`,\n readJsxStaticAttribute(openingElement, 'two') === undefined ? undefined : `two {${readJsxStaticAttribute(openingElement, 'two')}}`,\n readJsxStaticAttribute(openingElement, 'few') === undefined ? undefined : `few {${readJsxStaticAttribute(openingElement, 'few')}}`,\n readJsxStaticAttribute(openingElement, 'many') === undefined ? undefined : `many {${readJsxStaticAttribute(openingElement, 'many')}}`,\n readJsxStaticAttribute(openingElement, 'other') === undefined ? undefined : `other {${readJsxStaticAttribute(openingElement, 'other')}}`,\n ].filter(Boolean)\n\n if (forms.length === 0) return undefined\n\n const offsetPart = typeof offsetRaw === 'number' ? ` offset:${offsetRaw}` : ''\n const icuMessage = `{count, plural,${offsetPart} ${forms.join(' ')}}`\n return hashFn(icuMessage, context)\n}\n\nfunction buildSelectMessageId(openingElement: JSXOpeningElementNode, hashFn: HashFunction): string | undefined {\n const id = readJsxStaticAttribute(openingElement, 'id')\n if (id) return id\n\n const context = readJsxStaticAttribute(openingElement, 'context')\n const forms = readStaticSelectForms(openingElement)\n if (!forms || forms['other'] === undefined) return undefined\n\n const orderedKeys = [...Object.keys(forms).filter((key) => key !== 'other').sort(), 'other']\n const icuMessage = `{value, select, ${orderedKeys.map((key) => `${key} {${forms[key]!}}`).join(' ')}}`\n return hashFn(icuMessage, context)\n}\n\nfunction readStaticSelectForms(openingElement: JSXOpeningElementNode): Record<string, string> | undefined {\n const optionForms = readJsxStaticObject(openingElement, 'options')\n if (optionForms) {\n const other = readJsxStaticAttribute(openingElement, 'other')\n return {\n ...optionForms,\n ...(other !== undefined ? { other } : {}),\n }\n }\n\n const forms: Record<string, string> = {}\n for (const attribute of openingElement.attributes) {\n if (!isJsxAttribute(attribute)) continue\n const name = attribute.name.name\n if (['value', 'id', 'context', 'comment', 'options'].includes(name)) continue\n const value = readJsxAttributeValue(attribute)\n if (value !== undefined) {\n forms[name] = value\n }\n }\n\n return Object.keys(forms).length > 0 ? forms : undefined\n}\n\nfunction readStaticSelectObjectValue(node: SourceNode): Record<string, string> | undefined {\n if (!isObjectExpression(node)) return undefined\n const values: Record<string, string> = {}\n\n for (const property of node.properties) {\n if (!isObjectProperty(property) || property.computed) return undefined\n const key = readPropertyKey(property.key)\n const value = readStaticString(property.value)\n if (!key || value === undefined) return undefined\n values[key] = value\n }\n\n return values\n}\n\nfunction readJsxStaticObject(openingElement: JSXOpeningElementNode, name: string): Record<string, string> | undefined {\n const attribute = findJsxAttribute(openingElement, name)\n if (!attribute?.value) return undefined\n if (attribute.value.type !== 'JSXExpressionContainer') return undefined\n return readStaticSelectObjectValue((attribute.value as JSXExpressionContainerNode).expression)\n}\n\nfunction readJsxStaticAttribute(openingElement: JSXOpeningElementNode, name: string): string | undefined {\n return readJsxAttributeValue(findJsxAttribute(openingElement, name))\n}\n\nfunction readJsxStaticNumber(openingElement: JSXOpeningElementNode, name: string): number | undefined {\n const attribute = findJsxAttribute(openingElement, name)\n if (!attribute?.value || attribute.value.type !== 'JSXExpressionContainer') return undefined\n const expression = (attribute.value as JSXExpressionContainerNode).expression\n return expression.type === 'NumericLiteral' ? (expression as NumericLiteralNode).value : undefined\n}\n\nfunction findJsxAttribute(openingElement: JSXOpeningElementNode, name: string): JSXAttributeNode | undefined {\n return openingElement.attributes.find((attribute) => {\n return isJsxAttribute(attribute) && attribute.name.name === name\n }) as JSXAttributeNode | undefined\n}\n\nfunction readJsxAttributeValue(attribute: JSXAttributeNode | undefined): string | undefined {\n if (!attribute?.value) return undefined\n\n if (attribute.value.type === 'StringLiteral') {\n return (attribute.value as StringLiteralNode).value\n }\n\n if (attribute.value.type === 'JSXExpressionContainer') {\n return readStaticString((attribute.value as JSXExpressionContainerNode).expression)\n }\n\n return undefined\n}\n\nfunction readJsxName(node: SourceNode): string | undefined {\n return node.type === 'JSXIdentifier' ? (node as JSXIdentifierNode).name : undefined\n}\n\nfunction readStaticString(node: SourceNode): string | undefined {\n if (node.type === 'StringLiteral') {\n return (node as StringLiteralNode).value\n }\n\n if (node.type === 'TemplateLiteral') {\n const template = node as TemplateLiteralNode\n if (template.expressions.length === 0 && template.quasis.length === 1) {\n return template.quasis[0]!.value.cooked ?? template.quasis[0]!.value.raw\n }\n }\n\n return undefined\n}\n\nfunction readPropertyKey(node: SourceNode): string | undefined {\n if (isIdentifier(node)) return node.name\n if (node.type === 'StringLiteral') return (node as StringLiteralNode).value\n return undefined\n}\n\nfunction isImportDeclaration(node: SourceNode): node is ImportDeclarationNode {\n return node.type === 'ImportDeclaration'\n}\n\nfunction isImportSpecifier(node: SourceNode): node is ImportSpecifierNode {\n return node.type === 'ImportSpecifier'\n}\n\nfunction isVariableDeclarator(node: SourceNode): node is VariableDeclaratorNode {\n return node.type === 'VariableDeclarator'\n}\n\nfunction isObjectPattern(node: SourceNode): node is ObjectPatternNode {\n return node.type === 'ObjectPattern'\n}\n\nfunction isObjectExpression(node: SourceNode): node is ObjectExpressionNode {\n return node.type === 'ObjectExpression'\n}\n\nfunction isObjectProperty(node: SourceNode): node is ObjectPropertyNode {\n return node.type === 'ObjectProperty'\n}\n\nfunction isCallExpression(node: SourceNode): node is CallExpressionNode {\n return node.type === 'CallExpression'\n}\n\nfunction isMemberExpression(node: SourceNode): node is MemberExpressionNode {\n return node.type === 'MemberExpression'\n}\n\nfunction isIdentifier(node: SourceNode | undefined | null): node is IdentifierNode {\n return node?.type === 'Identifier'\n}\n\nfunction isJsxElement(node: SourceNode): node is JSXElementNode {\n return node.type === 'JSXElement'\n}\n\nfunction isJsxAttribute(node: SourceNode): node is JSXAttributeNode {\n return node.type === 'JSXAttribute'\n}\n\nfunction readImportedName(specifier: ImportSpecifierNode): string | undefined {\n const imported = specifier.imported\n if (imported.type === 'Identifier') return imported.name\n if (imported.type === 'StringLiteral') return imported.value\n return undefined\n}\n\n/**\n * Inject the catalog import statement at the top of the module.\n */\nexport function injectCatalogImport(code: string, strategy: 'dynamic' | 'static', hashes: Set<string>, hashFn?: HashFunction): string {\n if (strategy === 'dynamic') {\n return `import { __catalog } from 'virtual:fluenti/runtime';\\n${code}`\n }\n\n // Static: import named exports directly\n const hash = hashFn ?? defaultHashMessage\n const imports = [...hashes].map((id) => `_${hash(id)}`).join(', ')\n return `import { ${imports} } from 'virtual:fluenti/messages';\\n${code}`\n}\n","/**\n * Virtual module resolution for code-splitting mode.\n *\n * Provides:\n * - virtual:fluenti/runtime → reactive catalog + switchLocale + preloadLocale\n * - virtual:fluenti/messages → re-export from static locale (for static strategy)\n */\n\nimport { resolve } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { validateLocale } from '@fluenti/core'\nimport type { RuntimeGenerator, RuntimeGeneratorOptions } from './types'\n\n/**\n * Escapes a string value for safe embedding in generated JavaScript code.\n * Returns a JSON-encoded string (with double quotes), preventing injection\n * of quotes, backticks, template interpolation, and other special characters.\n */\nfunction safeStringLiteral(value: string): string {\n return JSON.stringify(value)\n}\n\n/**\n * Validates that a catalog directory path does not contain characters\n * that could enable code injection in generated template literals.\n */\nfunction validateCatalogDir(catalogDir: string): void {\n if (catalogDir.includes('`') || catalogDir.includes('$')) {\n throw new Error(\n `[fluenti] vite-plugin: catalogDir must not contain backticks or $ characters, got ${JSON.stringify(catalogDir)}`,\n )\n }\n}\n\nconst VIRTUAL_RUNTIME = 'virtual:fluenti/runtime'\nconst VIRTUAL_MESSAGES = 'virtual:fluenti/messages'\nconst RESOLVED_RUNTIME = '\\0virtual:fluenti/runtime'\nconst RESOLVED_MESSAGES = '\\0virtual:fluenti/messages'\n\nexport interface VirtualModuleOptions {\n rootDir: string\n catalogDir: string\n catalogExtension: string\n locales: string[]\n sourceLocale: string\n defaultBuildLocale: string\n framework: string\n runtimeGenerator?: RuntimeGenerator | undefined\n}\n\nexport function resolveVirtualSplitId(id: string): string | undefined {\n if (id === VIRTUAL_RUNTIME) return RESOLVED_RUNTIME\n if (id === VIRTUAL_MESSAGES) return RESOLVED_MESSAGES\n return undefined\n}\n\nexport function loadVirtualSplitModule(\n id: string,\n options: VirtualModuleOptions,\n): string | undefined {\n if (id === RESOLVED_RUNTIME) {\n return generateRuntimeModule(options)\n }\n if (id === RESOLVED_MESSAGES) {\n return generateStaticMessagesModule(options)\n }\n return undefined\n}\n\nfunction generateRuntimeModule(options: VirtualModuleOptions): string {\n const { locales, runtimeGenerator, catalogDir } = options\n validateCatalogDir(catalogDir)\n for (const locale of locales) {\n validateLocale(locale, 'vite-plugin')\n }\n\n if (!runtimeGenerator) {\n throw new Error('[fluenti] vite-plugin: runtimeGenerator is required. Use a framework-specific plugin (e.g. @fluenti/vue/vite-plugin).')\n }\n\n return runtimeGenerator.generateRuntime(toRuntimeGeneratorOptions(options))\n}\n\nfunction generateStaticMessagesModule(options: VirtualModuleOptions): string {\n const { rootDir, catalogDir, catalogExtension, defaultBuildLocale, sourceLocale } = options\n const defaultLocale = defaultBuildLocale || sourceLocale\n validateLocale(defaultLocale, 'vite-plugin')\n validateCatalogDir(catalogDir)\n const absoluteCatalogDir = resolve(rootDir, catalogDir)\n const catalogFile = resolve(absoluteCatalogDir, defaultLocale + catalogExtension)\n\n if (!existsSync(catalogFile)) {\n console.warn(\n `[fluenti] Compiled catalog for locale \"${defaultLocale}\" not found at ${catalogFile}. Run \"fluenti compile\" first.`,\n )\n }\n\n return `export * from ${safeStringLiteral(catalogFile)}\\n`\n}\n\nfunction toRuntimeGeneratorOptions(options: VirtualModuleOptions): RuntimeGeneratorOptions {\n const { rootDir, catalogDir, catalogExtension, locales, sourceLocale, defaultBuildLocale } = options\n return { rootDir, catalogDir, catalogExtension, locales, sourceLocale, defaultBuildLocale }\n}\n","import type { Plugin } from 'vite'\nimport { createFilter } from 'vite'\nimport type { FluentiCoreOptions, RuntimeGenerator } from './types'\nimport type { FluentiBuildConfig } from '@fluenti/core/compiler'\nimport { resolveLocaleCodes } from '@fluenti/core/compiler'\nimport { DEFAULT_FLUENTI_CONFIG, loadConfigSync } from '@fluenti/core/config'\nimport { setResolvedMode, isBuildMode, getPluginEnvironment } from './mode-detect'\nimport { createDebouncedRunner, runExtractCompile } from './dev-runner'\nimport { transformForDynamicSplit, transformForStaticSplit, injectCatalogImport } from './build-transform'\nimport { resolveVirtualSplitId, loadVirtualSplitModule } from './virtual-modules'\nimport { createTransformPipeline, hasScopeTransformCandidate } from '@fluenti/core/transform'\nexport type { FluentiPluginOptions, FluentiCoreOptions, RuntimeGenerator, RuntimeGeneratorOptions, IdGenerator } from './types'\nexport { createRuntimeGenerator } from './runtime-template'\nexport type { RuntimePrimitives } from './runtime-template'\nexport { resolveVirtualSplitId, loadVirtualSplitModule } from './virtual-modules'\nexport { setResolvedMode, isBuildMode, getPluginEnvironment } from './mode-detect'\n\nconst VIRTUAL_PREFIX = 'virtual:fluenti/messages/'\nconst RESOLVED_PREFIX = '\\0virtual:fluenti/messages/'\n\n/**\n * Resolve a config option (string path, inline object, or undefined) into a full FluentiBuildConfig.\n */\nfunction resolvePluginConfig(configOption?: string | FluentiBuildConfig, cwd?: string): FluentiBuildConfig {\n if (typeof configOption === 'object') {\n // Inline config — merge with defaults\n return { ...DEFAULT_FLUENTI_CONFIG, ...configOption }\n }\n // string → specified path; undefined → auto-discover\n return loadConfigSync(\n typeof configOption === 'string' ? configOption : undefined,\n cwd,\n )\n}\n\n// ─── Public factory for framework packages ─────────────────────────────────\n\n/**\n * Create the Fluenti plugin pipeline.\n * Framework packages call this with their framework-specific plugins and runtime generator.\n */\nexport function createFluentiPlugins(\n options: FluentiCoreOptions,\n frameworkPlugins: Plugin[],\n runtimeGenerator?: RuntimeGenerator,\n): Plugin[] {\n let fluentiConfig: FluentiBuildConfig | undefined\n let rootDir = process.cwd()\n\n function getConfig(cwd?: string): FluentiBuildConfig {\n const effectiveCwd = cwd ?? rootDir\n if (!fluentiConfig) {\n fluentiConfig = resolvePluginConfig(options.config, effectiveCwd)\n }\n return fluentiConfig\n }\n\n const framework = options.framework\n\n function getResolvedSettings(cwd?: string) {\n const config = getConfig(cwd)\n const catalogDir = config.compileOutDir.replace(/^\\.\\//, '')\n const catalogExtension = config.catalogExtension ?? '.js'\n const rawSplitting = config.splitting ?? false\n if (rawSplitting && rawSplitting !== 'dynamic' && rawSplitting !== 'static') {\n console.warn(`[fluenti] Invalid splitting value \"${rawSplitting}\". Expected 'dynamic', 'static', or false. Falling back to 'dynamic'.`)\n }\n const splitting = rawSplitting === 'static' ? 'static' as const : rawSplitting ? 'dynamic' as const : false as const\n const sourceLocale = config.sourceLocale\n const localeCodes = resolveLocaleCodes(config.locales)\n const defaultBuildLocale = config.defaultBuildLocale ?? sourceLocale\n return {\n config,\n catalogDir,\n catalogExtension,\n splitting,\n sourceLocale,\n localeCodes,\n defaultBuildLocale,\n }\n }\n\n const virtualPlugin: Plugin = {\n name: 'fluenti:virtual',\n configResolved(config) {\n rootDir = config.root\n fluentiConfig = resolvePluginConfig(options.config, rootDir)\n setResolvedMode(config.command)\n },\n resolveId(id) {\n if (id.startsWith(VIRTUAL_PREFIX)) {\n return '\\0' + id\n }\n const { splitting } = getResolvedSettings()\n if (splitting) {\n const resolved = resolveVirtualSplitId(id)\n if (resolved) return resolved\n }\n return undefined\n },\n load(id) {\n const {\n catalogDir,\n catalogExtension,\n splitting,\n localeCodes,\n sourceLocale,\n defaultBuildLocale,\n } = getResolvedSettings()\n if (id.startsWith(RESOLVED_PREFIX)) {\n const locale = id.slice(RESOLVED_PREFIX.length)\n if (!localeCodes.includes(locale)) {\n return undefined\n }\n const catalogPath = `${catalogDir}/${locale}${catalogExtension}`\n return `export { default } from '${catalogPath}'`\n }\n if (splitting) {\n const result = loadVirtualSplitModule(id, {\n rootDir,\n catalogDir,\n catalogExtension,\n locales: localeCodes,\n sourceLocale,\n defaultBuildLocale,\n framework,\n runtimeGenerator,\n })\n if (result) return result\n }\n return undefined\n },\n }\n\n const pipeline = createTransformPipeline({ framework })\n\n const scriptTransformPlugin: Plugin = {\n name: 'fluenti:script-transform',\n enforce: 'pre',\n transform(code, id) {\n if (id.includes('node_modules')) return undefined\n if (!id.match(/\\.(vue|tsx|jsx|ts|js)(\\?|$)/)) return undefined\n if (id.includes('.vue') && !id.includes('type=script')) return undefined\n\n // Vue .vue files need allowTopLevelImportedT for top-level `import { t }`\n const isVueSfc = framework === 'vue' && id.includes('.vue')\n const componentModuleImport = `@fluenti/${framework}/components`\n\n let result = code\n let changed = false\n\n // ── <Trans> compile-time optimization (JSX/TSX only) ──────────────\n if (id.match(/\\.[jt]sx(\\?|$)/) && /<Trans[\\s>]/.test(result)) {\n const transResult = pipeline.transformTrans(result)\n if (transResult.transformed) {\n result = transResult.code\n changed = true\n }\n }\n\n if (\n id.match(/\\.[jt]sx(\\?|$)/)\n && (framework === 'react' || framework === 'solid')\n && /<(Plural|Select)[\\s/>]/.test(result)\n ) {\n const componentResult = pipeline.transformPluralSelect(result, componentModuleImport)\n if (componentResult.transformed) {\n result = componentResult.code\n changed = true\n }\n }\n\n // ── t`` / t() scope-aware transform ────────────────────────────────\n if (hasScopeTransformCandidate(result)) {\n const scoped = pipeline.transformScope(result, {\n componentModuleImport,\n ...(isVueSfc ? { allowTopLevelImportedT: true } : {}),\n })\n if (scoped.transformed) {\n return { code: scoped.code, map: null }\n }\n }\n\n return changed ? { code: result, map: null } : undefined\n },\n }\n\n const buildSplitPlugin: Plugin = {\n name: 'fluenti:build-split',\n transform(code, id) {\n const { splitting, config } = getResolvedSettings()\n if (!splitting) return undefined\n if (!isBuildMode(getPluginEnvironment(this))) return undefined\n if (id.includes('node_modules')) return undefined\n if (!id.match(/\\.(vue|tsx|jsx|ts|js)(\\?|$)/)) return undefined\n\n const strategy = splitting === 'static' ? 'static' : 'dynamic'\n const transformOptions = config.idGenerator ? { hashFn: config.idGenerator } : undefined\n const transformed = strategy === 'static'\n ? transformForStaticSplit(code, transformOptions)\n : transformForDynamicSplit(code, transformOptions)\n\n if (!transformed.needsCatalogImport) return undefined\n\n const finalCode = injectCatalogImport(\n transformed.code,\n strategy,\n transformed.usedHashes,\n config.idGenerator,\n )\n return { code: finalCode, map: null }\n },\n }\n\n const buildCompilePlugin: Plugin = {\n name: 'fluenti:build-compile',\n async buildStart() {\n const { config } = getResolvedSettings()\n if (!isBuildMode(getPluginEnvironment(this))) return\n const buildAutoCompile = config.buildAutoCompile ?? true\n if (!buildAutoCompile) return\n if (config.onBeforeCompile) {\n const result = await config.onBeforeCompile()\n if (result === false) return\n }\n await runExtractCompile({ cwd: rootDir, throwOnError: true, compileOnly: true })\n if (config.onAfterCompile) {\n await config.onAfterCompile()\n }\n },\n }\n\n const devPlugin: Plugin = {\n name: 'fluenti:dev',\n configureServer(server) {\n const { config, catalogDir } = getResolvedSettings(server.config.root)\n const devAutoCompile = config.devAutoCompile ?? true\n if (!devAutoCompile) return\n\n const includePatterns = config.include ?? ['src/**/*.{vue,tsx,jsx,ts,js}']\n const excludePatterns = config.exclude ?? []\n\n const filter = createFilter(includePatterns, [\n ...excludePatterns,\n '**/node_modules/**',\n `**/${catalogDir}/**`,\n ])\n\n const runnerOptions: Parameters<typeof createDebouncedRunner>[0] = {\n cwd: server.config.root,\n onSuccess: () => {\n // Existing hotUpdate will pick up catalog changes\n },\n }\n if (config.parallelCompile) runnerOptions.parallelCompile = true\n if (config.onBeforeCompile) runnerOptions.onBeforeCompile = config.onBeforeCompile\n if (config.onAfterCompile) runnerOptions.onAfterCompile = config.onAfterCompile\n const debouncedRun = createDebouncedRunner(runnerOptions, config.devAutoCompileDelay ?? 500)\n\n debouncedRun()\n\n server.watcher.on('change', (file) => {\n if (filter(file)) {\n debouncedRun()\n }\n })\n },\n hotUpdate({ file }) {\n const { catalogDir } = getResolvedSettings()\n if (file.includes(catalogDir)) {\n const modules = [...this.environment.moduleGraph.urlToModuleMap.entries()]\n .filter(([url]) => url.includes('virtual:fluenti'))\n .map(([, mod]) => mod)\n\n if (modules.length > 0) {\n return modules\n }\n }\n return undefined\n },\n }\n\n // Plugin order matters:\n // 1. virtualPlugin — resolves virtual:fluenti/* module IDs (must be first)\n // 2. frameworkPlugins — framework-specific template transforms (e.g., Vue v-t directive)\n // must run after virtual resolution but before script transforms\n // 3. scriptTransformPlugin — t()/t`` scope transforms + <Trans> optimization (enforce: 'pre')\n // 4. buildCompilePlugin — triggers extract+compile before the build starts\n // 5. buildSplitPlugin — rewrites t() calls to catalog refs (dynamic/static)\n // 6. devPlugin — file watcher + HMR for dev mode (must be last)\n return [virtualPlugin, ...frameworkPlugins, scriptTransformPlugin, buildCompilePlugin, buildSplitPlugin, devPlugin]\n}\n"],"mappings":"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"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/mode-detect.ts","../src/dev-runner.ts","../src/build-transform.ts","../src/virtual-modules.ts","../src/index.ts"],"sourcesContent":["/**\n * Detect whether Vite is running in build or dev mode.\n * Supports Vite 7 (configResolved) and Vite 8+ (environment API).\n */\n\nlet resolvedMode: 'build' | 'dev' = 'dev'\n\n/** Called from configResolved hook to capture the mode early */\nexport function setResolvedMode(command: string): void {\n resolvedMode = command === 'build' ? 'build' : 'dev'\n}\n\n/** Get the current resolved mode */\nexport function getResolvedMode(): 'build' | 'dev' {\n return resolvedMode\n}\n\n/**\n * Safely extract the environment object from a Vite plugin context.\n * Handles Vite 8+ environment API without direct `(this as any)` casts at call sites.\n */\nexport function getPluginEnvironment(pluginContext: unknown): { mode?: string } | undefined {\n if (\n typeof pluginContext === 'object' &&\n pluginContext !== null &&\n 'environment' in pluginContext\n ) {\n const env = (pluginContext as Record<string, unknown>)['environment']\n if (typeof env === 'object' && env !== null) {\n return env as { mode?: string }\n }\n }\n return undefined\n}\n\n/**\n * Check if we're in build mode.\n * Tries environment API (Vite 8+), then falls back to configResolved capture,\n * then falls back to NODE_ENV.\n */\nexport function isBuildMode(environment?: { mode?: string }): boolean {\n // Vite 8+: environment.mode === 'build'\n if (environment?.mode === 'build') return true\n\n // Vite 7: captured from configResolved\n if (resolvedMode === 'build') return true\n\n // Last resort: NODE_ENV\n if (process.env['NODE_ENV'] === 'production') return true\n\n return false\n}\n","import { join, resolve } from 'node:path'\nimport { createRequire } from 'node:module'\nimport { mkdirSync } from 'node:fs'\n\nexport interface DevRunnerOptions {\n cwd: string\n onSuccess?: () => void\n onError?: (err: Error) => void\n /** If true, reject the promise on failure instead of swallowing the error */\n throwOnError?: boolean\n /** Run only compile (skip extract). Useful for production builds where source is unchanged. */\n compileOnly?: boolean\n /** Enable parallel compilation across locales using worker threads */\n parallelCompile?: boolean\n /** Called before compile runs. Return false to skip compilation. */\n onBeforeCompile?: () => boolean | void | Promise<boolean | void>\n /** Called after compile completes successfully */\n onAfterCompile?: () => void | Promise<void>\n}\n\n/**\n * Run compile in-process via `@fluenti/cli`.\n *\n * In `compileOnly` mode, only compilation is performed (extract is skipped).\n * In dev mode, both extract and compile run in sequence.\n *\n * If `@fluenti/cli` is not installed, shows an install guide instead of\n * falling back to shell-out — keeping the process boundary clean.\n */\nexport async function runExtractCompile(options: DevRunnerOptions): Promise<void> {\n // Ensure compileOutDir exists on first run (auto-init for zero-config DX)\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { DEFAULT_FLUENTI_CONFIG, loadConfigSync } = projectRequire('@fluenti/core/config') as {\n DEFAULT_FLUENTI_CONFIG: { compileOutDir: string; catalogDir: string }\n loadConfigSync: (path?: string, cwd?: string) => { compileOutDir: string; catalogDir: string }\n }\n let config: { compileOutDir: string; catalogDir: string }\n try {\n config = loadConfigSync(undefined, options.cwd)\n } catch {\n config = DEFAULT_FLUENTI_CONFIG\n }\n mkdirSync(resolve(options.cwd, config.compileOutDir), { recursive: true })\n mkdirSync(resolve(options.cwd, config.catalogDir), { recursive: true })\n } catch {\n // Non-critical — directories may already exist or config may not be available\n }\n\n if (options.onBeforeCompile) {\n const result = await options.onBeforeCompile()\n if (result === false) return\n }\n\n if (options.compileOnly) {\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { runCompile } = projectRequire('@fluenti/cli')\n await runCompile(options.cwd)\n console.log('[fluenti] Compiling... done')\n if (options.onAfterCompile) await options.onAfterCompile()\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n if (options.throwOnError) throw error\n console.warn('[fluenti] Compile failed:', error.message)\n options.onError?.(error)\n return\n }\n }\n\n // Dev mode: in-process extract + compile\n try {\n const projectRequire = createRequire(join(options.cwd, 'package.json'))\n const { runExtract, runCompile } = projectRequire('@fluenti/cli')\n await runExtract(options.cwd)\n await runCompile(options.cwd, { parallel: options.parallelCompile })\n console.log('[fluenti] Extracting and compiling... done')\n if (options.onAfterCompile) await options.onAfterCompile()\n options.onSuccess?.()\n return\n } catch (e) {\n const error = e instanceof Error ? e : new Error(String(e))\n const isNotInstalled = error.message.includes('Cannot find module')\n\n if (isNotInstalled) {\n const msg =\n '[fluenti] @fluenti/cli is required for auto-compile.\\n' +\n ' Install it as a devDependency:\\n' +\n ' pnpm add -D @fluenti/cli\\n' +\n ' See: https://fluenti.dev/start/introduction/'\n if (options.throwOnError) throw new Error(msg)\n console.warn(msg)\n options.onError?.(new Error(msg))\n return\n }\n\n if (options.throwOnError) throw error\n console.warn('[fluenti] Extract/compile failed:', error.message)\n options.onError?.(error)\n }\n}\n\n/**\n * Create a debounced runner that collapses rapid calls.\n *\n * - If called while idle, schedules a run after `delay` ms.\n * - If called while a run is in progress, marks a pending rerun.\n * - Never runs concurrently.\n */\nexport function createDebouncedRunner(\n options: DevRunnerOptions,\n delay = 300,\n): () => void {\n let timer: ReturnType<typeof setTimeout> | null = null\n let running = false\n let pendingRerun = false\n\n async function execute(): Promise<void> {\n running = true\n try {\n await runExtractCompile(options)\n } finally {\n running = false\n if (pendingRerun) {\n pendingRerun = false\n schedule()\n }\n }\n }\n\n function schedule(): void {\n if (timer !== null) {\n clearTimeout(timer)\n }\n timer = setTimeout(() => {\n timer = null\n if (running) {\n pendingRerun = true\n } else {\n execute()\n }\n }, delay)\n }\n\n return schedule\n}\n","/**\n * Build-mode transform for code-splitting.\n *\n * Strategy 'dynamic': rewrites supported translation calls to __catalog._<hash> references.\n * Strategy 'static': rewrites to direct named imports from compiled locale modules.\n */\n\nimport { hashMessage as defaultHashMessage } from '@fluenti/core/compiler'\nimport { parseSourceModule, walkSourceAst, type SourceNode } from '@fluenti/core/transform'\n\nexport type HashFunction = (message: string, context?: string) => string\n\nexport interface BuildTransformResult {\n code: string\n needsCatalogImport: boolean\n usedHashes: Set<string>\n}\n\nexport interface BuildTransformOptions {\n /** Custom hash function for message IDs (defaults to @fluenti/core hashMessage) */\n hashFn?: HashFunction\n}\n\ntype SplitStrategy = 'dynamic' | 'static'\n\ninterface IdentifierNode extends SourceNode {\n type: 'Identifier'\n name: string\n}\n\ninterface StringLiteralNode extends SourceNode {\n type: 'StringLiteral'\n value: string\n}\n\ninterface NumericLiteralNode extends SourceNode {\n type: 'NumericLiteral'\n value: number\n}\n\ninterface TemplateElementNode extends SourceNode {\n type: 'TemplateElement'\n value: { cooked: string | null; raw: string }\n}\n\ninterface TemplateLiteralNode extends SourceNode {\n type: 'TemplateLiteral'\n expressions: SourceNode[]\n quasis: TemplateElementNode[]\n}\n\ninterface ImportDeclarationNode extends SourceNode {\n type: 'ImportDeclaration'\n source: StringLiteralNode\n specifiers: SourceNode[]\n}\n\ninterface ImportSpecifierNode extends SourceNode {\n type: 'ImportSpecifier'\n imported: IdentifierNode | StringLiteralNode\n local: IdentifierNode\n}\n\ninterface CallExpressionNode extends SourceNode {\n type: 'CallExpression'\n callee: SourceNode\n arguments: SourceNode[]\n}\n\ninterface AwaitExpressionNode extends SourceNode {\n type: 'AwaitExpression'\n argument: SourceNode\n}\n\ninterface VariableDeclaratorNode extends SourceNode {\n type: 'VariableDeclarator'\n id: SourceNode\n init?: SourceNode | null\n}\n\ninterface ProgramNode extends SourceNode {\n type: 'Program'\n body: SourceNode[]\n}\n\ninterface ObjectExpressionNode extends SourceNode {\n type: 'ObjectExpression'\n properties: SourceNode[]\n}\n\ninterface ObjectPropertyNode extends SourceNode {\n type: 'ObjectProperty'\n key: SourceNode\n value: SourceNode\n computed?: boolean\n}\n\ninterface ObjectPatternNode extends SourceNode {\n type: 'ObjectPattern'\n properties: SourceNode[]\n}\n\ninterface MemberExpressionNode extends SourceNode {\n type: 'MemberExpression'\n object: SourceNode\n property: SourceNode\n computed?: boolean\n}\n\ninterface JSXElementNode extends SourceNode {\n type: 'JSXElement'\n openingElement: JSXOpeningElementNode\n}\n\ninterface JSXOpeningElementNode extends SourceNode {\n type: 'JSXOpeningElement'\n name: SourceNode\n attributes: SourceNode[]\n}\n\ninterface JSXIdentifierNode extends SourceNode {\n type: 'JSXIdentifier'\n name: string\n}\n\ninterface JSXAttributeNode extends SourceNode {\n type: 'JSXAttribute'\n name: JSXIdentifierNode\n value?: SourceNode | null\n}\n\ninterface JSXExpressionContainerNode extends SourceNode {\n type: 'JSXExpressionContainer'\n expression: SourceNode\n}\n\ninterface SplitReplacement {\n start: number\n end: number\n replacement: string\n}\n\ninterface SplitTarget {\n catalogId: string\n valuesSource?: string\n}\n\ninterface RuntimeBindings {\n tracked: Set<string>\n unref: Set<string>\n}\n\nexport function transformForDynamicSplit(code: string, options?: BuildTransformOptions): BuildTransformResult {\n return transformForSplitStrategy(code, 'dynamic', options)\n}\n\nexport function transformForStaticSplit(code: string, options?: BuildTransformOptions): BuildTransformResult {\n return transformForSplitStrategy(code, 'static', options)\n}\n\nfunction transformForSplitStrategy(\n code: string,\n strategy: SplitStrategy,\n options?: BuildTransformOptions,\n): BuildTransformResult {\n const hashFn = options?.hashFn ?? defaultHashMessage\n const ast = parseSourceModule(code)\n if (!ast || ast.type !== 'Program') {\n return { code, needsCatalogImport: false, usedHashes: new Set() }\n }\n\n const bindings = collectTrackedRuntimeBindings(ast as ProgramNode)\n const replacements: SplitReplacement[] = []\n const usedHashes = new Set<string>()\n\n walkSourceAst(ast, (node) => {\n const replacement = extractCallReplacement(code, node, bindings, strategy, usedHashes, hashFn)\n if (replacement) {\n replacements.push(replacement)\n return\n }\n\n collectComponentUsage(node, usedHashes, hashFn)\n })\n\n if (replacements.length === 0) {\n return { code, needsCatalogImport: false, usedHashes }\n }\n\n let result = code\n for (let i = replacements.length - 1; i >= 0; i--) {\n const { start, end, replacement } = replacements[i]!\n result = result.slice(0, start) + replacement + result.slice(end)\n }\n\n return { code: result, needsCatalogImport: true, usedHashes }\n}\n\nfunction collectTrackedRuntimeBindings(program: ProgramNode): RuntimeBindings {\n const tracked = new Set<string>()\n const useI18nBindings = new Set<string>()\n const getI18nBindings = new Set<string>()\n const unrefBindings = new Set<string>()\n\n for (const statement of program.body) {\n if (!isImportDeclaration(statement)) continue\n for (const specifier of statement.specifiers) {\n if (!isImportSpecifier(specifier)) continue\n const importedName = readImportedName(specifier)\n if (!importedName) continue\n if (importedName === 'useI18n') {\n useI18nBindings.add(specifier.local.name)\n }\n if (importedName === 'getI18n') {\n getI18nBindings.add(specifier.local.name)\n }\n if (importedName === 'unref') {\n unrefBindings.add(specifier.local.name)\n }\n }\n }\n\n walkSourceAst(program, (node) => {\n if (!isVariableDeclarator(node) || !node.init || !isObjectPattern(node.id)) return\n\n if (isCallExpression(node.init) && isIdentifier(node.init.callee) && useI18nBindings.has(node.init.callee.name)) {\n addTrackedObjectPatternBindings(node.id, tracked)\n return\n }\n\n const awaitedCall = node.init.type === 'AwaitExpression'\n ? (node.init as AwaitExpressionNode).argument\n : null\n\n if (\n awaitedCall\n && isCallExpression(awaitedCall)\n && isIdentifier(awaitedCall.callee)\n && getI18nBindings.has(awaitedCall.callee.name)\n ) {\n addTrackedObjectPatternBindings(node.id, tracked)\n }\n })\n\n return { tracked, unref: unrefBindings }\n}\n\nfunction addTrackedObjectPatternBindings(pattern: ObjectPatternNode, tracked: Set<string>): void {\n for (const property of pattern.properties) {\n if (!isObjectProperty(property) || property.computed) continue\n if (!isIdentifier(property.key) || property.key.name !== 't') continue\n if (isIdentifier(property.value)) {\n tracked.add(property.value.name)\n }\n }\n}\n\nfunction extractCallReplacement(\n code: string,\n node: SourceNode,\n bindings: RuntimeBindings,\n strategy: SplitStrategy,\n usedHashes: Set<string>,\n hashFn: HashFunction,\n): SplitReplacement | undefined {\n if (!isCallExpression(node) || node.start == null || node.end == null) {\n return undefined\n }\n\n const splitTarget = resolveSplitTarget(code, node, bindings, hashFn)\n if (!splitTarget) {\n return undefined\n }\n\n const { catalogId } = splitTarget\n usedHashes.add(catalogId)\n const exportHash = hashFn(catalogId)\n const replacementTarget = strategy === 'dynamic'\n ? `__catalog[${JSON.stringify(catalogId)}]`\n : `_${exportHash}`\n const replacement = splitTarget.valuesSource\n ? `${replacementTarget}(${splitTarget.valuesSource})`\n : replacementTarget\n\n return {\n start: node.start,\n end: node.end,\n replacement,\n }\n}\n\nfunction resolveSplitTarget(\n code: string,\n call: CallExpressionNode,\n bindings: RuntimeBindings,\n hashFn: HashFunction,\n): SplitTarget | undefined {\n if (call.arguments.length === 0) return undefined\n\n const callee = call.callee\n const isTrackedIdentifierCall = isIdentifier(callee) && (bindings.tracked.has(callee.name) || callee.name === '$t')\n const isTemplateMemberCall = isMemberExpression(callee)\n && !callee.computed\n && isIdentifier(callee.property)\n && (\n callee.property.name === '$t'\n || (\n callee.property.name === 't'\n && isIdentifier(callee.object)\n && (callee.object.name === '_ctx' || callee.object.name === '$setup')\n )\n )\n const isVueUnrefCall = isCallExpression(callee)\n && isIdentifier(callee.callee)\n && bindings.unref.has(callee.callee.name)\n && callee.arguments.length === 1\n && isIdentifier(callee.arguments[0])\n && bindings.tracked.has(callee.arguments[0].name)\n\n if (!isTrackedIdentifierCall && !isTemplateMemberCall && !isVueUnrefCall) {\n return undefined\n }\n\n const catalogId = extractCatalogId(call.arguments[0]!, hashFn)\n if (!catalogId) return undefined\n\n const valuesSource = call.arguments[1] && call.arguments[1]!.start != null && call.arguments[1]!.end != null\n ? code.slice(call.arguments[1]!.start, call.arguments[1]!.end)\n : undefined\n\n return valuesSource === undefined\n ? { catalogId }\n : { catalogId, valuesSource }\n}\n\nfunction extractCatalogId(argument: SourceNode, hashFn: HashFunction): string | undefined {\n const staticString = readStaticString(argument)\n if (staticString !== undefined) {\n return hashFn(staticString)\n }\n\n if (!isObjectExpression(argument)) {\n return undefined\n }\n\n let id: string | undefined\n let message: string | undefined\n let context: string | undefined\n\n for (const property of argument.properties) {\n if (!isObjectProperty(property) || property.computed) continue\n const key = readPropertyKey(property.key)\n if (!key) continue\n\n const value = readStaticString(property.value)\n if (value === undefined) continue\n\n if (key === 'id') id = value\n if (key === 'message') message = value\n if (key === 'context') context = value\n }\n\n if (id) return id\n if (message) return hashFn(message, context)\n return undefined\n}\n\nfunction collectComponentUsage(node: SourceNode, usedHashes: Set<string>, hashFn: HashFunction): void {\n if (!isJsxElement(node)) return\n\n const componentName = readJsxName(node.openingElement.name)\n if (!componentName) return\n\n if (componentName === 'Trans') {\n const id = readJsxStaticAttribute(node.openingElement, '__id') ?? readJsxStaticAttribute(node.openingElement, 'id')\n if (id) {\n usedHashes.add(id)\n return\n }\n\n const message = readJsxStaticAttribute(node.openingElement, '__message')\n const context = readJsxStaticAttribute(node.openingElement, 'context')\n if (message) {\n usedHashes.add(hashFn(message, context))\n }\n return\n }\n\n if (componentName === 'Plural') {\n const messageId = buildPluralMessageId(node.openingElement, hashFn)\n if (messageId) {\n usedHashes.add(messageId)\n }\n return\n }\n\n if (componentName === 'Select') {\n const messageId = buildSelectMessageId(node.openingElement, hashFn)\n if (messageId) {\n usedHashes.add(messageId)\n }\n }\n}\n\nfunction buildPluralMessageId(openingElement: JSXOpeningElementNode, hashFn: HashFunction): string | undefined {\n const id = readJsxStaticAttribute(openingElement, 'id')\n if (id) return id\n\n const context = readJsxStaticAttribute(openingElement, 'context')\n const offsetRaw = readJsxStaticNumber(openingElement, 'offset')\n const forms = [\n readJsxStaticAttribute(openingElement, 'zero') === undefined ? undefined : `=0 {${readJsxStaticAttribute(openingElement, 'zero')}}`,\n readJsxStaticAttribute(openingElement, 'one') === undefined ? undefined : `one {${readJsxStaticAttribute(openingElement, 'one')}}`,\n readJsxStaticAttribute(openingElement, 'two') === undefined ? undefined : `two {${readJsxStaticAttribute(openingElement, 'two')}}`,\n readJsxStaticAttribute(openingElement, 'few') === undefined ? undefined : `few {${readJsxStaticAttribute(openingElement, 'few')}}`,\n readJsxStaticAttribute(openingElement, 'many') === undefined ? undefined : `many {${readJsxStaticAttribute(openingElement, 'many')}}`,\n readJsxStaticAttribute(openingElement, 'other') === undefined ? undefined : `other {${readJsxStaticAttribute(openingElement, 'other')}}`,\n ].filter(Boolean)\n\n if (forms.length === 0) return undefined\n\n const offsetPart = typeof offsetRaw === 'number' ? ` offset:${offsetRaw}` : ''\n const icuMessage = `{count, plural,${offsetPart} ${forms.join(' ')}}`\n return hashFn(icuMessage, context)\n}\n\nfunction buildSelectMessageId(openingElement: JSXOpeningElementNode, hashFn: HashFunction): string | undefined {\n const id = readJsxStaticAttribute(openingElement, 'id')\n if (id) return id\n\n const context = readJsxStaticAttribute(openingElement, 'context')\n const forms = readStaticSelectForms(openingElement)\n if (!forms || forms['other'] === undefined) return undefined\n\n const orderedKeys = [...Object.keys(forms).filter((key) => key !== 'other').sort(), 'other']\n const icuMessage = `{value, select, ${orderedKeys.map((key) => `${key} {${forms[key]!}}`).join(' ')}}`\n return hashFn(icuMessage, context)\n}\n\nfunction readStaticSelectForms(openingElement: JSXOpeningElementNode): Record<string, string> | undefined {\n const optionForms = readJsxStaticObject(openingElement, 'options')\n if (optionForms) {\n const other = readJsxStaticAttribute(openingElement, 'other')\n return {\n ...optionForms,\n ...(other !== undefined ? { other } : {}),\n }\n }\n\n const forms: Record<string, string> = {}\n for (const attribute of openingElement.attributes) {\n if (!isJsxAttribute(attribute)) continue\n const name = attribute.name.name\n if (['value', 'id', 'context', 'comment', 'options'].includes(name)) continue\n const value = readJsxAttributeValue(attribute)\n if (value !== undefined) {\n forms[name] = value\n }\n }\n\n return Object.keys(forms).length > 0 ? forms : undefined\n}\n\nfunction readStaticSelectObjectValue(node: SourceNode): Record<string, string> | undefined {\n if (!isObjectExpression(node)) return undefined\n const values: Record<string, string> = {}\n\n for (const property of node.properties) {\n if (!isObjectProperty(property) || property.computed) return undefined\n const key = readPropertyKey(property.key)\n const value = readStaticString(property.value)\n if (!key || value === undefined) return undefined\n values[key] = value\n }\n\n return values\n}\n\nfunction readJsxStaticObject(openingElement: JSXOpeningElementNode, name: string): Record<string, string> | undefined {\n const attribute = findJsxAttribute(openingElement, name)\n if (!attribute?.value) return undefined\n if (attribute.value.type !== 'JSXExpressionContainer') return undefined\n return readStaticSelectObjectValue((attribute.value as JSXExpressionContainerNode).expression)\n}\n\nfunction readJsxStaticAttribute(openingElement: JSXOpeningElementNode, name: string): string | undefined {\n return readJsxAttributeValue(findJsxAttribute(openingElement, name))\n}\n\nfunction readJsxStaticNumber(openingElement: JSXOpeningElementNode, name: string): number | undefined {\n const attribute = findJsxAttribute(openingElement, name)\n if (!attribute?.value || attribute.value.type !== 'JSXExpressionContainer') return undefined\n const expression = (attribute.value as JSXExpressionContainerNode).expression\n return expression.type === 'NumericLiteral' ? (expression as NumericLiteralNode).value : undefined\n}\n\nfunction findJsxAttribute(openingElement: JSXOpeningElementNode, name: string): JSXAttributeNode | undefined {\n return openingElement.attributes.find((attribute) => {\n return isJsxAttribute(attribute) && attribute.name.name === name\n }) as JSXAttributeNode | undefined\n}\n\nfunction readJsxAttributeValue(attribute: JSXAttributeNode | undefined): string | undefined {\n if (!attribute?.value) return undefined\n\n if (attribute.value.type === 'StringLiteral') {\n return (attribute.value as StringLiteralNode).value\n }\n\n if (attribute.value.type === 'JSXExpressionContainer') {\n return readStaticString((attribute.value as JSXExpressionContainerNode).expression)\n }\n\n return undefined\n}\n\nfunction readJsxName(node: SourceNode): string | undefined {\n return node.type === 'JSXIdentifier' ? (node as JSXIdentifierNode).name : undefined\n}\n\nfunction readStaticString(node: SourceNode): string | undefined {\n if (node.type === 'StringLiteral') {\n return (node as StringLiteralNode).value\n }\n\n if (node.type === 'TemplateLiteral') {\n const template = node as TemplateLiteralNode\n if (template.expressions.length === 0 && template.quasis.length === 1) {\n return template.quasis[0]!.value.cooked ?? template.quasis[0]!.value.raw\n }\n }\n\n return undefined\n}\n\nfunction readPropertyKey(node: SourceNode): string | undefined {\n if (isIdentifier(node)) return node.name\n if (node.type === 'StringLiteral') return (node as StringLiteralNode).value\n return undefined\n}\n\nfunction isImportDeclaration(node: SourceNode): node is ImportDeclarationNode {\n return node.type === 'ImportDeclaration'\n}\n\nfunction isImportSpecifier(node: SourceNode): node is ImportSpecifierNode {\n return node.type === 'ImportSpecifier'\n}\n\nfunction isVariableDeclarator(node: SourceNode): node is VariableDeclaratorNode {\n return node.type === 'VariableDeclarator'\n}\n\nfunction isObjectPattern(node: SourceNode): node is ObjectPatternNode {\n return node.type === 'ObjectPattern'\n}\n\nfunction isObjectExpression(node: SourceNode): node is ObjectExpressionNode {\n return node.type === 'ObjectExpression'\n}\n\nfunction isObjectProperty(node: SourceNode): node is ObjectPropertyNode {\n return node.type === 'ObjectProperty'\n}\n\nfunction isCallExpression(node: SourceNode): node is CallExpressionNode {\n return node.type === 'CallExpression'\n}\n\nfunction isMemberExpression(node: SourceNode): node is MemberExpressionNode {\n return node.type === 'MemberExpression'\n}\n\nfunction isIdentifier(node: SourceNode | undefined | null): node is IdentifierNode {\n return node?.type === 'Identifier'\n}\n\nfunction isJsxElement(node: SourceNode): node is JSXElementNode {\n return node.type === 'JSXElement'\n}\n\nfunction isJsxAttribute(node: SourceNode): node is JSXAttributeNode {\n return node.type === 'JSXAttribute'\n}\n\nfunction readImportedName(specifier: ImportSpecifierNode): string | undefined {\n const imported = specifier.imported\n if (imported.type === 'Identifier') return imported.name\n if (imported.type === 'StringLiteral') return imported.value\n return undefined\n}\n\n/**\n * Inject the catalog import statement at the top of the module.\n */\nexport function injectCatalogImport(code: string, strategy: 'dynamic' | 'static', hashes: Set<string>, hashFn?: HashFunction): string {\n if (strategy === 'dynamic') {\n return `import { __catalog } from 'virtual:fluenti/runtime';\\n${code}`\n }\n\n // Static: import named exports directly\n const hash = hashFn ?? defaultHashMessage\n const imports = [...hashes].map((id) => `_${hash(id)}`).join(', ')\n return `import { ${imports} } from 'virtual:fluenti/messages';\\n${code}`\n}\n","/**\n * Virtual module resolution for code-splitting mode.\n *\n * Provides:\n * - virtual:fluenti/runtime → reactive catalog + switchLocale + preloadLocale\n * - virtual:fluenti/messages → re-export from static locale (for static strategy)\n */\n\nimport { resolve } from 'node:path'\nimport { existsSync } from 'node:fs'\nimport { validateLocale } from '@fluenti/core'\nimport type { RuntimeGenerator, RuntimeGeneratorOptions } from './types'\n\n/**\n * Escapes a string value for safe embedding in generated JavaScript code.\n * Returns a JSON-encoded string (with double quotes), preventing injection\n * of quotes, backticks, template interpolation, and other special characters.\n */\nfunction safeStringLiteral(value: string): string {\n return JSON.stringify(value)\n}\n\n/**\n * Validates that a catalog directory path does not contain characters\n * that could enable code injection in generated template literals.\n */\nfunction validateCatalogDir(catalogDir: string): void {\n if (catalogDir.includes('`') || catalogDir.includes('$')) {\n throw new Error(\n `[fluenti] vite-plugin: catalogDir must not contain backticks or $ characters, got ${JSON.stringify(catalogDir)}`,\n )\n }\n}\n\nconst VIRTUAL_RUNTIME = 'virtual:fluenti/runtime'\nconst VIRTUAL_MESSAGES = 'virtual:fluenti/messages'\nconst RESOLVED_RUNTIME = '\\0virtual:fluenti/runtime'\nconst RESOLVED_MESSAGES = '\\0virtual:fluenti/messages'\n\nexport interface VirtualModuleOptions {\n rootDir: string\n catalogDir: string\n catalogExtension: string\n locales: string[]\n sourceLocale: string\n defaultBuildLocale: string\n framework: string\n runtimeGenerator?: RuntimeGenerator | undefined\n}\n\nexport function resolveVirtualSplitId(id: string): string | undefined {\n if (id === VIRTUAL_RUNTIME) return RESOLVED_RUNTIME\n if (id === VIRTUAL_MESSAGES) return RESOLVED_MESSAGES\n return undefined\n}\n\nexport function loadVirtualSplitModule(\n id: string,\n options: VirtualModuleOptions,\n): string | undefined {\n if (id === RESOLVED_RUNTIME) {\n return generateRuntimeModule(options)\n }\n if (id === RESOLVED_MESSAGES) {\n return generateStaticMessagesModule(options)\n }\n return undefined\n}\n\nfunction generateRuntimeModule(options: VirtualModuleOptions): string {\n const { locales, runtimeGenerator, catalogDir } = options\n validateCatalogDir(catalogDir)\n for (const locale of locales) {\n validateLocale(locale, 'vite-plugin')\n }\n\n if (!runtimeGenerator) {\n throw new Error('[fluenti] vite-plugin: runtimeGenerator is required. Use a framework-specific plugin (e.g. @fluenti/vue/vite-plugin).')\n }\n\n return runtimeGenerator.generateRuntime(toRuntimeGeneratorOptions(options))\n}\n\nfunction generateStaticMessagesModule(options: VirtualModuleOptions): string {\n const { rootDir, catalogDir, catalogExtension, defaultBuildLocale, sourceLocale } = options\n const defaultLocale = defaultBuildLocale || sourceLocale\n validateLocale(defaultLocale, 'vite-plugin')\n validateCatalogDir(catalogDir)\n const absoluteCatalogDir = resolve(rootDir, catalogDir)\n const catalogFile = resolve(absoluteCatalogDir, defaultLocale + catalogExtension)\n\n if (!existsSync(catalogFile)) {\n console.warn(\n `[fluenti] Compiled catalog for locale \"${defaultLocale}\" not found at ${catalogFile}. Run \"fluenti compile\" first.`,\n )\n }\n\n return `export * from ${safeStringLiteral(catalogFile)}\\n`\n}\n\nfunction toRuntimeGeneratorOptions(options: VirtualModuleOptions): RuntimeGeneratorOptions {\n const { rootDir, catalogDir, catalogExtension, locales, sourceLocale, defaultBuildLocale } = options\n return { rootDir, catalogDir, catalogExtension, locales, sourceLocale, defaultBuildLocale }\n}\n","import type { Plugin } from 'vite'\nimport { createFilter } from 'vite'\nimport type { FluentiCoreOptions, RuntimeGenerator } from './types'\nimport type { FluentiBuildConfig } from '@fluenti/core/compiler'\nimport { resolveLocaleCodes } from '@fluenti/core/compiler'\nimport { DEFAULT_FLUENTI_CONFIG, loadConfigSync } from '@fluenti/core/config'\nimport { setResolvedMode, isBuildMode, getPluginEnvironment } from './mode-detect'\nimport { createDebouncedRunner, runExtractCompile } from './dev-runner'\nimport { transformForDynamicSplit, transformForStaticSplit, injectCatalogImport } from './build-transform'\nimport { resolveVirtualSplitId, loadVirtualSplitModule } from './virtual-modules'\nimport { createTransformPipeline, hasScopeTransformCandidate } from '@fluenti/core/transform'\nexport type { FluentiPluginOptions, FluentiCoreOptions, RuntimeGenerator, RuntimeGeneratorOptions, IdGenerator } from './types'\nexport { createRuntimeGenerator } from './runtime-template'\nexport type { RuntimePrimitives } from './runtime-template'\nexport { resolveVirtualSplitId, loadVirtualSplitModule } from './virtual-modules'\nexport { setResolvedMode, isBuildMode, getPluginEnvironment } from './mode-detect'\n\nconst VIRTUAL_PREFIX = 'virtual:fluenti/messages/'\nconst RESOLVED_PREFIX = '\\0virtual:fluenti/messages/'\n\n/**\n * Resolve a config option (string path, inline object, or undefined) into a full FluentiBuildConfig.\n */\nfunction resolvePluginConfig(configOption?: string | FluentiBuildConfig, cwd?: string): FluentiBuildConfig {\n if (typeof configOption === 'object') {\n // Inline config — merge with defaults\n return { ...DEFAULT_FLUENTI_CONFIG, ...configOption }\n }\n // string → specified path; undefined → auto-discover\n return loadConfigSync(\n typeof configOption === 'string' ? configOption : undefined,\n cwd,\n )\n}\n\n// ─── Public factory for framework packages ─────────────────────────────────\n\n/**\n * Create the Fluenti plugin pipeline.\n * Framework packages call this with their framework-specific plugins and runtime generator.\n */\nexport function createFluentiPlugins(\n options: FluentiCoreOptions,\n frameworkPlugins: Plugin[],\n runtimeGenerator?: RuntimeGenerator,\n): Plugin[] {\n let fluentiConfig: FluentiBuildConfig | undefined\n let rootDir = process.cwd()\n\n function getConfig(cwd?: string): FluentiBuildConfig {\n const effectiveCwd = cwd ?? rootDir\n if (!fluentiConfig) {\n fluentiConfig = resolvePluginConfig(options.config, effectiveCwd)\n }\n return fluentiConfig\n }\n\n const framework = options.framework\n\n function getResolvedSettings(cwd?: string) {\n const config = getConfig(cwd)\n const catalogDir = config.compileOutDir.replace(/^\\.\\//, '')\n const catalogExtension = config.catalogExtension ?? '.js'\n const rawSplitting = config.splitting ?? false\n if (rawSplitting && rawSplitting !== 'dynamic' && rawSplitting !== 'static') {\n console.warn(`[fluenti] Invalid splitting value \"${rawSplitting}\". Expected 'dynamic', 'static', or false. Falling back to 'dynamic'.`)\n }\n const splitting = rawSplitting === 'static' ? 'static' as const : rawSplitting ? 'dynamic' as const : false as const\n const sourceLocale = config.sourceLocale\n const localeCodes = resolveLocaleCodes(config.locales)\n const defaultBuildLocale = config.defaultBuildLocale ?? sourceLocale\n return {\n config,\n catalogDir,\n catalogExtension,\n splitting,\n sourceLocale,\n localeCodes,\n defaultBuildLocale,\n }\n }\n\n const virtualPlugin: Plugin = {\n name: 'fluenti:virtual',\n configResolved(config) {\n rootDir = config.root\n fluentiConfig = resolvePluginConfig(options.config, rootDir)\n setResolvedMode(config.command)\n },\n resolveId(id) {\n if (id.startsWith(VIRTUAL_PREFIX)) {\n return '\\0' + id\n }\n const { splitting } = getResolvedSettings()\n if (splitting) {\n const resolved = resolveVirtualSplitId(id)\n if (resolved) return resolved\n }\n return undefined\n },\n load(id) {\n const {\n catalogDir,\n catalogExtension,\n splitting,\n localeCodes,\n sourceLocale,\n defaultBuildLocale,\n } = getResolvedSettings()\n if (id.startsWith(RESOLVED_PREFIX)) {\n const locale = id.slice(RESOLVED_PREFIX.length)\n if (!localeCodes.includes(locale)) {\n return undefined\n }\n const catalogPath = `${catalogDir}/${locale}${catalogExtension}`\n return `export { default } from '${catalogPath}'`\n }\n if (splitting) {\n const result = loadVirtualSplitModule(id, {\n rootDir,\n catalogDir,\n catalogExtension,\n locales: localeCodes,\n sourceLocale,\n defaultBuildLocale,\n framework,\n runtimeGenerator,\n })\n if (result) return result\n }\n return undefined\n },\n }\n\n const pipeline = createTransformPipeline({ framework })\n\n const scriptTransformPlugin: Plugin = {\n name: 'fluenti:script-transform',\n enforce: 'pre',\n transform(code, id) {\n if (id.includes('node_modules')) return undefined\n if (!id.match(/\\.(vue|tsx|jsx|ts|js)(\\?|$)/)) return undefined\n if (id.includes('.vue') && !id.includes('type=script')) return undefined\n\n // Vue .vue files need allowTopLevelImportedT for top-level `import { t }`\n const isVueSfc = framework === 'vue' && id.includes('.vue')\n const componentModuleImport = `@fluenti/${framework}/components`\n\n let result = code\n let changed = false\n\n // ── <Trans> compile-time optimization (JSX/TSX only) ──────────────\n if (id.match(/\\.[jt]sx(\\?|$)/) && /<Trans[\\s>]/.test(result)) {\n const transResult = pipeline.transformTrans(result)\n if (transResult.transformed) {\n result = transResult.code\n changed = true\n }\n }\n\n if (\n id.match(/\\.[jt]sx(\\?|$)/)\n && (framework === 'react' || framework === 'solid')\n && /<(Plural|Select)[\\s/>]/.test(result)\n ) {\n const componentResult = pipeline.transformPluralSelect(result, componentModuleImport)\n if (componentResult.transformed) {\n result = componentResult.code\n changed = true\n }\n }\n\n // ── t`` / t() scope-aware transform ────────────────────────────────\n if (hasScopeTransformCandidate(result)) {\n const scoped = pipeline.transformScope(result, {\n componentModuleImport,\n ...(isVueSfc ? { allowTopLevelImportedT: true } : {}),\n })\n if (scoped.transformed) {\n return { code: scoped.code, map: null }\n }\n }\n\n return changed ? { code: result, map: null } : undefined\n },\n }\n\n const buildSplitPlugin: Plugin = {\n name: 'fluenti:build-split',\n transform(code, id) {\n const { splitting, config } = getResolvedSettings()\n if (!splitting) return undefined\n if (!isBuildMode(getPluginEnvironment(this))) return undefined\n if (id.includes('node_modules')) return undefined\n if (!id.match(/\\.(vue|tsx|jsx|ts|js)(\\?|$)/)) return undefined\n\n const strategy = splitting === 'static' ? 'static' : 'dynamic'\n const transformOptions = config.idGenerator ? { hashFn: config.idGenerator } : undefined\n const transformed = strategy === 'static'\n ? transformForStaticSplit(code, transformOptions)\n : transformForDynamicSplit(code, transformOptions)\n\n if (!transformed.needsCatalogImport) return undefined\n\n const finalCode = injectCatalogImport(\n transformed.code,\n strategy,\n transformed.usedHashes,\n config.idGenerator,\n )\n return { code: finalCode, map: null }\n },\n }\n\n const buildCompilePlugin: Plugin = {\n name: 'fluenti:build-compile',\n async buildStart() {\n const { config } = getResolvedSettings()\n if (!isBuildMode(getPluginEnvironment(this))) return\n const buildAutoCompile = config.buildAutoCompile ?? true\n if (!buildAutoCompile) return\n if (config.onBeforeCompile) {\n const result = await config.onBeforeCompile()\n if (result === false) return\n }\n await runExtractCompile({ cwd: rootDir, throwOnError: true, compileOnly: true })\n if (config.onAfterCompile) {\n await config.onAfterCompile()\n }\n },\n }\n\n const devPlugin: Plugin = {\n name: 'fluenti:dev',\n configureServer(server) {\n const { config, catalogDir } = getResolvedSettings(server.config.root)\n const devAutoCompile = config.devAutoCompile ?? true\n if (!devAutoCompile) return\n\n const includePatterns = config.include ?? ['src/**/*.{vue,tsx,jsx,ts,js}']\n const excludePatterns = config.exclude ?? []\n\n const filter = createFilter(includePatterns, [\n ...excludePatterns,\n '**/node_modules/**',\n `**/${catalogDir}/**`,\n ])\n\n const runnerOptions: Parameters<typeof createDebouncedRunner>[0] = {\n cwd: server.config.root,\n onSuccess: () => {\n // Existing hotUpdate will pick up catalog changes\n },\n }\n if (config.parallelCompile) runnerOptions.parallelCompile = true\n if (config.onBeforeCompile) runnerOptions.onBeforeCompile = config.onBeforeCompile\n if (config.onAfterCompile) runnerOptions.onAfterCompile = config.onAfterCompile\n const debouncedRun = createDebouncedRunner(runnerOptions, config.devAutoCompileDelay ?? 500)\n\n debouncedRun()\n\n server.watcher.on('change', (file) => {\n if (filter(file)) {\n debouncedRun()\n }\n })\n },\n hotUpdate({ file }) {\n const { catalogDir } = getResolvedSettings()\n if (file.includes(catalogDir)) {\n const modules = [...this.environment.moduleGraph.urlToModuleMap.entries()]\n .filter(([url]) => url.includes('virtual:fluenti'))\n .map(([, mod]) => mod)\n\n if (modules.length > 0) {\n return modules\n }\n }\n return undefined\n },\n }\n\n // Plugin order matters:\n // 1. virtualPlugin — resolves virtual:fluenti/* module IDs (must be first)\n // 2. frameworkPlugins — framework-specific template transforms (e.g., Vue v-t directive)\n // must run after virtual resolution but before script transforms\n // 3. scriptTransformPlugin — t()/t`` scope transforms + <Trans> optimization (enforce: 'pre')\n // 4. buildCompilePlugin — triggers extract+compile before the build starts\n // 5. buildSplitPlugin — rewrites t() calls to catalog refs (dynamic/static)\n // 6. devPlugin — file watcher + HMR for dev mode (must be last)\n return [virtualPlugin, ...frameworkPlugins, scriptTransformPlugin, buildCompilePlugin, buildSplitPlugin, devPlugin]\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sfc-transform.cjs","names":[],"sources":["../src/sfc-transform.ts"],"sourcesContent":["// ─── SFC pre-transform fallback for v-t ──────────────────────────────────────\n// Used when the nodeTransform can't be injected into @vitejs/plugin-vue\n// Uses @vue/compiler-sfc AST instead of regex for robust template parsing.\n\nimport { hashMessage } from '@fluenti/core/compiler'\nimport { parse as parseSFC } from '@vue/compiler-sfc'\n\n// Vue compiler AST node types\nconst NT_ELEMENT = 1\nconst NT_TEXT = 2\nconst NT_INTERPOLATION = 5\nconst NT_ATTRIBUTE = 6\nconst NT_DIRECTIVE = 7\n\ninterface ASTNode {\n type: number\n tag?: string\n props?: ASTNode[]\n children?: ASTNode[]\n content?: string | ASTNode\n name?: string\n arg?: ASTNode\n exp?: ASTNode\n modifiers?: Array<string | ASTNode>\n value?: ASTNode\n isSelfClosing?: boolean\n loc: {\n source: string\n start: { offset: number; line: number; column: number }\n end: { offset: number; line: number; column: number }\n }\n}\n\n// ─── Preserved utility functions ──────────────────────────────────────────────\n\nfunction escapeSingleQuotedString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")\n}\n\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface RichChild {\n tag: string\n rawAttrs: string\n selfClosing: boolean\n innerContent: string\n}\n\ninterface ExtractedRich {\n message: string\n elements: RichChild[]\n hasElements: boolean\n}\n\ninterface StaticSfcAttrValue {\n kind: 'missing' | 'static' | 'dynamic'\n value?: string\n}\n\ninterface ReplaceOp {\n start: number\n end: number\n replacement: string\n}\n\n// ─── Output helpers (no parsing, kept as-is) ──────────────────────────────────\n\nfunction serializeElements(elements: readonly RichChild[]): string {\n const entries = elements.map(el => {\n // Escape for JS string + HTML attribute context (v-html=\"...\"):\n // &quot; is decoded by HTML parser before JS evaluates the expression\n const rawAttrsStr = escapeSingleQuotedString(el.rawAttrs).replace(/\"/g, '&quot;')\n return `{ tag: '${escapeSingleQuotedString(el.tag)}', rawAttrs: '${rawAttrsStr}' }`\n })\n return `[${entries.join(', ')}]`\n}\n\nfunction buildDescriptorExpression(\n message: string,\n options?: {\n id?: string | undefined\n context?: string | undefined\n },\n): string {\n const id = options?.id ?? hashMessage(message, options?.context)\n return `{ id: '${escapeSingleQuotedString(id)}', message: '${escapeSingleQuotedString(message)}' }`\n}\n\n// ─── AST helper functions ─────────────────────────────────────────────────────\n\nfunction getModifierContent(mod: string | ASTNode): string {\n return typeof mod === 'string' ? mod : (mod.content as string) ?? ''\n}\n\nfunction readAttr(props: ASTNode[], name: string): StaticSfcAttrValue {\n for (const prop of props) {\n if (prop.type === NT_DIRECTIVE && prop.name === 'bind') {\n const argContent = typeof prop.arg?.content === 'string' ? prop.arg.content : undefined\n if (argContent === name) {\n return { kind: 'dynamic' }\n }\n }\n if (prop.type === NT_ATTRIBUTE && prop.name === name) {\n const value = typeof prop.value?.content === 'string' ? prop.value.content : ''\n return { kind: 'static', value }\n }\n }\n return { kind: 'missing' }\n}\n\nfunction getBindingExpr(props: ASTNode[], name: string): string | undefined {\n for (const prop of props) {\n if (prop.type === NT_DIRECTIVE && prop.name === 'bind') {\n const argContent = typeof prop.arg?.content === 'string' ? prop.arg.content : undefined\n if (argContent === name) {\n return typeof prop.exp?.content === 'string' ? prop.exp.content : undefined\n }\n }\n }\n return undefined\n}\n\n/**\n * Extract rich children from AST child nodes.\n * Converts ElementNodes to indexed placeholders, TextNodes to literal text,\n * and InterpolationNodes to their raw source ({{ expr }}).\n */\nfunction extractRichFromAST(children: ASTNode[]): ExtractedRich {\n const elements: RichChild[] = []\n let message = ''\n\n for (const child of children) {\n if (child.type === NT_TEXT) {\n message += typeof child.content === 'string' ? child.content : ''\n } else if (child.type === NT_INTERPOLATION) {\n message += child.loc.source\n } else if (child.type === NT_ELEMENT && child.tag) {\n const idx = elements.length\n const rawAttrs = (child.props ?? [])\n .map(p => p.loc.source)\n .join(' ')\n const isSelfClosing = child.isSelfClosing ?? false\n\n if (isSelfClosing || !child.children?.length) {\n elements.push({ tag: child.tag, rawAttrs, selfClosing: true, innerContent: '' })\n message += `<${idx}/>`\n } else {\n // Collect inner content from the original source between children range\n const firstChild = child.children[0]!\n const lastChild = child.children[child.children.length - 1]!\n const innerContent = child.loc.source.slice(\n firstChild.loc.start.offset - child.loc.start.offset,\n lastChild.loc.end.offset - child.loc.start.offset,\n )\n elements.push({ tag: child.tag, rawAttrs, selfClosing: false, innerContent })\n message += `<${idx}>${innerContent}</${idx}>`\n }\n }\n }\n\n return { message, elements, hasElements: elements.length > 0 }\n}\n\n/**\n * Extract {{ expr }} interpolations from AST children for v-t content.\n * Returns message with ICU {var} placeholders and variable entries.\n */\nfunction extractVarsFromAST(children: ASTNode[]): { message: string; vars: string[] } {\n const vars: string[] = []\n let message = ''\n\n for (const child of children) {\n if (child.type === NT_TEXT) {\n message += typeof child.content === 'string' ? child.content : ''\n } else if (child.type === NT_INTERPOLATION) {\n const expr = typeof child.content === 'object' && child.content\n ? typeof child.content.content === 'string' ? child.content.content : ''\n : ''\n const trimmed = expr.trim()\n\n let varName: string\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(trimmed)) {\n varName = trimmed\n } else if (/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(trimmed) && !trimmed.endsWith('.')) {\n const parts = trimmed.split('.')\n varName = parts[parts.length - 1]!\n } else {\n varName = String(vars.length)\n }\n vars.push(`${varName}: ${trimmed}`)\n message += `{${varName}}`\n }\n }\n\n return { message, vars }\n}\n\n/**\n * Build the list of remaining props for an element, excluding specific prop nodes.\n * Returns their raw source strings joined with spaces.\n */\nfunction buildCleanAttrs(props: ASTNode[], exclude: Set<ASTNode>): string {\n return props\n .filter(p => !exclude.has(p))\n .map(p => p.loc.source)\n .join(' ')\n}\n\n// ─── Transform collectors ─────────────────────────────────────────────────────\n\nconst TRANS_ONLY_PROPS = new Set(['tag', 'id', 'context', 'comment'])\n\nfunction collectVtAttrOps(node: ASTNode, ops: ReplaceOp[]): void {\n const props = node.props ?? []\n const vtDir = props.find(\n p => p.type === NT_DIRECTIVE && p.name === 't' && (p.modifiers ?? []).length > 0,\n )\n if (!vtDir) return\n\n const modifiers = (vtDir.modifiers ?? []).map(getModifierContent)\n // Skip v-t.plural — handled by collectVtContentOps\n if (modifiers.length === 1 && modifiers[0] === 'plural') return\n\n const attrName = modifiers.find(m => m !== 'plural')\n if (!attrName) return\n\n // Find the corresponding static attribute\n const staticAttr = props.find(\n p => p.type === NT_ATTRIBUTE && p.name === attrName,\n )\n if (!staticAttr) return\n const attrValue = typeof staticAttr.value?.content === 'string' ? staticAttr.value.content : ''\n\n const descriptor = buildDescriptorExpression(attrValue)\n\n // Build new opening tag: keep all props except v-t.X and the static attr, add :attrName=\"$t(...)\"\n const exclude = new Set([vtDir, staticAttr])\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const newAttrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n // Replace the opening tag portion of the element\n const tag = node.tag!\n if (node.isSelfClosing) {\n const replacement = `<${tag}${newAttrsPart} :${attrName}=\"$t(${descriptor})\" />`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n } else {\n // Find the end of the opening tag: start of first child or the inner content\n const children = node.children ?? []\n const openTagEnd = children.length > 0\n ? children[0]!.loc.start.offset\n : node.loc.source.indexOf('>') + node.loc.start.offset + 1\n const newOpenTag = `<${tag}${newAttrsPart} :${attrName}=\"$t(${descriptor})\">`\n ops.push({ start: node.loc.start.offset, end: openTagEnd, replacement: newOpenTag })\n }\n}\n\nfunction collectVtContentOps(node: ASTNode, ops: ReplaceOp[]): void {\n const props = node.props ?? []\n const vtDir = props.find(p => p.type === NT_DIRECTIVE && p.name === 't')\n if (!vtDir) return\n\n // Skip if this is a pure attribute binding (handled by collectVtAttrOps)\n const modifiers = (vtDir.modifiers ?? []).map(getModifierContent)\n const nonPluralMods = modifiers.filter(m => m !== 'plural')\n // If there's a non-plural modifier that corresponds to an attribute name, skip (attribute binding)\n if (nonPluralMods.length > 0) {\n const attrName = nonPluralMods[0]!\n const hasStaticAttr = props.some(p => p.type === NT_ATTRIBUTE && p.name === attrName)\n if (hasStaticAttr) return\n }\n\n const isPlural = modifiers.includes('plural')\n const bindExpr = typeof vtDir.exp?.content === 'string' ? vtDir.exp.content : undefined\n\n // Build explicit ID from arg + non-reserved modifiers\n const RESERVED_MODIFIERS = new Set(['plural'])\n const idSegments = modifiers.filter(m => !RESERVED_MODIFIERS.has(m))\n const argContent = typeof vtDir.arg?.content === 'string' ? vtDir.arg.content : undefined\n const explicitId = argContent ? [argContent, ...idSegments].join('.') : undefined\n\n const tag = node.tag!\n const children = node.children ?? []\n\n // Build clean attrs: remove v-t directive\n const exclude = new Set([vtDir])\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const attrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n if (isPlural && bindExpr) {\n // Collect text content from children\n const textContent = children\n .filter(c => c.type === NT_TEXT)\n .map(c => (typeof c.content === 'string' ? c.content : '').trim())\n .join('')\n const forms = textContent.split('|').map(s => s.trim())\n const categories = forms.length === 2\n ? ['one', 'other']\n : ['one', 'other', 'zero', 'few', 'many'].slice(0, forms.length)\n const icuParts = categories.map((cat, i) => `${cat} {${forms[i] ?? ''}}`)\n const icuMessage = `{${bindExpr}, plural, ${icuParts.join(' ')}}`\n const descriptor = buildDescriptorExpression(icuMessage, { id: explicitId })\n const replacement = `<${tag}${attrsPart}>{{ $t(${descriptor}, { ${bindExpr} }) }}</${tag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Check for rich text (child elements)\n const extracted = extractRichFromAST(children)\n if (extracted.hasElements) {\n const message = extracted.message.trim()\n const descriptor = buildDescriptorExpression(message, { id: explicitId })\n const elementsLiteral = serializeElements(extracted.elements)\n const replacement = `<${tag}${attrsPart} v-html=\"$vtRich(${descriptor}, ${elementsLiteral})\"></${tag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Plain text, possibly with interpolation\n const { message, vars } = extractVarsFromAST(children)\n const trimmedMessage = message.trim()\n\n // Skip if there's no message content and no explicit ID — matches guard in collectTransOps\n if (!trimmedMessage && !explicitId) return\n\n const descriptor = buildDescriptorExpression(trimmedMessage, { id: explicitId })\n\n let replacement: string\n if (vars.length > 0) {\n replacement = `<${tag}${attrsPart}>{{ $t(${descriptor}, { ${vars.join(', ')} }) }}</${tag}>`\n } else {\n replacement = `<${tag}${attrsPart}>{{ $t(${descriptor}) }}</${tag}>`\n }\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n}\n\nfunction collectTransOps(node: ASTNode, ops: ReplaceOp[]): void {\n if (node.tag !== 'Trans') return\n const props = node.props ?? []\n const children = node.children ?? []\n\n // Skip if empty content\n if (children.length === 0) return\n // Skip all-whitespace content\n const hasContent = children.some(c => {\n if (c.type === NT_TEXT) return (typeof c.content === 'string' ? c.content : '').trim().length > 0\n return true\n })\n if (!hasContent) return\n\n // Skip old API: <Trans message=\"...\">\n if (props.some(p => p.type === NT_ATTRIBUTE && p.name === 'message')) return\n\n const explicitId = readAttr(props, 'id')\n if (explicitId.kind === 'dynamic') return\n\n const context = readAttr(props, 'context')\n if (!explicitId.value && context.kind === 'dynamic') return\n\n // Extract tag prop (default: 'span')\n const tagAttr = readAttr(props, 'tag')\n const wrapperTag = tagAttr.value ?? 'span'\n\n // Build clean attrs: remove Trans-specific props\n const exclude = new Set<ASTNode>()\n for (const p of props) {\n if (p.type === NT_ATTRIBUTE && TRANS_ONLY_PROPS.has(p.name as string)) {\n exclude.add(p)\n }\n if (p.type === NT_DIRECTIVE && p.name === 'bind') {\n const argName = typeof p.arg?.content === 'string' ? p.arg.content : undefined\n if (argName && TRANS_ONLY_PROPS.has(argName)) {\n exclude.add(p)\n }\n }\n }\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const cleanAttrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n // Check for rich text\n const extracted = extractRichFromAST(children)\n if (extracted.hasElements) {\n const message = extracted.message.trim()\n const descriptor = buildDescriptorExpression(message, {\n id: explicitId.value,\n context: context.value,\n })\n const elementsLiteral = serializeElements(extracted.elements)\n const replacement = `<${wrapperTag}${cleanAttrsPart} v-html=\"$vtRich(${descriptor}, ${elementsLiteral})\"></${wrapperTag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Plain text\n const rawContent = children\n .map(c => (c.type === NT_TEXT && typeof c.content === 'string') ? c.content : '')\n .join('')\n .trim()\n const descriptor = buildDescriptorExpression(rawContent, {\n id: explicitId.value,\n context: context.value,\n })\n const replacement = `<${wrapperTag}${cleanAttrsPart}>{{ $t(${descriptor}) }}</${wrapperTag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n}\n\nconst PLURAL_CATS = ['zero', 'one', 'two', 'few', 'many', 'other'] as const\n\nfunction collectPluralOps(node: ASTNode, ops: ReplaceOp[]): void {\n if (node.tag !== 'Plural') return\n const props = node.props ?? []\n\n const explicitId = readAttr(props, 'id')\n const context = readAttr(props, 'context')\n if (explicitId.kind === 'dynamic') return\n if (!explicitId.value && context.kind === 'dynamic') return\n\n const valueExpr = getBindingExpr(props, 'value')\n if (!valueExpr) return\n\n const tagAttr = readAttr(props, 'tag')\n const wrapperTag = tagAttr.value ?? 'span'\n\n // Check for template slot children\n const children = node.children ?? []\n const slots: Array<{ cat: string; children: ASTNode[] }> = []\n for (const child of children) {\n if (child.type === NT_ELEMENT && child.tag === 'template') {\n const slotDir = (child.props ?? []).find(\n p => p.type === NT_DIRECTIVE && p.name === 'slot',\n )\n if (slotDir) {\n const slotName = typeof slotDir.arg?.content === 'string' ? slotDir.arg.content : undefined\n if (slotName) {\n slots.push({ cat: slotName, children: child.children ?? [] })\n }\n }\n }\n }\n\n if (slots.length > 0) {\n // Slot mode\n const allElements: RichChild[] = []\n const icuParts: string[] = []\n\n for (const cat of PLURAL_CATS) {\n const slot = slots.find(s => s.cat === cat)\n if (!slot) continue\n\n const extracted = extractRichFromAST(slot.children)\n let branchMessage: string\n\n if (extracted.hasElements) {\n const baseIndex = allElements.length\n branchMessage = extracted.message.replace(/<(\\d+)(\\/?)>/g, (_m, idxStr: string, slash: string) => {\n return `<${baseIndex + Number(idxStr)}${slash}>`\n }).replace(/<\\/(\\d+)>/g, (_m, idxStr: string) => {\n return `</${baseIndex + Number(idxStr)}>`\n })\n allElements.push(...extracted.elements)\n } else {\n // Plain text from slot children\n branchMessage = slot.children\n .map(c => (c.type === NT_TEXT && typeof c.content === 'string') ? c.content : '')\n .join('')\n .trim()\n }\n\n const icuKey = cat === 'zero' ? '=0' : cat\n icuParts.push(`${icuKey} {${branchMessage}}`)\n }\n\n if (icuParts.length === 0) return\n\n const icuMessage = `{count, plural, ${icuParts.join(' ')}}`\n const descriptor = buildDescriptorExpression(icuMessage, {\n id: explicitId.value,\n context: context.value,\n })\n\n // Build clean attrs\n const pluralOnlyProps = new Set([...TRANS_ONLY_PROPS, 'tag'])\n const exclude = new Set<ASTNode>()\n for (const p of props) {\n if (p.type === NT_ATTRIBUTE && pluralOnlyProps.has(p.name as string)) {\n exclude.add(p)\n }\n if (p.type === NT_DIRECTIVE && p.name === 'bind') {\n const argName = typeof p.arg?.content === 'string' ? p.arg.content : undefined\n if (argName === 'value' || (argName && pluralOnlyProps.has(argName))) {\n exclude.add(p)\n }\n }\n }\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const attrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n let replacement: string\n if (allElements.length > 0) {\n const elementsLiteral = serializeElements(allElements)\n replacement = `<${wrapperTag}${attrsPart} v-html=\"$vtRich(${descriptor}, ${elementsLiteral}, { count: ${valueExpr} })\"></${wrapperTag}>`\n } else {\n replacement = `<${wrapperTag}${attrsPart} v-text=\"$t(${descriptor}, { count: ${valueExpr} })\"></${wrapperTag}>`\n }\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Prop mode: read zero/one/two/few/many/other static props\n const icuParts: string[] = []\n const catPropsToExclude = new Set<ASTNode>()\n\n for (const cat of PLURAL_CATS) {\n const catProp = props.find(p => p.type === NT_ATTRIBUTE && p.name === cat)\n if (catProp) {\n const value = typeof catProp.value?.content === 'string' ? catProp.value.content : ''\n const icuKey = cat === 'zero' ? '=0' : cat\n icuParts.push(`${icuKey} {${value}}`)\n catPropsToExclude.add(catProp)\n }\n }\n\n if (icuParts.length === 0) return\n\n const icuMessage = `{count, plural, ${icuParts.join(' ')}}`\n const descriptor = buildDescriptorExpression(icuMessage, {\n id: explicitId.value,\n context: context.value,\n })\n\n // Build clean attrs: remove :value, tag, id, context, comment, category props\n const exclude = new Set<ASTNode>(catPropsToExclude)\n for (const p of props) {\n if (p.type === NT_ATTRIBUTE && (p.name === 'tag' || TRANS_ONLY_PROPS.has(p.name as string))) {\n exclude.add(p)\n }\n if (p.type === NT_DIRECTIVE && p.name === 'bind') {\n const argName = typeof p.arg?.content === 'string' ? p.arg.content : undefined\n if (argName === 'value' || (argName && TRANS_ONLY_PROPS.has(argName))) {\n exclude.add(p)\n }\n }\n }\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const attrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n const replacement = `<${wrapperTag}${attrsPart} v-text=\"$t(${descriptor}, { count: ${valueExpr} })\"></${wrapperTag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n}\n\n// ─── AST traversal ────────────────────────────────────────────────────────────\n\nfunction collectOps(root: ASTNode): ReplaceOp[] {\n const ops: ReplaceOp[] = []\n\n function walk(node: ASTNode): void {\n if (node.type === NT_ELEMENT) {\n if (node.tag === 'Trans') {\n collectTransOps(node, ops)\n return // Don't recurse into transformed nodes\n }\n if (node.tag === 'Plural') {\n collectPluralOps(node, ops)\n return\n }\n\n // v-t directive handling\n const hasVt = (node.props ?? []).some(p => p.type === NT_DIRECTIVE && p.name === 't')\n if (hasVt) {\n collectVtAttrOps(node, ops)\n collectVtContentOps(node, ops)\n return\n }\n }\n\n // Recurse into children\n for (const child of node.children ?? []) {\n walk(child)\n }\n }\n\n walk(root)\n return ops\n}\n\n// ─── Entry point ──────────────────────────────────────────────────────────────\n\nexport function transformVtDirectives(sfc: string): string {\n // Quick bail: check if there's anything to transform\n if (!/<template[\\s>]/.test(sfc)) return sfc\n if (sfc.lastIndexOf('</template>') < 0) return sfc\n\n const hasVt = /\\bv-t\\b/.test(sfc)\n const hasTrans = /<Trans[\\s>]/.test(sfc)\n const hasPlural = /<Plural[\\s/>]/.test(sfc)\n if (!hasVt && !hasTrans && !hasPlural) return sfc\n\n const { descriptor } = parseSFC(sfc, { pad: false })\n if (!descriptor.template?.ast) return sfc\n\n const ops = collectOps(descriptor.template.ast as unknown as ASTNode)\n if (ops.length === 0) return sfc\n\n // Apply replacements from end to start to avoid offset drift\n ops.sort((a, b) => b.start - a.start)\n let result = sfc\n for (const op of ops) {\n result = result.slice(0, op.start) + op.replacement + result.slice(op.end)\n }\n return result\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sfc-transform.js","names":[],"sources":["../src/sfc-transform.ts"],"sourcesContent":["// ─── SFC pre-transform fallback for v-t ──────────────────────────────────────\n// Used when the nodeTransform can't be injected into @vitejs/plugin-vue\n// Uses @vue/compiler-sfc AST instead of regex for robust template parsing.\n\nimport { hashMessage } from '@fluenti/core/compiler'\nimport { parse as parseSFC } from '@vue/compiler-sfc'\n\n// Vue compiler AST node types\nconst NT_ELEMENT = 1\nconst NT_TEXT = 2\nconst NT_INTERPOLATION = 5\nconst NT_ATTRIBUTE = 6\nconst NT_DIRECTIVE = 7\n\ninterface ASTNode {\n type: number\n tag?: string\n props?: ASTNode[]\n children?: ASTNode[]\n content?: string | ASTNode\n name?: string\n arg?: ASTNode\n exp?: ASTNode\n modifiers?: Array<string | ASTNode>\n value?: ASTNode\n isSelfClosing?: boolean\n loc: {\n source: string\n start: { offset: number; line: number; column: number }\n end: { offset: number; line: number; column: number }\n }\n}\n\n// ─── Preserved utility functions ──────────────────────────────────────────────\n\nfunction escapeSingleQuotedString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")\n}\n\nexport function escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface RichChild {\n tag: string\n rawAttrs: string\n selfClosing: boolean\n innerContent: string\n}\n\ninterface ExtractedRich {\n message: string\n elements: RichChild[]\n hasElements: boolean\n}\n\ninterface StaticSfcAttrValue {\n kind: 'missing' | 'static' | 'dynamic'\n value?: string\n}\n\ninterface ReplaceOp {\n start: number\n end: number\n replacement: string\n}\n\n// ─── Output helpers (no parsing, kept as-is) ──────────────────────────────────\n\nfunction serializeElements(elements: readonly RichChild[]): string {\n const entries = elements.map(el => {\n // Escape for JS string + HTML attribute context (v-html=\"...\"):\n // &quot; is decoded by HTML parser before JS evaluates the expression\n const rawAttrsStr = escapeSingleQuotedString(el.rawAttrs).replace(/\"/g, '&quot;')\n return `{ tag: '${escapeSingleQuotedString(el.tag)}', rawAttrs: '${rawAttrsStr}' }`\n })\n return `[${entries.join(', ')}]`\n}\n\nfunction buildDescriptorExpression(\n message: string,\n options?: {\n id?: string | undefined\n context?: string | undefined\n },\n): string {\n const id = options?.id ?? hashMessage(message, options?.context)\n return `{ id: '${escapeSingleQuotedString(id)}', message: '${escapeSingleQuotedString(message)}' }`\n}\n\n// ─── AST helper functions ─────────────────────────────────────────────────────\n\nfunction getModifierContent(mod: string | ASTNode): string {\n return typeof mod === 'string' ? mod : (mod.content as string) ?? ''\n}\n\nfunction readAttr(props: ASTNode[], name: string): StaticSfcAttrValue {\n for (const prop of props) {\n if (prop.type === NT_DIRECTIVE && prop.name === 'bind') {\n const argContent = typeof prop.arg?.content === 'string' ? prop.arg.content : undefined\n if (argContent === name) {\n return { kind: 'dynamic' }\n }\n }\n if (prop.type === NT_ATTRIBUTE && prop.name === name) {\n const value = typeof prop.value?.content === 'string' ? prop.value.content : ''\n return { kind: 'static', value }\n }\n }\n return { kind: 'missing' }\n}\n\nfunction getBindingExpr(props: ASTNode[], name: string): string | undefined {\n for (const prop of props) {\n if (prop.type === NT_DIRECTIVE && prop.name === 'bind') {\n const argContent = typeof prop.arg?.content === 'string' ? prop.arg.content : undefined\n if (argContent === name) {\n return typeof prop.exp?.content === 'string' ? prop.exp.content : undefined\n }\n }\n }\n return undefined\n}\n\n/**\n * Extract rich children from AST child nodes.\n * Converts ElementNodes to indexed placeholders, TextNodes to literal text,\n * and InterpolationNodes to their raw source ({{ expr }}).\n */\nfunction extractRichFromAST(children: ASTNode[]): ExtractedRich {\n const elements: RichChild[] = []\n let message = ''\n\n for (const child of children) {\n if (child.type === NT_TEXT) {\n message += typeof child.content === 'string' ? child.content : ''\n } else if (child.type === NT_INTERPOLATION) {\n message += child.loc.source\n } else if (child.type === NT_ELEMENT && child.tag) {\n const idx = elements.length\n const rawAttrs = (child.props ?? [])\n .map(p => p.loc.source)\n .join(' ')\n const isSelfClosing = child.isSelfClosing ?? false\n\n if (isSelfClosing || !child.children?.length) {\n elements.push({ tag: child.tag, rawAttrs, selfClosing: true, innerContent: '' })\n message += `<${idx}/>`\n } else {\n // Collect inner content from the original source between children range\n const firstChild = child.children[0]!\n const lastChild = child.children[child.children.length - 1]!\n const innerContent = child.loc.source.slice(\n firstChild.loc.start.offset - child.loc.start.offset,\n lastChild.loc.end.offset - child.loc.start.offset,\n )\n elements.push({ tag: child.tag, rawAttrs, selfClosing: false, innerContent })\n message += `<${idx}>${innerContent}</${idx}>`\n }\n }\n }\n\n return { message, elements, hasElements: elements.length > 0 }\n}\n\n/**\n * Extract {{ expr }} interpolations from AST children for v-t content.\n * Returns message with ICU {var} placeholders and variable entries.\n */\nfunction extractVarsFromAST(children: ASTNode[]): { message: string; vars: string[] } {\n const vars: string[] = []\n let message = ''\n\n for (const child of children) {\n if (child.type === NT_TEXT) {\n message += typeof child.content === 'string' ? child.content : ''\n } else if (child.type === NT_INTERPOLATION) {\n const expr = typeof child.content === 'object' && child.content\n ? typeof child.content.content === 'string' ? child.content.content : ''\n : ''\n const trimmed = expr.trim()\n\n let varName: string\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(trimmed)) {\n varName = trimmed\n } else if (/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(trimmed) && !trimmed.endsWith('.')) {\n const parts = trimmed.split('.')\n varName = parts[parts.length - 1]!\n } else {\n varName = String(vars.length)\n }\n vars.push(`${varName}: ${trimmed}`)\n message += `{${varName}}`\n }\n }\n\n return { message, vars }\n}\n\n/**\n * Build the list of remaining props for an element, excluding specific prop nodes.\n * Returns their raw source strings joined with spaces.\n */\nfunction buildCleanAttrs(props: ASTNode[], exclude: Set<ASTNode>): string {\n return props\n .filter(p => !exclude.has(p))\n .map(p => p.loc.source)\n .join(' ')\n}\n\n// ─── Transform collectors ─────────────────────────────────────────────────────\n\nconst TRANS_ONLY_PROPS = new Set(['tag', 'id', 'context', 'comment'])\n\nfunction collectVtAttrOps(node: ASTNode, ops: ReplaceOp[]): void {\n const props = node.props ?? []\n const vtDir = props.find(\n p => p.type === NT_DIRECTIVE && p.name === 't' && (p.modifiers ?? []).length > 0,\n )\n if (!vtDir) return\n\n const modifiers = (vtDir.modifiers ?? []).map(getModifierContent)\n // Skip v-t.plural — handled by collectVtContentOps\n if (modifiers.length === 1 && modifiers[0] === 'plural') return\n\n const attrName = modifiers.find(m => m !== 'plural')\n if (!attrName) return\n\n // Find the corresponding static attribute\n const staticAttr = props.find(\n p => p.type === NT_ATTRIBUTE && p.name === attrName,\n )\n if (!staticAttr) return\n const attrValue = typeof staticAttr.value?.content === 'string' ? staticAttr.value.content : ''\n\n const descriptor = buildDescriptorExpression(attrValue)\n\n // Build new opening tag: keep all props except v-t.X and the static attr, add :attrName=\"$t(...)\"\n const exclude = new Set([vtDir, staticAttr])\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const newAttrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n // Replace the opening tag portion of the element\n const tag = node.tag!\n if (node.isSelfClosing) {\n const replacement = `<${tag}${newAttrsPart} :${attrName}=\"$t(${descriptor})\" />`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n } else {\n // Find the end of the opening tag: start of first child or the inner content\n const children = node.children ?? []\n const openTagEnd = children.length > 0\n ? children[0]!.loc.start.offset\n : node.loc.source.indexOf('>') + node.loc.start.offset + 1\n const newOpenTag = `<${tag}${newAttrsPart} :${attrName}=\"$t(${descriptor})\">`\n ops.push({ start: node.loc.start.offset, end: openTagEnd, replacement: newOpenTag })\n }\n}\n\nfunction collectVtContentOps(node: ASTNode, ops: ReplaceOp[]): void {\n const props = node.props ?? []\n const vtDir = props.find(p => p.type === NT_DIRECTIVE && p.name === 't')\n if (!vtDir) return\n\n // Skip if this is a pure attribute binding (handled by collectVtAttrOps)\n const modifiers = (vtDir.modifiers ?? []).map(getModifierContent)\n const nonPluralMods = modifiers.filter(m => m !== 'plural')\n // If there's a non-plural modifier that corresponds to an attribute name, skip (attribute binding)\n if (nonPluralMods.length > 0) {\n const attrName = nonPluralMods[0]!\n const hasStaticAttr = props.some(p => p.type === NT_ATTRIBUTE && p.name === attrName)\n if (hasStaticAttr) return\n }\n\n const isPlural = modifiers.includes('plural')\n const bindExpr = typeof vtDir.exp?.content === 'string' ? vtDir.exp.content : undefined\n\n // Build explicit ID from arg + non-reserved modifiers\n const RESERVED_MODIFIERS = new Set(['plural'])\n const idSegments = modifiers.filter(m => !RESERVED_MODIFIERS.has(m))\n const argContent = typeof vtDir.arg?.content === 'string' ? vtDir.arg.content : undefined\n const explicitId = argContent ? [argContent, ...idSegments].join('.') : undefined\n\n const tag = node.tag!\n const children = node.children ?? []\n\n // Build clean attrs: remove v-t directive\n const exclude = new Set([vtDir])\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const attrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n if (isPlural && bindExpr) {\n // Collect text content from children\n const textContent = children\n .filter(c => c.type === NT_TEXT)\n .map(c => (typeof c.content === 'string' ? c.content : '').trim())\n .join('')\n const forms = textContent.split('|').map(s => s.trim())\n const categories = forms.length === 2\n ? ['one', 'other']\n : ['one', 'other', 'zero', 'few', 'many'].slice(0, forms.length)\n const icuParts = categories.map((cat, i) => `${cat} {${forms[i] ?? ''}}`)\n const icuMessage = `{${bindExpr}, plural, ${icuParts.join(' ')}}`\n const descriptor = buildDescriptorExpression(icuMessage, { id: explicitId })\n const replacement = `<${tag}${attrsPart}>{{ $t(${descriptor}, { ${bindExpr} }) }}</${tag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Check for rich text (child elements)\n const extracted = extractRichFromAST(children)\n if (extracted.hasElements) {\n const message = extracted.message.trim()\n const descriptor = buildDescriptorExpression(message, { id: explicitId })\n const elementsLiteral = serializeElements(extracted.elements)\n const replacement = `<${tag}${attrsPart} v-html=\"$vtRich(${descriptor}, ${elementsLiteral})\"></${tag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Plain text, possibly with interpolation\n const { message, vars } = extractVarsFromAST(children)\n const trimmedMessage = message.trim()\n\n // Skip if there's no message content and no explicit ID — matches guard in collectTransOps\n if (!trimmedMessage && !explicitId) return\n\n const descriptor = buildDescriptorExpression(trimmedMessage, { id: explicitId })\n\n let replacement: string\n if (vars.length > 0) {\n replacement = `<${tag}${attrsPart}>{{ $t(${descriptor}, { ${vars.join(', ')} }) }}</${tag}>`\n } else {\n replacement = `<${tag}${attrsPart}>{{ $t(${descriptor}) }}</${tag}>`\n }\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n}\n\nfunction collectTransOps(node: ASTNode, ops: ReplaceOp[]): void {\n if (node.tag !== 'Trans') return\n const props = node.props ?? []\n const children = node.children ?? []\n\n // Skip if empty content\n if (children.length === 0) return\n // Skip all-whitespace content\n const hasContent = children.some(c => {\n if (c.type === NT_TEXT) return (typeof c.content === 'string' ? c.content : '').trim().length > 0\n return true\n })\n if (!hasContent) return\n\n // Skip old API: <Trans message=\"...\">\n if (props.some(p => p.type === NT_ATTRIBUTE && p.name === 'message')) return\n\n const explicitId = readAttr(props, 'id')\n if (explicitId.kind === 'dynamic') return\n\n const context = readAttr(props, 'context')\n if (!explicitId.value && context.kind === 'dynamic') return\n\n // Extract tag prop (default: 'span')\n const tagAttr = readAttr(props, 'tag')\n const wrapperTag = tagAttr.value ?? 'span'\n\n // Build clean attrs: remove Trans-specific props\n const exclude = new Set<ASTNode>()\n for (const p of props) {\n if (p.type === NT_ATTRIBUTE && TRANS_ONLY_PROPS.has(p.name as string)) {\n exclude.add(p)\n }\n if (p.type === NT_DIRECTIVE && p.name === 'bind') {\n const argName = typeof p.arg?.content === 'string' ? p.arg.content : undefined\n if (argName && TRANS_ONLY_PROPS.has(argName)) {\n exclude.add(p)\n }\n }\n }\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const cleanAttrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n // Check for rich text\n const extracted = extractRichFromAST(children)\n if (extracted.hasElements) {\n const message = extracted.message.trim()\n const descriptor = buildDescriptorExpression(message, {\n id: explicitId.value,\n context: context.value,\n })\n const elementsLiteral = serializeElements(extracted.elements)\n const replacement = `<${wrapperTag}${cleanAttrsPart} v-html=\"$vtRich(${descriptor}, ${elementsLiteral})\"></${wrapperTag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Plain text\n const rawContent = children\n .map(c => (c.type === NT_TEXT && typeof c.content === 'string') ? c.content : '')\n .join('')\n .trim()\n const descriptor = buildDescriptorExpression(rawContent, {\n id: explicitId.value,\n context: context.value,\n })\n const replacement = `<${wrapperTag}${cleanAttrsPart}>{{ $t(${descriptor}) }}</${wrapperTag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n}\n\nconst PLURAL_CATS = ['zero', 'one', 'two', 'few', 'many', 'other'] as const\n\nfunction collectPluralOps(node: ASTNode, ops: ReplaceOp[]): void {\n if (node.tag !== 'Plural') return\n const props = node.props ?? []\n\n const explicitId = readAttr(props, 'id')\n const context = readAttr(props, 'context')\n if (explicitId.kind === 'dynamic') return\n if (!explicitId.value && context.kind === 'dynamic') return\n\n const valueExpr = getBindingExpr(props, 'value')\n if (!valueExpr) return\n\n const tagAttr = readAttr(props, 'tag')\n const wrapperTag = tagAttr.value ?? 'span'\n\n // Check for template slot children\n const children = node.children ?? []\n const slots: Array<{ cat: string; children: ASTNode[] }> = []\n for (const child of children) {\n if (child.type === NT_ELEMENT && child.tag === 'template') {\n const slotDir = (child.props ?? []).find(\n p => p.type === NT_DIRECTIVE && p.name === 'slot',\n )\n if (slotDir) {\n const slotName = typeof slotDir.arg?.content === 'string' ? slotDir.arg.content : undefined\n if (slotName) {\n slots.push({ cat: slotName, children: child.children ?? [] })\n }\n }\n }\n }\n\n if (slots.length > 0) {\n // Slot mode\n const allElements: RichChild[] = []\n const icuParts: string[] = []\n\n for (const cat of PLURAL_CATS) {\n const slot = slots.find(s => s.cat === cat)\n if (!slot) continue\n\n const extracted = extractRichFromAST(slot.children)\n let branchMessage: string\n\n if (extracted.hasElements) {\n const baseIndex = allElements.length\n branchMessage = extracted.message.replace(/<(\\d+)(\\/?)>/g, (_m, idxStr: string, slash: string) => {\n return `<${baseIndex + Number(idxStr)}${slash}>`\n }).replace(/<\\/(\\d+)>/g, (_m, idxStr: string) => {\n return `</${baseIndex + Number(idxStr)}>`\n })\n allElements.push(...extracted.elements)\n } else {\n // Plain text from slot children\n branchMessage = slot.children\n .map(c => (c.type === NT_TEXT && typeof c.content === 'string') ? c.content : '')\n .join('')\n .trim()\n }\n\n const icuKey = cat === 'zero' ? '=0' : cat\n icuParts.push(`${icuKey} {${branchMessage}}`)\n }\n\n if (icuParts.length === 0) return\n\n const icuMessage = `{count, plural, ${icuParts.join(' ')}}`\n const descriptor = buildDescriptorExpression(icuMessage, {\n id: explicitId.value,\n context: context.value,\n })\n\n // Build clean attrs\n const pluralOnlyProps = new Set([...TRANS_ONLY_PROPS, 'tag'])\n const exclude = new Set<ASTNode>()\n for (const p of props) {\n if (p.type === NT_ATTRIBUTE && pluralOnlyProps.has(p.name as string)) {\n exclude.add(p)\n }\n if (p.type === NT_DIRECTIVE && p.name === 'bind') {\n const argName = typeof p.arg?.content === 'string' ? p.arg.content : undefined\n if (argName === 'value' || (argName && pluralOnlyProps.has(argName))) {\n exclude.add(p)\n }\n }\n }\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const attrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n let replacement: string\n if (allElements.length > 0) {\n const elementsLiteral = serializeElements(allElements)\n replacement = `<${wrapperTag}${attrsPart} v-html=\"$vtRich(${descriptor}, ${elementsLiteral}, { count: ${valueExpr} })\"></${wrapperTag}>`\n } else {\n replacement = `<${wrapperTag}${attrsPart} v-text=\"$t(${descriptor}, { count: ${valueExpr} })\"></${wrapperTag}>`\n }\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n return\n }\n\n // Prop mode: read zero/one/two/few/many/other static props\n const icuParts: string[] = []\n const catPropsToExclude = new Set<ASTNode>()\n\n for (const cat of PLURAL_CATS) {\n const catProp = props.find(p => p.type === NT_ATTRIBUTE && p.name === cat)\n if (catProp) {\n const value = typeof catProp.value?.content === 'string' ? catProp.value.content : ''\n const icuKey = cat === 'zero' ? '=0' : cat\n icuParts.push(`${icuKey} {${value}}`)\n catPropsToExclude.add(catProp)\n }\n }\n\n if (icuParts.length === 0) return\n\n const icuMessage = `{count, plural, ${icuParts.join(' ')}}`\n const descriptor = buildDescriptorExpression(icuMessage, {\n id: explicitId.value,\n context: context.value,\n })\n\n // Build clean attrs: remove :value, tag, id, context, comment, category props\n const exclude = new Set<ASTNode>(catPropsToExclude)\n for (const p of props) {\n if (p.type === NT_ATTRIBUTE && (p.name === 'tag' || TRANS_ONLY_PROPS.has(p.name as string))) {\n exclude.add(p)\n }\n if (p.type === NT_DIRECTIVE && p.name === 'bind') {\n const argName = typeof p.arg?.content === 'string' ? p.arg.content : undefined\n if (argName === 'value' || (argName && TRANS_ONLY_PROPS.has(argName))) {\n exclude.add(p)\n }\n }\n }\n const remainingAttrs = buildCleanAttrs(props, exclude)\n const attrsPart = remainingAttrs ? ` ${remainingAttrs}` : ''\n\n const replacement = `<${wrapperTag}${attrsPart} v-text=\"$t(${descriptor}, { count: ${valueExpr} })\"></${wrapperTag}>`\n ops.push({ start: node.loc.start.offset, end: node.loc.end.offset, replacement })\n}\n\n// ─── AST traversal ────────────────────────────────────────────────────────────\n\nfunction collectOps(root: ASTNode): ReplaceOp[] {\n const ops: ReplaceOp[] = []\n\n function walk(node: ASTNode): void {\n if (node.type === NT_ELEMENT) {\n if (node.tag === 'Trans') {\n collectTransOps(node, ops)\n return // Don't recurse into transformed nodes\n }\n if (node.tag === 'Plural') {\n collectPluralOps(node, ops)\n return\n }\n\n // v-t directive handling\n const hasVt = (node.props ?? []).some(p => p.type === NT_DIRECTIVE && p.name === 't')\n if (hasVt) {\n collectVtAttrOps(node, ops)\n collectVtContentOps(node, ops)\n return\n }\n }\n\n // Recurse into children\n for (const child of node.children ?? []) {\n walk(child)\n }\n }\n\n walk(root)\n return ops\n}\n\n// ─── Entry point ──────────────────────────────────────────────────────────────\n\nexport function transformVtDirectives(sfc: string): string {\n // Quick bail: check if there's anything to transform\n if (!/<template[\\s>]/.test(sfc)) return sfc\n if (sfc.lastIndexOf('</template>') < 0) return sfc\n\n const hasVt = /\\bv-t\\b/.test(sfc)\n const hasTrans = /<Trans[\\s>]/.test(sfc)\n const hasPlural = /<Plural[\\s/>]/.test(sfc)\n if (!hasVt && !hasTrans && !hasPlural) return sfc\n\n const { descriptor } = parseSFC(sfc, { pad: false })\n if (!descriptor.template?.ast) return sfc\n\n const ops = collectOps(descriptor.template.ast as unknown as ASTNode)\n if (ops.length === 0) return sfc\n\n // Apply replacements from end to start to avoid offset drift\n ops.sort((a, b) => b.start - a.start)\n let result = sfc\n for (const op of ops) {\n result = result.slice(0, op.start) + op.replacement + result.slice(op.end)\n }\n return result\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-transform.d.ts","sourceRoot":"","sources":["../../../src/build-transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;AAExE,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,kBAAkB,EAAE,OAAO,CAAA;IAC3B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,mFAAmF;IACnF,MAAM,CAAC,EAAE,YAAY,CAAA;CACtB;AAmID,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAE5G;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,oBAAoB,CAE3G;AAkbD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CASpI"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-runner.d.ts","sourceRoot":"","sources":["../../../src/dev-runner.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC9B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,+FAA+F;IAC/F,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sEAAsE;IACtE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAChE,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5C;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEhF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,gBAAgB,EACzB,KAAK,SAAM,GACV,MAAM,IAAI,CAiCZ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAElC,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AASnE,YAAY,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC/H,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AACjF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAsBlF;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,gBAAgB,EAAE,MAAM,EAAE,EAC1B,gBAAgB,CAAC,EAAE,gBAAgB,GAClC,MAAM,EAAE,CAsPV"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"mode-detect.d.ts","sourceRoot":"","sources":["../../../src/mode-detect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAErD;AAED,oCAAoC;AACpC,wBAAgB,eAAe,IAAI,OAAO,GAAG,KAAK,CAEjD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,OAAO,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAY1F;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,WAAW,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAWpE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"runtime-template.d.ts","sourceRoot":"","sources":["../../../src/runtime-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAChE,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sfc-transform.d.ts","sourceRoot":"","sources":["../../../src/sfc-transform.ts"],"names":[],"mappings":"AAuCA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAqiBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAuBzD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAEhE,YAAY,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAExF,2CAA2C;AAC3C,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;AAEvE,+EAA+E;AAC/E,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAA;CACrC;AAED,wFAAwF;AACxF,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAA;IACpC,wGAAwG;IACxG,SAAS,EAAE,MAAM,CAAA;CAClB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"virtual-modules.d.ts","sourceRoot":"","sources":["../../../src/virtual-modules.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAA2B,MAAM,SAAS,CAAA;AA4BxE,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAA;CAChD;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIpE;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,oBAAoB,GAC5B,MAAM,GAAG,SAAS,CAQpB"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"vt-transform.d.ts","sourceRoot":"","sources":["../../../src/vt-transform.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,UAAU,IAAI,CAAA;AAC3B,eAAO,MAAM,OAAO,IAAI,CAAA;AACxB,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,YAAY,IAAI,CAAA;AAC7B,eAAO,MAAM,YAAY,IAAI,CAAA;AAC7B,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IACvD,GAAG,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CACtD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,EAAE,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,SAAS,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,CAAA;IACnC,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAQD,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IAChC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAChC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;AAE7F,wBAAgB,qBAAqB,IAAI,aAAa,CA2IrD;AA6ND,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMrF;AAWD,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAC,CAAA;IAC/D,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,cAAc,CAoC/E"}