@fluenti/cli 0.1.3 → 0.2.1

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.
Files changed (37) hide show
  1. package/dist/cli.cjs +9 -9
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.js +206 -209
  4. package/dist/cli.js.map +1 -1
  5. package/dist/compile-runner.d.ts +7 -0
  6. package/dist/compile-runner.d.ts.map +1 -0
  7. package/dist/compile.d.ts.map +1 -1
  8. package/dist/{compile-BJdEF9QX.js → config-loader-BgAoTfxH.js} +123 -93
  9. package/dist/config-loader-BgAoTfxH.js.map +1 -0
  10. package/dist/config-loader-D3RGkK_r.cjs +16 -0
  11. package/dist/config-loader-D3RGkK_r.cjs.map +1 -0
  12. package/dist/config-loader.d.ts +7 -0
  13. package/dist/config-loader.d.ts.map +1 -0
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +2 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +29 -6
  19. package/dist/index.js.map +1 -1
  20. package/dist/translate.d.ts +2 -1
  21. package/dist/translate.d.ts.map +1 -1
  22. package/dist/{tsx-extractor-DZrY1LMS.js → tsx-extractor-CcFjsYI-.js} +1 -1
  23. package/dist/{tsx-extractor-DZrY1LMS.js.map → tsx-extractor-CcFjsYI-.js.map} +1 -1
  24. package/dist/tsx-extractor-D__s_cP8.cjs +2 -0
  25. package/dist/{tsx-extractor-LEAVCuX9.cjs.map → tsx-extractor-D__s_cP8.cjs.map} +1 -1
  26. package/dist/vue-extractor.cjs +3 -0
  27. package/dist/vue-extractor.cjs.map +1 -0
  28. package/dist/{vue-extractor-iUl6SUkv.js → vue-extractor.js} +60 -67
  29. package/dist/vue-extractor.js.map +1 -0
  30. package/package.json +27 -2
  31. package/dist/compile-BJdEF9QX.js.map +0 -1
  32. package/dist/compile-d4Q8bND5.cjs +0 -16
  33. package/dist/compile-d4Q8bND5.cjs.map +0 -1
  34. package/dist/tsx-extractor-LEAVCuX9.cjs +0 -2
  35. package/dist/vue-extractor-BlHc3vzt.cjs +0 -3
  36. package/dist/vue-extractor-BlHc3vzt.cjs.map +0 -1
  37. package/dist/vue-extractor-iUl6SUkv.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"vue-extractor-iUl6SUkv.js","names":[],"sources":["../src/vue-extractor.ts"],"sourcesContent":["import type { ExtractedMessage } from '@fluenti/core'\nimport { parse as parseSFC } from '@vue/compiler-sfc'\nimport { createMessageId } from '@fluenti/core/internal'\nimport { extractFromTsx } from './tsx-extractor'\n\n// Vue template AST node types\nconst ELEMENT_NODE = 1\nconst TEXT_NODE = 2\nconst DIRECTIVE_PROP = 7\nconst ATTRIBUTE_PROP = 6\n\ninterface LocInfo {\n line: number\n column: number\n offset: number\n}\n\ninterface SourceLoc {\n start: LocInfo\n end: LocInfo\n source: string\n}\n\ninterface TemplateNode {\n type: number\n tag?: string\n tagType?: number\n props?: TemplateProp[]\n children?: TemplateNode[]\n content?: string\n loc: SourceLoc\n}\n\ninterface TemplateProp {\n type: number\n name: string | { content: string }\n rawName?: string\n arg?: { content: string; isStatic: boolean }\n exp?: { content: string }\n modifiers?: Array<{ content: string } | string>\n value?: { content: string }\n nameLoc?: SourceLoc\n loc: SourceLoc\n}\n\nfunction getTextContent(children: TemplateNode[]): string {\n return children\n .filter((c) => c.type === TEXT_NODE)\n .map((c) => (c.content ?? '').trim())\n .join('')\n}\n\nfunction buildPluralICUFromPipe(text: string, countVar: string): string {\n const forms = text.split('|').map((s) => s.trim())\n const categories = ['one', 'other', 'zero', 'few', 'many']\n const options: string[] = []\n\n if (forms.length === 2) {\n options.push(`one {${forms[0]}}`)\n options.push(`other {${forms[1]}}`)\n } else {\n for (let i = 0; i < forms.length && i < categories.length; i++) {\n options.push(`${categories[i]} {${forms[i]}}`)\n }\n }\n\n return `{${countVar}, plural, ${options.join(' ')}}`\n}\n\nfunction buildPluralICUFromProps(props: Record<string, string>): string {\n const countVar = props['count'] ?? 'count'\n const categories = ['zero', 'one', 'two', 'few', 'many', 'other']\n const options: string[] = []\n const offset = props['offset']\n\n for (const cat of categories) {\n if (props[cat] !== undefined) {\n const key = cat === 'zero' ? '=0' : cat\n options.push(`${key} {${props[cat]}}`)\n }\n }\n\n if (options.length === 0) return ''\n const offsetPrefix = offset ? `offset:${offset} ` : ''\n return `{${countVar}, plural, ${offsetPrefix}${options.join(' ')}}`\n}\n\nfunction walkTemplate(\n node: TemplateNode,\n filename: string,\n messages: ExtractedMessage[],\n): void {\n if (node.type === ELEMENT_NODE) {\n const vtDirective = node.props?.find(\n (p) => p.type === DIRECTIVE_PROP && getPropName(p) === 't',\n )\n\n if (vtDirective) {\n const RESERVED_MODIFIERS = new Set(['plural'])\n const modifiers = (vtDirective.modifiers ?? []).map(\n (m: string | { content: string }) => (typeof m === 'string' ? m : m.content),\n )\n const isPlural = modifiers.includes('plural')\n // Reconstruct dotted ID: v-t:checkout.title → arg=\"checkout\", modifier=\"title\" → \"checkout.title\"\n // Non-reserved modifiers are treated as ID path segments\n const idSegments = modifiers.filter((m: string) => !RESERVED_MODIFIERS.has(m))\n const argContent = vtDirective.arg?.content\n const explicitId = argContent\n ? [argContent, ...idSegments].join('.')\n : undefined\n const textContent = getTextContent(node.children ?? [])\n\n if (isPlural) {\n const countVar = vtDirective.exp?.content ?? 'count'\n const message = buildPluralICUFromPipe(textContent, countVar)\n const id = explicitId ?? createMessageId(message)\n messages.push({\n id,\n message,\n origin: {\n file: filename,\n line: vtDirective.loc.start.line,\n column: vtDirective.loc.start.column,\n },\n })\n } else if (textContent) {\n const id = explicitId ?? createMessageId(textContent)\n messages.push({\n id,\n message: textContent,\n origin: {\n file: filename,\n line: vtDirective.loc.start.line,\n column: vtDirective.loc.start.column,\n },\n })\n }\n }\n\n if (node.tag === 'Trans') {\n const messageProp = node.props?.find(\n (p) => p.type === ATTRIBUTE_PROP && getPropName(p) === 'message',\n )\n const idProp = node.props?.find(\n (p) => p.type === ATTRIBUTE_PROP && getPropName(p) === 'id',\n )\n const contextProp = node.props?.find(\n (p) => p.type === ATTRIBUTE_PROP && getPropName(p) === 'context',\n )\n const commentProp = node.props?.find(\n (p) => p.type === ATTRIBUTE_PROP && getPropName(p) === 'comment',\n )\n const context = contextProp?.value?.content\n const comment = commentProp?.value?.content\n\n if (messageProp?.value) {\n // Old API: <Trans message=\"...\" />\n const message = messageProp.value.content\n const id = idProp?.value?.content ?? createMessageId(message, context)\n messages.push({\n id,\n message,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n origin: {\n file: filename,\n line: node.loc.start.line,\n column: node.loc.start.column,\n },\n })\n } else if (node.children && node.children.length > 0) {\n // New API: <Trans>content with <a>rich text</a></Trans>\n const richText = extractRichTextFromTemplateChildren(node.children)\n if (richText.message) {\n const id = idProp?.value?.content ?? createMessageId(richText.message, context)\n messages.push({\n id,\n message: richText.message,\n ...(context !== undefined ? { context } : {}),\n ...(comment !== undefined ? { comment } : {}),\n origin: {\n file: filename,\n line: node.loc.start.line,\n column: node.loc.start.column,\n },\n })\n }\n }\n }\n\n if (node.tag === 'Plural') {\n const propsMap: Record<string, string> = {}\n let valueExpr: string | undefined\n let offsetExpr: string | undefined\n for (const prop of node.props ?? []) {\n if (prop.type === ATTRIBUTE_PROP && prop.value) {\n propsMap[getPropName(prop)] = prop.value.content\n }\n // Handle :value=\"expr\" binding (directive prop)\n if (prop.type === DIRECTIVE_PROP && getPropName(prop) === 'bind' && prop.arg?.content === 'value' && prop.exp) {\n valueExpr = prop.exp.content\n }\n if (prop.type === DIRECTIVE_PROP && getPropName(prop) === 'bind' && prop.arg?.content === 'offset' && prop.exp) {\n offsetExpr = prop.exp.content\n }\n }\n\n // Use :value binding expression as count variable, fall back to 'count' static prop\n const countVar = valueExpr ?? propsMap['count'] ?? 'count'\n const offset = offsetExpr ?? propsMap['offset']\n const pluralMessage = buildPluralICUFromProps({\n ...propsMap,\n count: countVar,\n ...(offset !== undefined ? { offset } : {}),\n })\n if (pluralMessage) {\n const id = propsMap['id'] ?? createMessageId(pluralMessage)\n messages.push({\n id,\n message: pluralMessage,\n origin: {\n file: filename,\n line: node.loc.start.line,\n column: node.loc.start.column,\n },\n })\n }\n }\n }\n\n if (node.children) {\n for (const child of node.children) {\n walkTemplate(child, filename, messages)\n }\n }\n}\n\nfunction extractRichTextFromTemplateChildren(\n children: TemplateNode[],\n): { message: string; hasElements: boolean } {\n let elementIndex = 0\n let hasElements = false\n\n const parts = children.map((child) => {\n if (child.type === TEXT_NODE) {\n return (child.content ?? '').trim() ? child.content ?? '' : ''\n }\n if (child.type === ELEMENT_NODE && child.tag) {\n hasElements = true\n const idx = elementIndex++\n const innerText = extractRichTextFromTemplateChildren(child.children ?? []).message\n return `<${idx}>${innerText}</${idx}>`\n }\n return ''\n })\n\n return {\n message: parts.join('').trim(),\n hasElements,\n }\n}\n\nfunction getPropName(prop: TemplateProp): string {\n if (typeof prop.name === 'string') return prop.name\n return prop.name.content\n}\n\nfunction extractTemplateInterpolations(\n content: string,\n filename: string,\n): ExtractedMessage[] {\n const messages: ExtractedMessage[] = []\n const interpolationRegex = /\\{\\{([\\s\\S]*?)\\}\\}/g\n let match: RegExpExecArray | null\n\n while ((match = interpolationRegex.exec(content)) !== null) {\n const expression = match[1]?.trim()\n if (!expression) continue\n\n const extracted = extractFromTsx(expression, filename)\n if (extracted.length === 0) continue\n\n const lineOffset = content.slice(0, match.index).split('\\n').length - 1\n for (const msg of extracted) {\n messages.push({\n ...msg,\n origin: {\n ...msg.origin,\n line: msg.origin.line + lineOffset,\n },\n })\n }\n }\n\n return messages\n}\n\n/** Extract messages from Vue SFC files */\nexport function extractFromVue(code: string, filename: string): ExtractedMessage[] {\n const messages: ExtractedMessage[] = []\n\n const { descriptor } = parseSFC(code, { filename })\n\n if (descriptor.template?.ast) {\n walkTemplate(descriptor.template.ast as unknown as TemplateNode, filename, messages)\n }\n\n // Also extract t() function calls from raw template source\n // (picks up t('source text') in template expressions like {{ t('...') }})\n if (descriptor.template?.content) {\n const templateMessages = extractFromTsx(descriptor.template.content, filename)\n const templateLoc = descriptor.template.loc\n const lineOffset = templateLoc.start.line - 1\n const existingIds = new Set(messages.map((m) => m.id))\n for (const msg of templateMessages) {\n if (!existingIds.has(msg.id)) {\n messages.push({\n ...msg,\n origin: {\n ...msg.origin,\n line: msg.origin.line + lineOffset,\n },\n })\n }\n }\n\n const interpolationMessages = extractTemplateInterpolations(descriptor.template.content, filename)\n for (const msg of interpolationMessages) {\n if (!existingIds.has(msg.id)) {\n messages.push({\n ...msg,\n origin: {\n ...msg.origin,\n line: msg.origin.line + lineOffset,\n },\n })\n }\n }\n }\n\n if (descriptor.scriptSetup?.content) {\n const scriptMessages = extractFromTsx(descriptor.scriptSetup.content, filename)\n const scriptLoc = descriptor.scriptSetup.loc\n const lineOffset = scriptLoc.start.line - 1\n for (const msg of scriptMessages) {\n messages.push({\n ...msg,\n origin: {\n ...msg.origin,\n line: msg.origin.line + lineOffset,\n },\n })\n }\n }\n\n if (descriptor.script?.content) {\n const scriptMessages = extractFromTsx(descriptor.script.content, filename)\n const scriptLoc = descriptor.script.loc\n const lineOffset = scriptLoc.start.line - 1\n for (const msg of scriptMessages) {\n messages.push({\n ...msg,\n origin: {\n ...msg.origin,\n line: msg.origin.line + lineOffset,\n },\n })\n }\n }\n\n return messages\n}\n"],"mappings":"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"}