@intlayer/svelte-compiler 8.2.2 → 8.2.4
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.
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./_virtual/_rolldown/runtime.cjs`);let t=require(`node:fs/promises`),n=require(`@babel/core`),r=require(`magic-string`);r=e.__toESM(r);let i=require(`svelte/compiler`);
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./_virtual/_rolldown/runtime.cjs`);let t=require(`node:fs/promises`),n=require(`@babel/core`),r=require(`magic-string`);r=e.__toESM(r);let i=require(`svelte/compiler`);const a=(e,t)=>{if(!e)return!1;if(!t||t.length===0)return!0;let n=e.replace(/\\/g,`/`);return t.some(e=>e.replace(/\\/g,`/`)===n)},o=(e,t,o={})=>{let{defaultLocale:s=`en`,packageName:c=`svelte-intlayer`,filesList:l,shouldExtract:u,onExtract:d,dictionaryKey:f,attributesToExtract:p=[],extractDictionaryKeyFromPath:m,generateKey:h}=o;if(!a(t,l)||!t.endsWith(`.svelte`))return null;let g=new r.default(e),_={},v=new Set,y=f??m?.(t)??``,b=[],x;try{x=(0,i.parse)(e)}catch(e){return console.warn(`Svelte extraction: Failed to parse Svelte AST for ${t}`,e),null}let S=e=>e.type===`Text`||e.type===3,C=e=>e.type===`Attribute`||e.type===6,w=e=>{if(S(e)){let t=e.data??e.content??``;if(u?.(t)&&h){let n=h(t,v);v.add(n),b.push({start:e.start,end:e.end,replacement:`{$content.${n}}`,key:n,value:t.replace(/\s+/g,` `).trim()})}}else if(C(e)&&p.includes(e.name)&&e.value&&e.value.length===1&&S(e.value[0])){let t=e.value[0].data??e.value[0].content??``;if(u?.(t)&&h){let n=h(t,v);v.add(n),b.push({start:e.start,end:e.end,replacement:`${e.name}={$content.${n}}`,key:n,value:t.trim()})}}let t=e.children??e.fragment?.nodes??e.fragment?.children;t&&t.forEach(w),e.attributes&&e.attributes.forEach(w)};x.html&&w(x.html);let T=/<script[^>]*>([\s\S]*?)<\/script>/.exec(e),E=!1,D=T?T[1]:``;if(T){let e=T[0].indexOf(`>`)+1,r=T.index+e;try{let e=(0,n.parse)(D,{parserOpts:{sourceType:`module`,plugins:[`typescript`,`jsx`]}});e&&(0,n.traverse)(e,{StringLiteral(e){if(e.parentPath.isImportDeclaration()||e.parentPath.isExportDeclaration()||e.parentPath.isImportSpecifier()||e.parentPath.isObjectProperty()&&e.key===`key`)return;if(e.parentPath.isCallExpression()){let t=e.parentPath.node.callee;if(n.types.isMemberExpression(t)&&n.types.isIdentifier(t.object)&&t.object.name===`console`||n.types.isIdentifier(t)&&(t.name===`useIntlayer`||t.name===`t`)||t.type===`Import`||n.types.isIdentifier(t)&&t.name===`require`)return}let t=e.node.value;if(u?.(t)&&h){let n=h(t,v);v.add(n),E=!0,e.node.start!=null&&e.node.end!=null&&b.push({start:r+e.node.start,end:r+e.node.end,replacement:`get(content).${n}`,key:n,value:t.trim()})}}})}catch(e){console.warn(`Svelte extraction: Failed to parse script content for ${t}`,e)}}if(b.length===0)return null;b.sort((e,t)=>t.start-e.start);for(let{start:e,end:t,replacement:n,key:r,value:i}of b)g.overwrite(e,t,n),_[r]=i;let O=/import\s*{[^}]*useIntlayer[^}]*}\s*from\s*['"][^'"]+['"]/.test(D)||/import\s+useIntlayer\s+from\s*['"][^'"]+['"]/.test(D),k=/import\s*{[^}]*get[^}]*}\s*from\s*['"]svelte\/store['"]/.test(D),A=/const\s+content\s*=\s*useIntlayer\s*\(/.test(D),j=O?``:`import { useIntlayer } from '${c}';`,M=E&&!k?`import { get } from 'svelte/store';`:``,N=A?``:`const content = useIntlayer('${y}');`,P=[j,M,N].filter(Boolean);if(P.length>0){let e=`\n ${P.join(`
|
|
2
2
|
`)}\n`;if(T){let t=T.index+T[0].indexOf(`>`)+1;g.appendLeft(t,e)}else g.prepend(`<script>\n ${j}\n ${E?`import { get } from 'svelte/store';`:``}\n ${N}\n<\/script>\n\n`)}return d&&d({dictionaryKey:y,filePath:t,content:{..._},locale:s}),{code:g.toString(),map:g.generateMap({source:t,includeContent:!0}),extracted:!0}},s=async(e,n,r,i,a=!0)=>{let s=await(0,t.readFile)(e,`utf-8`),c=null,l=o(s,e,{packageName:r,dictionaryKey:n,shouldExtract:i.shouldExtract,generateKey:i.generateKey,extractDictionaryKeyFromPath:i.extractDictionaryKeyFromPath,attributesToExtract:i.attributesToExtract,onExtract:e=>{c=e.content}});return l?(a&&await(0,t.writeFile)(e,l.code),c):null};exports.intlayerSvelteExtract=o,exports.processSvelteFile=s,exports.shouldProcessFile=a;
|
|
3
3
|
//# sourceMappingURL=svelte-intlayer-extract.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svelte-intlayer-extract.cjs","names":["MagicString","svelteCompiler","t"],"sources":["../../src/svelte-intlayer-extract.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { parse as babelParse, types as t, traverse } from '@babel/core';\nimport MagicString from 'magic-string';\nimport * as svelteCompiler from 'svelte/compiler';\n\nexport type ExtractedContent = Record<string, string>;\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: ExtractedContent;\n locale: string;\n};\n\nexport type ExtractPluginOptions = {\n defaultLocale?: string;\n packageName?: string;\n filesList?: string[];\n shouldExtract?: (text: string) => boolean;\n onExtract?: (result: ExtractResult) => void;\n dictionaryKey?: string;\n attributesToExtract?: readonly string[];\n extractDictionaryKeyFromPath?: (path: string) => string;\n generateKey?: (text: string, existingKeys: Set<string>) => string;\n};\n\ntype Replacement = {\n start: number;\n end: number;\n replacement: string;\n key: string;\n value: string;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\nexport const shouldProcessFile = (\n filename: string | undefined,\n filesList?: string[]\n): boolean => {\n if (!filename) return false;\n if (!filesList || filesList.length === 0) return true;\n\n const normalizedFilename = filename.replace(/\\\\/g, '/');\n return filesList.some((f) => {\n const normalizedF = f.replace(/\\\\/g, '/');\n return normalizedF === normalizedFilename;\n });\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\nexport const intlayerSvelteExtract = (\n code: string,\n filename: string,\n options: ExtractPluginOptions = {}\n): { code: string; map?: unknown; extracted: boolean } | null => {\n const {\n defaultLocale = 'en',\n packageName = 'svelte-intlayer',\n filesList,\n shouldExtract,\n onExtract,\n dictionaryKey: dictionaryKeyOption,\n attributesToExtract = [],\n extractDictionaryKeyFromPath,\n generateKey,\n } = options;\n\n if (!shouldProcessFile(filename, filesList)) return null;\n if (!filename.endsWith('.svelte')) return null;\n\n const magic = new MagicString(code);\n const extractedContent: ExtractedContent = {};\n const existingKeys = new Set<string>();\n const dictionaryKey =\n dictionaryKeyOption ?? extractDictionaryKeyFromPath?.(filename) ?? '';\n const replacements: Replacement[] = [];\n\n let ast: any;\n try {\n ast = svelteCompiler.parse(code);\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse Svelte AST for ${filename}`,\n e\n );\n return null;\n }\n\n // Walk Svelte HTML AST.\n // Svelte 4 used numeric type constants; Svelte 5 uses string type names.\n // We check for both to remain compatible.\n const isTextNode = (node: any) => node.type === 'Text' || node.type === 3;\n const isAttributeNode = (node: any) =>\n node.type === 'Attribute' || node.type === 6;\n\n const walkSvelte = (node: any) => {\n if (isTextNode(node)) {\n const text = node.data ?? node.content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `{$content.${key}}`,\n key,\n value: text.replace(/\\s+/g, ' ').trim(),\n });\n }\n } else if (\n isAttributeNode(node) &&\n (attributesToExtract as readonly string[]).includes(node.name)\n ) {\n if (node.value && node.value.length === 1 && isTextNode(node.value[0])) {\n const text = node.value[0].data ?? node.value[0].content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `${node.name}={$content.${key}}`,\n key,\n value: text.trim(),\n });\n }\n }\n }\n\n const children =\n node.children ?? node.fragment?.nodes ?? node.fragment?.children;\n if (children) children.forEach(walkSvelte);\n if (node.attributes) node.attributes.forEach(walkSvelte);\n };\n\n if (ast.html) {\n walkSvelte(ast.html);\n }\n\n // Extract and walk Script using Babel\n const scriptRegex = /<script[^>]*>([\\s\\S]*?)<\\/script>/;\n const scriptMatch = scriptRegex.exec(code);\n let hasScriptExtraction = false;\n const scriptContent = scriptMatch ? scriptMatch[1] : '';\n\n if (scriptMatch) {\n const openTagEndIndex = scriptMatch[0].indexOf('>') + 1;\n const offset = scriptMatch.index + openTagEndIndex;\n\n try {\n const babelAst = babelParse(scriptContent, {\n parserOpts: {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n },\n });\n\n if (babelAst) {\n traverse(babelAst, {\n StringLiteral(path: any) {\n if (path.parentPath.isImportDeclaration()) return;\n if (path.parentPath.isExportDeclaration()) return;\n if (path.parentPath.isImportSpecifier()) return;\n if (path.parentPath.isObjectProperty() && path.key === 'key')\n return;\n\n if (path.parentPath.isCallExpression()) {\n const callee = path.parentPath.node.callee;\n if (\n t.isMemberExpression(callee) &&\n t.isIdentifier(callee.object) &&\n callee.object.name === 'console'\n )\n return;\n\n if (\n t.isIdentifier(callee) &&\n (callee.name === 'useIntlayer' || callee.name === 't')\n )\n return;\n\n if (callee.type === 'Import') return;\n if (t.isIdentifier(callee) && callee.name === 'require') return;\n }\n\n const text = path.node.value;\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n hasScriptExtraction = true;\n\n if (path.node.start != null && path.node.end != null) {\n replacements.push({\n start: offset + path.node.start,\n end: offset + path.node.end,\n replacement: `get(content).${key}`,\n key,\n value: text.trim(),\n });\n }\n }\n },\n });\n }\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse script content for ${filename}`,\n e\n );\n }\n }\n\n // Abort if nothing was extracted\n if (replacements.length === 0) return null;\n\n // Apply Replacements in Reverse Order (prevents magic-string chunk errors)\n replacements.sort((a, b) => b.start - a.start);\n for (const { start, end, replacement, key, value } of replacements) {\n magic.overwrite(start, end, replacement);\n extractedContent[key] = value;\n }\n\n // Inject necessary imports and setup\n const hasUseIntlayerImport =\n /import\\s*{[^}]*useIntlayer[^}]*}\\s*from\\s*['\"][^'\"]+['\"]/.test(\n scriptContent\n ) || /import\\s+useIntlayer\\s+from\\s*['\"][^'\"]+['\"]/.test(scriptContent);\n\n const hasGetImport =\n /import\\s*{[^}]*get[^}]*}\\s*from\\s*['\"]svelte\\/store['\"]/.test(\n scriptContent\n );\n const hasContentDeclaration = /const\\s+content\\s*=\\s*useIntlayer\\s*\\(/.test(\n scriptContent\n );\n\n const importStmt = hasUseIntlayerImport\n ? ''\n : `import { useIntlayer } from '${packageName}';`;\n const getImportStmt =\n hasScriptExtraction && !hasGetImport\n ? `import { get } from 'svelte/store';`\n : '';\n const contentDecl = hasContentDeclaration\n ? ''\n : `const content = useIntlayer('${dictionaryKey}');`;\n\n const injectionParts = [importStmt, getImportStmt, contentDecl].filter(\n Boolean\n );\n\n if (injectionParts.length > 0) {\n const injection = `\\n ${injectionParts.join('\\n ')}\\n`;\n\n if (scriptMatch) {\n const scriptContentStart =\n scriptMatch.index + scriptMatch[0].indexOf('>') + 1;\n magic.appendLeft(scriptContentStart, injection);\n } else {\n magic.prepend(\n `<script>\\n ${importStmt}\\n ${hasScriptExtraction ? \"import { get } from 'svelte/store';\" : ''}\\n ${contentDecl}\\n</script>\\n\\n`\n );\n }\n }\n\n if (onExtract) {\n onExtract({\n dictionaryKey,\n filePath: filename,\n content: { ...extractedContent },\n locale: defaultLocale,\n });\n }\n\n return {\n code: magic.toString(),\n map: magic.generateMap({ source: filename, includeContent: true }),\n extracted: true,\n };\n};\n\ntype Tools = {\n generateKey: (text: string, existingKeys: Set<string>) => string;\n shouldExtract: (text: string) => boolean;\n extractDictionaryKeyFromPath: (path: string) => string;\n attributesToExtract: readonly string[];\n extractTsContent: any;\n};\n\nexport const processSvelteFile = async (\n filePath: string,\n _componentKey: string,\n packageName: string,\n tools: Tools,\n save: boolean = true\n): Promise<Record<string, string> | null> => {\n const code = await readFile(filePath, 'utf-8');\n let extractedContent: Record<string, string> | null = null;\n\n const result = intlayerSvelteExtract(code, filePath, {\n packageName,\n dictionaryKey: _componentKey,\n shouldExtract: tools.shouldExtract,\n generateKey: tools.generateKey,\n extractDictionaryKeyFromPath: tools.extractDictionaryKeyFromPath,\n attributesToExtract: tools.attributesToExtract,\n onExtract: (extractResult) => {\n extractedContent = extractResult.content;\n },\n });\n\n if (!result) return null;\n\n if (save) {\n await writeFile(filePath, result.code);\n }\n\n return extractedContent;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"svelte-intlayer-extract.cjs","names":["MagicString","t"],"sources":["../../src/svelte-intlayer-extract.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { parse as babelParse, types as t, traverse } from '@babel/core';\nimport MagicString from 'magic-string';\nimport { parse } from 'svelte/compiler';\n\nexport type ExtractedContent = Record<string, string>;\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: ExtractedContent;\n locale: string;\n};\n\nexport type ExtractPluginOptions = {\n defaultLocale?: string;\n packageName?: string;\n filesList?: string[];\n shouldExtract?: (text: string) => boolean;\n onExtract?: (result: ExtractResult) => void;\n dictionaryKey?: string;\n attributesToExtract?: readonly string[];\n extractDictionaryKeyFromPath?: (path: string) => string;\n generateKey?: (text: string, existingKeys: Set<string>) => string;\n};\n\ntype Replacement = {\n start: number;\n end: number;\n replacement: string;\n key: string;\n value: string;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\nexport const shouldProcessFile = (\n filename: string | undefined,\n filesList?: string[]\n): boolean => {\n if (!filename) return false;\n if (!filesList || filesList.length === 0) return true;\n\n const normalizedFilename = filename.replace(/\\\\/g, '/');\n return filesList.some((f) => {\n const normalizedF = f.replace(/\\\\/g, '/');\n return normalizedF === normalizedFilename;\n });\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\nexport const intlayerSvelteExtract = (\n code: string,\n filename: string,\n options: ExtractPluginOptions = {}\n): { code: string; map?: unknown; extracted: boolean } | null => {\n const {\n defaultLocale = 'en',\n packageName = 'svelte-intlayer',\n filesList,\n shouldExtract,\n onExtract,\n dictionaryKey: dictionaryKeyOption,\n attributesToExtract = [],\n extractDictionaryKeyFromPath,\n generateKey,\n } = options;\n\n if (!shouldProcessFile(filename, filesList)) return null;\n if (!filename.endsWith('.svelte')) return null;\n\n const magic = new MagicString(code);\n const extractedContent: ExtractedContent = {};\n const existingKeys = new Set<string>();\n const dictionaryKey =\n dictionaryKeyOption ?? extractDictionaryKeyFromPath?.(filename) ?? '';\n const replacements: Replacement[] = [];\n\n let ast: any;\n try {\n ast = parse(code);\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse Svelte AST for ${filename}`,\n e\n );\n return null;\n }\n\n // Walk Svelte HTML AST.\n // Svelte 4 used numeric type constants; Svelte 5 uses string type names.\n // We check for both to remain compatible.\n const isTextNode = (node: any) => node.type === 'Text' || node.type === 3;\n const isAttributeNode = (node: any) =>\n node.type === 'Attribute' || node.type === 6;\n\n const walkSvelte = (node: any) => {\n if (isTextNode(node)) {\n const text = node.data ?? node.content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `{$content.${key}}`,\n key,\n value: text.replace(/\\s+/g, ' ').trim(),\n });\n }\n } else if (\n isAttributeNode(node) &&\n (attributesToExtract as readonly string[]).includes(node.name)\n ) {\n if (node.value && node.value.length === 1 && isTextNode(node.value[0])) {\n const text = node.value[0].data ?? node.value[0].content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `${node.name}={$content.${key}}`,\n key,\n value: text.trim(),\n });\n }\n }\n }\n\n const children =\n node.children ?? node.fragment?.nodes ?? node.fragment?.children;\n if (children) children.forEach(walkSvelte);\n if (node.attributes) node.attributes.forEach(walkSvelte);\n };\n\n if (ast.html) {\n walkSvelte(ast.html);\n }\n\n // Extract and walk Script using Babel\n const scriptRegex = /<script[^>]*>([\\s\\S]*?)<\\/script>/;\n const scriptMatch = scriptRegex.exec(code);\n let hasScriptExtraction = false;\n const scriptContent = scriptMatch ? scriptMatch[1] : '';\n\n if (scriptMatch) {\n const openTagEndIndex = scriptMatch[0].indexOf('>') + 1;\n const offset = scriptMatch.index + openTagEndIndex;\n\n try {\n const babelAst = babelParse(scriptContent, {\n parserOpts: {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n },\n });\n\n if (babelAst) {\n traverse(babelAst, {\n StringLiteral(path: any) {\n if (path.parentPath.isImportDeclaration()) return;\n if (path.parentPath.isExportDeclaration()) return;\n if (path.parentPath.isImportSpecifier()) return;\n if (path.parentPath.isObjectProperty() && path.key === 'key')\n return;\n\n if (path.parentPath.isCallExpression()) {\n const callee = path.parentPath.node.callee;\n if (\n t.isMemberExpression(callee) &&\n t.isIdentifier(callee.object) &&\n callee.object.name === 'console'\n )\n return;\n\n if (\n t.isIdentifier(callee) &&\n (callee.name === 'useIntlayer' || callee.name === 't')\n )\n return;\n\n if (callee.type === 'Import') return;\n if (t.isIdentifier(callee) && callee.name === 'require') return;\n }\n\n const text = path.node.value;\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n hasScriptExtraction = true;\n\n if (path.node.start != null && path.node.end != null) {\n replacements.push({\n start: offset + path.node.start,\n end: offset + path.node.end,\n replacement: `get(content).${key}`,\n key,\n value: text.trim(),\n });\n }\n }\n },\n });\n }\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse script content for ${filename}`,\n e\n );\n }\n }\n\n // Abort if nothing was extracted\n if (replacements.length === 0) return null;\n\n // Apply Replacements in Reverse Order (prevents magic-string chunk errors)\n replacements.sort((a, b) => b.start - a.start);\n for (const { start, end, replacement, key, value } of replacements) {\n magic.overwrite(start, end, replacement);\n extractedContent[key] = value;\n }\n\n // Inject necessary imports and setup\n const hasUseIntlayerImport =\n /import\\s*{[^}]*useIntlayer[^}]*}\\s*from\\s*['\"][^'\"]+['\"]/.test(\n scriptContent\n ) || /import\\s+useIntlayer\\s+from\\s*['\"][^'\"]+['\"]/.test(scriptContent);\n\n const hasGetImport =\n /import\\s*{[^}]*get[^}]*}\\s*from\\s*['\"]svelte\\/store['\"]/.test(\n scriptContent\n );\n const hasContentDeclaration = /const\\s+content\\s*=\\s*useIntlayer\\s*\\(/.test(\n scriptContent\n );\n\n const importStmt = hasUseIntlayerImport\n ? ''\n : `import { useIntlayer } from '${packageName}';`;\n const getImportStmt =\n hasScriptExtraction && !hasGetImport\n ? `import { get } from 'svelte/store';`\n : '';\n const contentDecl = hasContentDeclaration\n ? ''\n : `const content = useIntlayer('${dictionaryKey}');`;\n\n const injectionParts = [importStmt, getImportStmt, contentDecl].filter(\n Boolean\n );\n\n if (injectionParts.length > 0) {\n const injection = `\\n ${injectionParts.join('\\n ')}\\n`;\n\n if (scriptMatch) {\n const scriptContentStart =\n scriptMatch.index + scriptMatch[0].indexOf('>') + 1;\n magic.appendLeft(scriptContentStart, injection);\n } else {\n magic.prepend(\n `<script>\\n ${importStmt}\\n ${hasScriptExtraction ? \"import { get } from 'svelte/store';\" : ''}\\n ${contentDecl}\\n</script>\\n\\n`\n );\n }\n }\n\n if (onExtract) {\n onExtract({\n dictionaryKey,\n filePath: filename,\n content: { ...extractedContent },\n locale: defaultLocale,\n });\n }\n\n return {\n code: magic.toString(),\n map: magic.generateMap({ source: filename, includeContent: true }),\n extracted: true,\n };\n};\n\ntype Tools = {\n generateKey: (text: string, existingKeys: Set<string>) => string;\n shouldExtract: (text: string) => boolean;\n extractDictionaryKeyFromPath: (path: string) => string;\n attributesToExtract: readonly string[];\n extractTsContent: any;\n};\n\nexport const processSvelteFile = async (\n filePath: string,\n _componentKey: string,\n packageName: string,\n tools: Tools,\n save: boolean = true\n): Promise<Record<string, string> | null> => {\n const code = await readFile(filePath, 'utf-8');\n let extractedContent: Record<string, string> | null = null;\n\n const result = intlayerSvelteExtract(code, filePath, {\n packageName,\n dictionaryKey: _componentKey,\n shouldExtract: tools.shouldExtract,\n generateKey: tools.generateKey,\n extractDictionaryKeyFromPath: tools.extractDictionaryKeyFromPath,\n attributesToExtract: tools.attributesToExtract,\n onExtract: (extractResult) => {\n extractedContent = extractResult.content;\n },\n });\n\n if (!result) return null;\n\n if (save) {\n await writeFile(filePath, result.code);\n }\n\n return extractedContent;\n};\n"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{readFile as e,writeFile as t}from"node:fs/promises";import{parse as n,traverse as r,types as i}from"@babel/core";import a from"magic-string";import
|
|
1
|
+
import{readFile as e,writeFile as t}from"node:fs/promises";import{parse as n,traverse as r,types as i}from"@babel/core";import a from"magic-string";import{parse as o}from"svelte/compiler";const s=(e,t)=>{if(!e)return!1;if(!t||t.length===0)return!0;let n=e.replace(/\\/g,`/`);return t.some(e=>e.replace(/\\/g,`/`)===n)},c=(e,t,c={})=>{let{defaultLocale:l=`en`,packageName:u=`svelte-intlayer`,filesList:d,shouldExtract:f,onExtract:p,dictionaryKey:m,attributesToExtract:h=[],extractDictionaryKeyFromPath:g,generateKey:_}=c;if(!s(t,d)||!t.endsWith(`.svelte`))return null;let v=new a(e),y={},b=new Set,x=m??g?.(t)??``,S=[],C;try{C=o(e)}catch(e){return console.warn(`Svelte extraction: Failed to parse Svelte AST for ${t}`,e),null}let w=e=>e.type===`Text`||e.type===3,T=e=>e.type===`Attribute`||e.type===6,E=e=>{if(w(e)){let t=e.data??e.content??``;if(f?.(t)&&_){let n=_(t,b);b.add(n),S.push({start:e.start,end:e.end,replacement:`{$content.${n}}`,key:n,value:t.replace(/\s+/g,` `).trim()})}}else if(T(e)&&h.includes(e.name)&&e.value&&e.value.length===1&&w(e.value[0])){let t=e.value[0].data??e.value[0].content??``;if(f?.(t)&&_){let n=_(t,b);b.add(n),S.push({start:e.start,end:e.end,replacement:`${e.name}={$content.${n}}`,key:n,value:t.trim()})}}let t=e.children??e.fragment?.nodes??e.fragment?.children;t&&t.forEach(E),e.attributes&&e.attributes.forEach(E)};C.html&&E(C.html);let D=/<script[^>]*>([\s\S]*?)<\/script>/.exec(e),O=!1,k=D?D[1]:``;if(D){let e=D[0].indexOf(`>`)+1,a=D.index+e;try{let e=n(k,{parserOpts:{sourceType:`module`,plugins:[`typescript`,`jsx`]}});e&&r(e,{StringLiteral(e){if(e.parentPath.isImportDeclaration()||e.parentPath.isExportDeclaration()||e.parentPath.isImportSpecifier()||e.parentPath.isObjectProperty()&&e.key===`key`)return;if(e.parentPath.isCallExpression()){let t=e.parentPath.node.callee;if(i.isMemberExpression(t)&&i.isIdentifier(t.object)&&t.object.name===`console`||i.isIdentifier(t)&&(t.name===`useIntlayer`||t.name===`t`)||t.type===`Import`||i.isIdentifier(t)&&t.name===`require`)return}let t=e.node.value;if(f?.(t)&&_){let n=_(t,b);b.add(n),O=!0,e.node.start!=null&&e.node.end!=null&&S.push({start:a+e.node.start,end:a+e.node.end,replacement:`get(content).${n}`,key:n,value:t.trim()})}}})}catch(e){console.warn(`Svelte extraction: Failed to parse script content for ${t}`,e)}}if(S.length===0)return null;S.sort((e,t)=>t.start-e.start);for(let{start:e,end:t,replacement:n,key:r,value:i}of S)v.overwrite(e,t,n),y[r]=i;let A=/import\s*{[^}]*useIntlayer[^}]*}\s*from\s*['"][^'"]+['"]/.test(k)||/import\s+useIntlayer\s+from\s*['"][^'"]+['"]/.test(k),j=/import\s*{[^}]*get[^}]*}\s*from\s*['"]svelte\/store['"]/.test(k),M=/const\s+content\s*=\s*useIntlayer\s*\(/.test(k),N=A?``:`import { useIntlayer } from '${u}';`,P=O&&!j?`import { get } from 'svelte/store';`:``,F=M?``:`const content = useIntlayer('${x}');`,I=[N,P,F].filter(Boolean);if(I.length>0){let e=`\n ${I.join(`
|
|
2
2
|
`)}\n`;if(D){let t=D.index+D[0].indexOf(`>`)+1;v.appendLeft(t,e)}else v.prepend(`<script>\n ${N}\n ${O?`import { get } from 'svelte/store';`:``}\n ${F}\n<\/script>\n\n`)}return p&&p({dictionaryKey:x,filePath:t,content:{...y},locale:l}),{code:v.toString(),map:v.generateMap({source:t,includeContent:!0}),extracted:!0}},l=async(n,r,i,a,o=!0)=>{let s=await e(n,`utf-8`),l=null,u=c(s,n,{packageName:i,dictionaryKey:r,shouldExtract:a.shouldExtract,generateKey:a.generateKey,extractDictionaryKeyFromPath:a.extractDictionaryKeyFromPath,attributesToExtract:a.attributesToExtract,onExtract:e=>{l=e.content}});return u?(o&&await t(n,u.code),l):null};export{c as intlayerSvelteExtract,l as processSvelteFile,s as shouldProcessFile};
|
|
3
3
|
//# sourceMappingURL=svelte-intlayer-extract.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svelte-intlayer-extract.mjs","names":["babelParse","t"],"sources":["../../src/svelte-intlayer-extract.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { parse as babelParse, types as t, traverse } from '@babel/core';\nimport MagicString from 'magic-string';\nimport * as svelteCompiler from 'svelte/compiler';\n\nexport type ExtractedContent = Record<string, string>;\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: ExtractedContent;\n locale: string;\n};\n\nexport type ExtractPluginOptions = {\n defaultLocale?: string;\n packageName?: string;\n filesList?: string[];\n shouldExtract?: (text: string) => boolean;\n onExtract?: (result: ExtractResult) => void;\n dictionaryKey?: string;\n attributesToExtract?: readonly string[];\n extractDictionaryKeyFromPath?: (path: string) => string;\n generateKey?: (text: string, existingKeys: Set<string>) => string;\n};\n\ntype Replacement = {\n start: number;\n end: number;\n replacement: string;\n key: string;\n value: string;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\nexport const shouldProcessFile = (\n filename: string | undefined,\n filesList?: string[]\n): boolean => {\n if (!filename) return false;\n if (!filesList || filesList.length === 0) return true;\n\n const normalizedFilename = filename.replace(/\\\\/g, '/');\n return filesList.some((f) => {\n const normalizedF = f.replace(/\\\\/g, '/');\n return normalizedF === normalizedFilename;\n });\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\nexport const intlayerSvelteExtract = (\n code: string,\n filename: string,\n options: ExtractPluginOptions = {}\n): { code: string; map?: unknown; extracted: boolean } | null => {\n const {\n defaultLocale = 'en',\n packageName = 'svelte-intlayer',\n filesList,\n shouldExtract,\n onExtract,\n dictionaryKey: dictionaryKeyOption,\n attributesToExtract = [],\n extractDictionaryKeyFromPath,\n generateKey,\n } = options;\n\n if (!shouldProcessFile(filename, filesList)) return null;\n if (!filename.endsWith('.svelte')) return null;\n\n const magic = new MagicString(code);\n const extractedContent: ExtractedContent = {};\n const existingKeys = new Set<string>();\n const dictionaryKey =\n dictionaryKeyOption ?? extractDictionaryKeyFromPath?.(filename) ?? '';\n const replacements: Replacement[] = [];\n\n let ast: any;\n try {\n ast = svelteCompiler.parse(code);\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse Svelte AST for ${filename}`,\n e\n );\n return null;\n }\n\n // Walk Svelte HTML AST.\n // Svelte 4 used numeric type constants; Svelte 5 uses string type names.\n // We check for both to remain compatible.\n const isTextNode = (node: any) => node.type === 'Text' || node.type === 3;\n const isAttributeNode = (node: any) =>\n node.type === 'Attribute' || node.type === 6;\n\n const walkSvelte = (node: any) => {\n if (isTextNode(node)) {\n const text = node.data ?? node.content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `{$content.${key}}`,\n key,\n value: text.replace(/\\s+/g, ' ').trim(),\n });\n }\n } else if (\n isAttributeNode(node) &&\n (attributesToExtract as readonly string[]).includes(node.name)\n ) {\n if (node.value && node.value.length === 1 && isTextNode(node.value[0])) {\n const text = node.value[0].data ?? node.value[0].content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `${node.name}={$content.${key}}`,\n key,\n value: text.trim(),\n });\n }\n }\n }\n\n const children =\n node.children ?? node.fragment?.nodes ?? node.fragment?.children;\n if (children) children.forEach(walkSvelte);\n if (node.attributes) node.attributes.forEach(walkSvelte);\n };\n\n if (ast.html) {\n walkSvelte(ast.html);\n }\n\n // Extract and walk Script using Babel\n const scriptRegex = /<script[^>]*>([\\s\\S]*?)<\\/script>/;\n const scriptMatch = scriptRegex.exec(code);\n let hasScriptExtraction = false;\n const scriptContent = scriptMatch ? scriptMatch[1] : '';\n\n if (scriptMatch) {\n const openTagEndIndex = scriptMatch[0].indexOf('>') + 1;\n const offset = scriptMatch.index + openTagEndIndex;\n\n try {\n const babelAst = babelParse(scriptContent, {\n parserOpts: {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n },\n });\n\n if (babelAst) {\n traverse(babelAst, {\n StringLiteral(path: any) {\n if (path.parentPath.isImportDeclaration()) return;\n if (path.parentPath.isExportDeclaration()) return;\n if (path.parentPath.isImportSpecifier()) return;\n if (path.parentPath.isObjectProperty() && path.key === 'key')\n return;\n\n if (path.parentPath.isCallExpression()) {\n const callee = path.parentPath.node.callee;\n if (\n t.isMemberExpression(callee) &&\n t.isIdentifier(callee.object) &&\n callee.object.name === 'console'\n )\n return;\n\n if (\n t.isIdentifier(callee) &&\n (callee.name === 'useIntlayer' || callee.name === 't')\n )\n return;\n\n if (callee.type === 'Import') return;\n if (t.isIdentifier(callee) && callee.name === 'require') return;\n }\n\n const text = path.node.value;\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n hasScriptExtraction = true;\n\n if (path.node.start != null && path.node.end != null) {\n replacements.push({\n start: offset + path.node.start,\n end: offset + path.node.end,\n replacement: `get(content).${key}`,\n key,\n value: text.trim(),\n });\n }\n }\n },\n });\n }\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse script content for ${filename}`,\n e\n );\n }\n }\n\n // Abort if nothing was extracted\n if (replacements.length === 0) return null;\n\n // Apply Replacements in Reverse Order (prevents magic-string chunk errors)\n replacements.sort((a, b) => b.start - a.start);\n for (const { start, end, replacement, key, value } of replacements) {\n magic.overwrite(start, end, replacement);\n extractedContent[key] = value;\n }\n\n // Inject necessary imports and setup\n const hasUseIntlayerImport =\n /import\\s*{[^}]*useIntlayer[^}]*}\\s*from\\s*['\"][^'\"]+['\"]/.test(\n scriptContent\n ) || /import\\s+useIntlayer\\s+from\\s*['\"][^'\"]+['\"]/.test(scriptContent);\n\n const hasGetImport =\n /import\\s*{[^}]*get[^}]*}\\s*from\\s*['\"]svelte\\/store['\"]/.test(\n scriptContent\n );\n const hasContentDeclaration = /const\\s+content\\s*=\\s*useIntlayer\\s*\\(/.test(\n scriptContent\n );\n\n const importStmt = hasUseIntlayerImport\n ? ''\n : `import { useIntlayer } from '${packageName}';`;\n const getImportStmt =\n hasScriptExtraction && !hasGetImport\n ? `import { get } from 'svelte/store';`\n : '';\n const contentDecl = hasContentDeclaration\n ? ''\n : `const content = useIntlayer('${dictionaryKey}');`;\n\n const injectionParts = [importStmt, getImportStmt, contentDecl].filter(\n Boolean\n );\n\n if (injectionParts.length > 0) {\n const injection = `\\n ${injectionParts.join('\\n ')}\\n`;\n\n if (scriptMatch) {\n const scriptContentStart =\n scriptMatch.index + scriptMatch[0].indexOf('>') + 1;\n magic.appendLeft(scriptContentStart, injection);\n } else {\n magic.prepend(\n `<script>\\n ${importStmt}\\n ${hasScriptExtraction ? \"import { get } from 'svelte/store';\" : ''}\\n ${contentDecl}\\n</script>\\n\\n`\n );\n }\n }\n\n if (onExtract) {\n onExtract({\n dictionaryKey,\n filePath: filename,\n content: { ...extractedContent },\n locale: defaultLocale,\n });\n }\n\n return {\n code: magic.toString(),\n map: magic.generateMap({ source: filename, includeContent: true }),\n extracted: true,\n };\n};\n\ntype Tools = {\n generateKey: (text: string, existingKeys: Set<string>) => string;\n shouldExtract: (text: string) => boolean;\n extractDictionaryKeyFromPath: (path: string) => string;\n attributesToExtract: readonly string[];\n extractTsContent: any;\n};\n\nexport const processSvelteFile = async (\n filePath: string,\n _componentKey: string,\n packageName: string,\n tools: Tools,\n save: boolean = true\n): Promise<Record<string, string> | null> => {\n const code = await readFile(filePath, 'utf-8');\n let extractedContent: Record<string, string> | null = null;\n\n const result = intlayerSvelteExtract(code, filePath, {\n packageName,\n dictionaryKey: _componentKey,\n shouldExtract: tools.shouldExtract,\n generateKey: tools.generateKey,\n extractDictionaryKeyFromPath: tools.extractDictionaryKeyFromPath,\n attributesToExtract: tools.attributesToExtract,\n onExtract: (extractResult) => {\n extractedContent = extractResult.content;\n },\n });\n\n if (!result) return null;\n\n if (save) {\n await writeFile(filePath, result.code);\n }\n\n return extractedContent;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"svelte-intlayer-extract.mjs","names":["parse","babelParse","t"],"sources":["../../src/svelte-intlayer-extract.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { parse as babelParse, types as t, traverse } from '@babel/core';\nimport MagicString from 'magic-string';\nimport { parse } from 'svelte/compiler';\n\nexport type ExtractedContent = Record<string, string>;\n\nexport type ExtractResult = {\n dictionaryKey: string;\n filePath: string;\n content: ExtractedContent;\n locale: string;\n};\n\nexport type ExtractPluginOptions = {\n defaultLocale?: string;\n packageName?: string;\n filesList?: string[];\n shouldExtract?: (text: string) => boolean;\n onExtract?: (result: ExtractResult) => void;\n dictionaryKey?: string;\n attributesToExtract?: readonly string[];\n extractDictionaryKeyFromPath?: (path: string) => string;\n generateKey?: (text: string, existingKeys: Set<string>) => string;\n};\n\ntype Replacement = {\n start: number;\n end: number;\n replacement: string;\n key: string;\n value: string;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\nexport const shouldProcessFile = (\n filename: string | undefined,\n filesList?: string[]\n): boolean => {\n if (!filename) return false;\n if (!filesList || filesList.length === 0) return true;\n\n const normalizedFilename = filename.replace(/\\\\/g, '/');\n return filesList.some((f) => {\n const normalizedF = f.replace(/\\\\/g, '/');\n return normalizedF === normalizedFilename;\n });\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\nexport const intlayerSvelteExtract = (\n code: string,\n filename: string,\n options: ExtractPluginOptions = {}\n): { code: string; map?: unknown; extracted: boolean } | null => {\n const {\n defaultLocale = 'en',\n packageName = 'svelte-intlayer',\n filesList,\n shouldExtract,\n onExtract,\n dictionaryKey: dictionaryKeyOption,\n attributesToExtract = [],\n extractDictionaryKeyFromPath,\n generateKey,\n } = options;\n\n if (!shouldProcessFile(filename, filesList)) return null;\n if (!filename.endsWith('.svelte')) return null;\n\n const magic = new MagicString(code);\n const extractedContent: ExtractedContent = {};\n const existingKeys = new Set<string>();\n const dictionaryKey =\n dictionaryKeyOption ?? extractDictionaryKeyFromPath?.(filename) ?? '';\n const replacements: Replacement[] = [];\n\n let ast: any;\n try {\n ast = parse(code);\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse Svelte AST for ${filename}`,\n e\n );\n return null;\n }\n\n // Walk Svelte HTML AST.\n // Svelte 4 used numeric type constants; Svelte 5 uses string type names.\n // We check for both to remain compatible.\n const isTextNode = (node: any) => node.type === 'Text' || node.type === 3;\n const isAttributeNode = (node: any) =>\n node.type === 'Attribute' || node.type === 6;\n\n const walkSvelte = (node: any) => {\n if (isTextNode(node)) {\n const text = node.data ?? node.content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `{$content.${key}}`,\n key,\n value: text.replace(/\\s+/g, ' ').trim(),\n });\n }\n } else if (\n isAttributeNode(node) &&\n (attributesToExtract as readonly string[]).includes(node.name)\n ) {\n if (node.value && node.value.length === 1 && isTextNode(node.value[0])) {\n const text = node.value[0].data ?? node.value[0].content ?? '';\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n replacements.push({\n start: node.start,\n end: node.end,\n replacement: `${node.name}={$content.${key}}`,\n key,\n value: text.trim(),\n });\n }\n }\n }\n\n const children =\n node.children ?? node.fragment?.nodes ?? node.fragment?.children;\n if (children) children.forEach(walkSvelte);\n if (node.attributes) node.attributes.forEach(walkSvelte);\n };\n\n if (ast.html) {\n walkSvelte(ast.html);\n }\n\n // Extract and walk Script using Babel\n const scriptRegex = /<script[^>]*>([\\s\\S]*?)<\\/script>/;\n const scriptMatch = scriptRegex.exec(code);\n let hasScriptExtraction = false;\n const scriptContent = scriptMatch ? scriptMatch[1] : '';\n\n if (scriptMatch) {\n const openTagEndIndex = scriptMatch[0].indexOf('>') + 1;\n const offset = scriptMatch.index + openTagEndIndex;\n\n try {\n const babelAst = babelParse(scriptContent, {\n parserOpts: {\n sourceType: 'module',\n plugins: ['typescript', 'jsx'],\n },\n });\n\n if (babelAst) {\n traverse(babelAst, {\n StringLiteral(path: any) {\n if (path.parentPath.isImportDeclaration()) return;\n if (path.parentPath.isExportDeclaration()) return;\n if (path.parentPath.isImportSpecifier()) return;\n if (path.parentPath.isObjectProperty() && path.key === 'key')\n return;\n\n if (path.parentPath.isCallExpression()) {\n const callee = path.parentPath.node.callee;\n if (\n t.isMemberExpression(callee) &&\n t.isIdentifier(callee.object) &&\n callee.object.name === 'console'\n )\n return;\n\n if (\n t.isIdentifier(callee) &&\n (callee.name === 'useIntlayer' || callee.name === 't')\n )\n return;\n\n if (callee.type === 'Import') return;\n if (t.isIdentifier(callee) && callee.name === 'require') return;\n }\n\n const text = path.node.value;\n if (shouldExtract?.(text) && generateKey) {\n const key = generateKey(text, existingKeys);\n existingKeys.add(key);\n hasScriptExtraction = true;\n\n if (path.node.start != null && path.node.end != null) {\n replacements.push({\n start: offset + path.node.start,\n end: offset + path.node.end,\n replacement: `get(content).${key}`,\n key,\n value: text.trim(),\n });\n }\n }\n },\n });\n }\n } catch (e) {\n console.warn(\n `Svelte extraction: Failed to parse script content for ${filename}`,\n e\n );\n }\n }\n\n // Abort if nothing was extracted\n if (replacements.length === 0) return null;\n\n // Apply Replacements in Reverse Order (prevents magic-string chunk errors)\n replacements.sort((a, b) => b.start - a.start);\n for (const { start, end, replacement, key, value } of replacements) {\n magic.overwrite(start, end, replacement);\n extractedContent[key] = value;\n }\n\n // Inject necessary imports and setup\n const hasUseIntlayerImport =\n /import\\s*{[^}]*useIntlayer[^}]*}\\s*from\\s*['\"][^'\"]+['\"]/.test(\n scriptContent\n ) || /import\\s+useIntlayer\\s+from\\s*['\"][^'\"]+['\"]/.test(scriptContent);\n\n const hasGetImport =\n /import\\s*{[^}]*get[^}]*}\\s*from\\s*['\"]svelte\\/store['\"]/.test(\n scriptContent\n );\n const hasContentDeclaration = /const\\s+content\\s*=\\s*useIntlayer\\s*\\(/.test(\n scriptContent\n );\n\n const importStmt = hasUseIntlayerImport\n ? ''\n : `import { useIntlayer } from '${packageName}';`;\n const getImportStmt =\n hasScriptExtraction && !hasGetImport\n ? `import { get } from 'svelte/store';`\n : '';\n const contentDecl = hasContentDeclaration\n ? ''\n : `const content = useIntlayer('${dictionaryKey}');`;\n\n const injectionParts = [importStmt, getImportStmt, contentDecl].filter(\n Boolean\n );\n\n if (injectionParts.length > 0) {\n const injection = `\\n ${injectionParts.join('\\n ')}\\n`;\n\n if (scriptMatch) {\n const scriptContentStart =\n scriptMatch.index + scriptMatch[0].indexOf('>') + 1;\n magic.appendLeft(scriptContentStart, injection);\n } else {\n magic.prepend(\n `<script>\\n ${importStmt}\\n ${hasScriptExtraction ? \"import { get } from 'svelte/store';\" : ''}\\n ${contentDecl}\\n</script>\\n\\n`\n );\n }\n }\n\n if (onExtract) {\n onExtract({\n dictionaryKey,\n filePath: filename,\n content: { ...extractedContent },\n locale: defaultLocale,\n });\n }\n\n return {\n code: magic.toString(),\n map: magic.generateMap({ source: filename, includeContent: true }),\n extracted: true,\n };\n};\n\ntype Tools = {\n generateKey: (text: string, existingKeys: Set<string>) => string;\n shouldExtract: (text: string) => boolean;\n extractDictionaryKeyFromPath: (path: string) => string;\n attributesToExtract: readonly string[];\n extractTsContent: any;\n};\n\nexport const processSvelteFile = async (\n filePath: string,\n _componentKey: string,\n packageName: string,\n tools: Tools,\n save: boolean = true\n): Promise<Record<string, string> | null> => {\n const code = await readFile(filePath, 'utf-8');\n let extractedContent: Record<string, string> | null = null;\n\n const result = intlayerSvelteExtract(code, filePath, {\n packageName,\n dictionaryKey: _componentKey,\n shouldExtract: tools.shouldExtract,\n generateKey: tools.generateKey,\n extractDictionaryKeyFromPath: tools.extractDictionaryKeyFromPath,\n attributesToExtract: tools.attributesToExtract,\n onExtract: (extractResult) => {\n extractedContent = extractResult.content;\n },\n });\n\n if (!result) return null;\n\n if (save) {\n await writeFile(filePath, result.code);\n }\n\n return extractedContent;\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/svelte-compiler",
|
|
3
|
-
"version": "8.2.
|
|
3
|
+
"version": "8.2.4",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Vite-compatible compiler plugin for Svelte with Intlayer, providing HMR support, file transformation, and optimized dictionary loading for Svelte applications.",
|
|
6
6
|
"keywords": [
|
|
@@ -88,12 +88,12 @@
|
|
|
88
88
|
"@types/babel__core": "7.20.5",
|
|
89
89
|
"@types/babel__generator": "7.27.0",
|
|
90
90
|
"@types/babel__traverse": "7.28.0",
|
|
91
|
-
"@types/node": "25.3.
|
|
91
|
+
"@types/node": "25.3.5",
|
|
92
92
|
"@utils/ts-config": "1.0.4",
|
|
93
93
|
"@utils/ts-config-types": "1.0.4",
|
|
94
94
|
"@utils/tsdown-config": "1.0.4",
|
|
95
95
|
"rimraf": "6.1.3",
|
|
96
|
-
"tsdown": "0.
|
|
96
|
+
"tsdown": "0.21.0",
|
|
97
97
|
"typescript": "5.9.3",
|
|
98
98
|
"vitest": "4.0.18"
|
|
99
99
|
},
|