@intlayer/chokidar 7.2.0 → 7.2.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.
Files changed (37) hide show
  1. package/dist/cjs/_virtual/rolldown_runtime.cjs +10 -6
  2. package/dist/cjs/compiler/extractDictionaryKey.cjs +38 -0
  3. package/dist/cjs/compiler/extractDictionaryKey.cjs.map +1 -0
  4. package/dist/cjs/compiler/index.cjs +225 -0
  5. package/dist/cjs/compiler/index.cjs.map +1 -0
  6. package/dist/cjs/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs +5 -4
  7. package/dist/cjs/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs.map +1 -1
  8. package/dist/cjs/index.cjs +12 -6
  9. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +1 -1
  10. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  11. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +2 -2
  12. package/dist/esm/compiler/extractDictionaryKey.mjs +36 -0
  13. package/dist/esm/compiler/extractDictionaryKey.mjs.map +1 -0
  14. package/dist/esm/compiler/index.mjs +219 -0
  15. package/dist/esm/compiler/index.mjs.map +1 -0
  16. package/dist/esm/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.mjs +5 -4
  17. package/dist/esm/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.mjs.map +1 -1
  18. package/dist/esm/index.mjs +8 -7
  19. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +1 -1
  20. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  21. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +2 -2
  22. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts +3 -3
  23. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts +3 -3
  24. package/dist/types/buildIntlayerDictionary/writeMergedDictionary.d.ts +2 -2
  25. package/dist/types/buildIntlayerDictionary/writeRemoteDictionary.d.ts +2 -2
  26. package/dist/types/compiler/extractDictionaryKey.d.ts +13 -0
  27. package/dist/types/compiler/extractDictionaryKey.d.ts.map +1 -0
  28. package/dist/types/compiler/index.d.ts +36 -0
  29. package/dist/types/compiler/index.d.ts.map +1 -0
  30. package/dist/types/createDictionaryEntryPoint/createDictionaryEntryPoint.d.ts +2 -2
  31. package/dist/types/createDictionaryEntryPoint/generateDictionaryListContent.d.ts +2 -2
  32. package/dist/types/createDictionaryEntryPoint/generateDictionaryListContent.d.ts.map +1 -1
  33. package/dist/types/index.d.ts +2 -1
  34. package/dist/types/loadDictionaries/loadRemoteDictionaries.d.ts +2 -2
  35. package/dist/types/utils/getFormatFromExtension.d.ts.map +1 -1
  36. package/dist/types/writeContentDeclaration/transformJSFile.d.ts.map +1 -1
  37. package/package.json +13 -13
@@ -6,12 +6,16 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
- });
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
15
19
  }
16
20
  return to;
17
21
  };
@@ -0,0 +1,38 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ let node_path = require("node:path");
3
+
4
+ //#region src/compiler/extractDictionaryKey.ts
5
+ /**
6
+ * Attempt to detect an exported React component name in the file text.
7
+ * Looks for patterns like:
8
+ * - export const MyComponent = ...
9
+ * - export function MyComponent(...)
10
+ * - export default function MyComponent(...)
11
+ */
12
+ const detectExportedComponentName = (fileText) => {
13
+ const defaultEsmFnRegex = /export\s+default\s+function\s+(\w+)/;
14
+ const defaultEsmVarRegex = /export\s+default\s+(\w+)/;
15
+ const cjsDefaultRegex = /module\.exports\s*=\s*(\w+)/;
16
+ const cjsDefaultVarRegex = /exports\.default\s*=\s*(\w+)/;
17
+ const namedExportRegex = /export\s+(?:const|function)\s+(\w+)/g;
18
+ const defaultEsmFnMatch = fileText.match(defaultEsmFnRegex);
19
+ if (defaultEsmFnMatch) return defaultEsmFnMatch[1];
20
+ const defaultEsmVarMatch = fileText.match(defaultEsmVarRegex);
21
+ if (defaultEsmVarMatch) return defaultEsmVarMatch[1];
22
+ const cjsDefaultMatch = fileText.match(cjsDefaultRegex) || fileText.match(cjsDefaultVarRegex);
23
+ if (cjsDefaultMatch) return cjsDefaultMatch[1];
24
+ for (const [, exportName] of fileText.matchAll(namedExportRegex)) if (/^[A-Z]/.test(exportName)) return exportName;
25
+ return null;
26
+ };
27
+ const extractDictionaryKey = (filePath, fileText) => {
28
+ const componentName = detectExportedComponentName(fileText);
29
+ if (componentName) return componentName;
30
+ let baseName = (0, node_path.basename)(filePath, (0, node_path.extname)(filePath));
31
+ if (baseName === "index") baseName = (0, node_path.basename)((0, node_path.dirname)(filePath));
32
+ return baseName;
33
+ };
34
+
35
+ //#endregion
36
+ exports.detectExportedComponentName = detectExportedComponentName;
37
+ exports.extractDictionaryKey = extractDictionaryKey;
38
+ //# sourceMappingURL=extractDictionaryKey.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractDictionaryKey.cjs","names":[],"sources":["../../../src/compiler/extractDictionaryKey.ts"],"sourcesContent":["import { basename, dirname, extname } from 'node:path';\n\n/**\n * Attempt to detect an exported React component name in the file text.\n * Looks for patterns like:\n * - export const MyComponent = ...\n * - export function MyComponent(...)\n * - export default function MyComponent(...)\n */\nexport const detectExportedComponentName = (\n fileText: string\n): string | null => {\n // Added regexes for default ESM, default CJS, and named exports\n const defaultEsmFnRegex = /export\\s+default\\s+function\\s+(\\w+)/;\n const defaultEsmVarRegex = /export\\s+default\\s+(\\w+)/;\n const cjsDefaultRegex = /module\\.exports\\s*=\\s*(\\w+)/;\n const cjsDefaultVarRegex = /exports\\.default\\s*=\\s*(\\w+)/;\n const namedExportRegex = /export\\s+(?:const|function)\\s+(\\w+)/g;\n\n // 1) Check for default ESM function or variable\n const defaultEsmFnMatch = fileText.match(defaultEsmFnRegex);\n if (defaultEsmFnMatch) {\n return defaultEsmFnMatch[1];\n }\n\n const defaultEsmVarMatch = fileText.match(defaultEsmVarRegex);\n if (defaultEsmVarMatch) {\n return defaultEsmVarMatch[1];\n }\n\n // 2) Check for default CJS\n const cjsDefaultMatch =\n fileText.match(cjsDefaultRegex) || fileText.match(cjsDefaultVarRegex);\n if (cjsDefaultMatch) {\n return cjsDefaultMatch[1];\n }\n\n // 3) Otherwise, look for capitalized named exports\n for (const [, exportName] of fileText.matchAll(namedExportRegex)) {\n if (/^[A-Z]/.test(exportName)) {\n return exportName;\n }\n }\n\n // If we can’t find it, return null\n return null;\n};\n\nexport const extractDictionaryKey = (\n filePath: string,\n fileText: string\n): string => {\n const componentName = detectExportedComponentName(fileText);\n if (componentName) {\n return componentName;\n }\n\n const ext = extname(filePath);\n let baseName = basename(filePath, ext);\n\n if (baseName === 'index') {\n baseName = basename(dirname(filePath));\n }\n\n return baseName;\n};\n"],"mappings":";;;;;;;;;;;AASA,MAAa,+BACX,aACkB;CAElB,MAAM,oBAAoB;CAC1B,MAAM,qBAAqB;CAC3B,MAAM,kBAAkB;CACxB,MAAM,qBAAqB;CAC3B,MAAM,mBAAmB;CAGzB,MAAM,oBAAoB,SAAS,MAAM,kBAAkB;AAC3D,KAAI,kBACF,QAAO,kBAAkB;CAG3B,MAAM,qBAAqB,SAAS,MAAM,mBAAmB;AAC7D,KAAI,mBACF,QAAO,mBAAmB;CAI5B,MAAM,kBACJ,SAAS,MAAM,gBAAgB,IAAI,SAAS,MAAM,mBAAmB;AACvE,KAAI,gBACF,QAAO,gBAAgB;AAIzB,MAAK,MAAM,GAAG,eAAe,SAAS,SAAS,iBAAiB,CAC9D,KAAI,SAAS,KAAK,WAAW,CAC3B,QAAO;AAKX,QAAO;;AAGT,MAAa,wBACX,UACA,aACW;CACX,MAAM,gBAAgB,4BAA4B,SAAS;AAC3D,KAAI,cACF,QAAO;CAIT,IAAI,mCAAoB,iCADJ,SAAS,CACS;AAEtC,KAAI,aAAa,QACf,2DAA4B,SAAS,CAAC;AAGxC,QAAO"}
@@ -0,0 +1,225 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_writeContentDeclaration_detectFormatCommand = require('../writeContentDeclaration/detectFormatCommand.cjs');
3
+ const require_writeContentDeclaration_writeContentDeclaration = require('../writeContentDeclaration/writeContentDeclaration.cjs');
4
+ const require_compiler_extractDictionaryKey = require('./extractDictionaryKey.cjs');
5
+ let __intlayer_config = require("@intlayer/config");
6
+ let node_path = require("node:path");
7
+ let node_child_process = require("node:child_process");
8
+ let ts_morph = require("ts-morph");
9
+
10
+ //#region src/compiler/index.ts
11
+ const ATTRIBUTES_TO_EXTRACT = [
12
+ "title",
13
+ "placeholder",
14
+ "alt",
15
+ "aria-label",
16
+ "label"
17
+ ];
18
+ const generateKey = (text, existingKeys) => {
19
+ let key = text.replace(/\s+/g, " ").replace(/[^a-zA-Z0-9 ]/g, "").trim().split(" ").filter(Boolean).slice(0, 5).map((word, index) => index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
20
+ if (!key) key = "content";
21
+ if (existingKeys.has(key)) {
22
+ let i = 1;
23
+ while (existingKeys.has(`${key}${i}`)) i++;
24
+ key = `${key}${i}`;
25
+ }
26
+ return key;
27
+ };
28
+ const shouldExtract = (text) => {
29
+ const trimmed = text.trim();
30
+ if (!trimmed) return false;
31
+ if (!trimmed.includes(" ")) return false;
32
+ if (!/^[A-Z]/.test(trimmed)) return false;
33
+ return true;
34
+ };
35
+ /**
36
+ * 1. Extraction of content
37
+ */
38
+ const extractContent = (sourceFile) => {
39
+ const extractedContent = {};
40
+ const existingKeys = /* @__PURE__ */ new Set();
41
+ const replacements = [];
42
+ const processText = (text, node, type) => {
43
+ if (!shouldExtract(text)) return;
44
+ const key = generateKey(text.trim(), existingKeys);
45
+ existingKeys.add(key);
46
+ extractedContent[key] = type === "jsx-text" ? text.replace(/\s+/g, " ").trim() : text.trim();
47
+ replacements.push({
48
+ node,
49
+ key,
50
+ type
51
+ });
52
+ };
53
+ sourceFile.forEachDescendant((node) => {
54
+ if (ts_morph.Node.isJsxText(node)) processText(node.getText(), node, "jsx-text");
55
+ if (ts_morph.Node.isJsxAttribute(node)) {
56
+ const name = node.getNameNode().getText();
57
+ if (ATTRIBUTES_TO_EXTRACT.includes(name)) {
58
+ const initializer = node.getInitializer();
59
+ if (ts_morph.Node.isStringLiteral(initializer)) processText(initializer.getLiteralValue(), node, "jsx-attribute");
60
+ }
61
+ }
62
+ if (ts_morph.Node.isStringLiteral(node)) {
63
+ const parent = node.getParent();
64
+ if (ts_morph.Node.isCallExpression(parent)) {
65
+ const expression = parent.getExpression();
66
+ if (ts_morph.Node.isIdentifier(expression) && expression.getText() === "useState") processText(node.getLiteralValue(), node, "string-literal");
67
+ }
68
+ if (ts_morph.Node.isConditionalExpression(parent)) {
69
+ let current = parent.getParent();
70
+ let isInsideJsx = false;
71
+ while (current) {
72
+ if (ts_morph.Node.isJsxExpression(current)) {
73
+ isInsideJsx = true;
74
+ break;
75
+ }
76
+ if (ts_morph.Node.isBlock(current) || ts_morph.Node.isSourceFile(current)) break;
77
+ current = current.getParent();
78
+ }
79
+ if (isInsideJsx) processText(node.getLiteralValue(), node, "string-literal");
80
+ }
81
+ if (ts_morph.Node.isArrayLiteralExpression(parent)) processText(node.getLiteralValue(), node, "string-literal");
82
+ if (ts_morph.Node.isPropertyAssignment(parent)) {
83
+ if (parent.getInitializer() === node) processText(node.getLiteralValue(), node, "string-literal");
84
+ }
85
+ if (ts_morph.Node.isReturnStatement(parent)) processText(node.getLiteralValue(), node, "string-literal");
86
+ }
87
+ });
88
+ return {
89
+ extractedContent,
90
+ replacements
91
+ };
92
+ };
93
+ /**
94
+ * 2. Write content declaration
95
+ */
96
+ const writeContent = async (extractedContent, componentKey, filePath, configuration, outputDir) => {
97
+ const { defaultLocale } = configuration.internationalization;
98
+ const { baseDir } = configuration.content;
99
+ const dirName = outputDir ? (0, node_path.resolve)(outputDir) : (0, node_path.dirname)(filePath);
100
+ const contentFilePath = (0, node_path.join)(dirName, `${(0, node_path.basename)(filePath, (0, node_path.extname)(filePath))}.content.ts`);
101
+ await require_writeContentDeclaration_writeContentDeclaration.writeContentDeclaration({
102
+ key: componentKey,
103
+ content: extractedContent,
104
+ locale: defaultLocale,
105
+ filePath: (0, node_path.relative)(baseDir, contentFilePath)
106
+ }, configuration, { newDictionariesPath: (0, node_path.relative)(baseDir, dirName) });
107
+ return contentFilePath;
108
+ };
109
+ const isComponent = (node) => {
110
+ let name;
111
+ if (ts_morph.Node.isFunctionDeclaration(node)) name = node.getName();
112
+ else if (ts_morph.Node.isFunctionExpression(node) || ts_morph.Node.isArrowFunction(node)) {
113
+ const parent = node.getParent();
114
+ if (ts_morph.Node.isVariableDeclaration(parent)) name = parent.getName();
115
+ }
116
+ if (!name) return false;
117
+ return /^[A-Z]/.test(name);
118
+ };
119
+ /**
120
+ * 3. Transform component
121
+ */
122
+ const transformComponent = async (sourceFile, replacements, componentKey, packageName) => {
123
+ if (replacements.length === 0) return;
124
+ const componentsToInjectHook = /* @__PURE__ */ new Map();
125
+ for (const { node, key, type } of replacements) {
126
+ let current = node.getParent();
127
+ while (current) {
128
+ if ((ts_morph.Node.isFunctionDeclaration(current) || ts_morph.Node.isArrowFunction(current) || ts_morph.Node.isFunctionExpression(current)) && (() => {
129
+ const body = current.getBody?.();
130
+ return body && ts_morph.Node.isBlock(body);
131
+ })()) {
132
+ const injectionType = isComponent(current) ? "hook" : "function";
133
+ const existing = componentsToInjectHook.get(current);
134
+ if (!existing) componentsToInjectHook.set(current, injectionType);
135
+ else if (existing === "function" && injectionType === "hook") componentsToInjectHook.set(current, "hook");
136
+ break;
137
+ }
138
+ current = current.getParent();
139
+ }
140
+ const replaceText = (isJsx) => {
141
+ return !isJsx && (packageName === "react-intlayer" || packageName === "next-intlayer") ? `content.${key}.value` : `content.${key}`;
142
+ };
143
+ if (type === "jsx-text" && ts_morph.Node.isJsxText(node)) node.replaceWithText(`{${replaceText(true)}}`);
144
+ else if (type === "jsx-attribute" && ts_morph.Node.isJsxAttribute(node)) node.setInitializer(`{${replaceText(false)}}`);
145
+ else if (type === "string-literal" && ts_morph.Node.isStringLiteral(node)) node.replaceWithText(replaceText(false));
146
+ }
147
+ let injectedUseIntlayer = false;
148
+ let injectedGetIntlayer = false;
149
+ for (const [componentBody, injectionType] of componentsToInjectHook) {
150
+ const body = componentBody.getBody();
151
+ if (ts_morph.Node.isBlock(body)) {
152
+ const text = body.getText();
153
+ const statement = injectionType === "hook" ? `const content = useIntlayer("${componentKey}");` : `const content = getIntlayer("${componentKey}");`;
154
+ if (!text.includes(`useIntlayer("${componentKey}")`) && !text.includes(`getIntlayer("${componentKey}")`)) body.insertStatements(0, statement);
155
+ if (injectionType === "hook") injectedUseIntlayer = true;
156
+ if (injectionType === "function") injectedGetIntlayer = true;
157
+ }
158
+ }
159
+ const importSource = packageName === "next-intlayer" ? sourceFile.getText().includes("\"use client\"") || sourceFile.getText().includes("'use client'") ? "next-intlayer" : "next-intlayer/server" : packageName;
160
+ const existingImport = sourceFile.getImportDeclaration((d) => d.getModuleSpecifierValue() === importSource);
161
+ const namedImports = /* @__PURE__ */ new Set();
162
+ if (injectedUseIntlayer) namedImports.add("useIntlayer");
163
+ if (injectedGetIntlayer) namedImports.add("getIntlayer");
164
+ if (namedImports.size > 0) if (!existingImport) sourceFile.addImportDeclaration({
165
+ namedImports: Array.from(namedImports),
166
+ moduleSpecifier: importSource
167
+ });
168
+ else {
169
+ const currentNamedImports = existingImport.getNamedImports().map((n) => n.getName());
170
+ for (const name of namedImports) if (!currentNamedImports.includes(name)) existingImport.addNamedImport(name);
171
+ }
172
+ await sourceFile.save();
173
+ };
174
+ const extractIntlayer = async (filePath, packageName, options, project) => {
175
+ const configuration = (0, __intlayer_config.getConfiguration)(options?.configOptions);
176
+ const { baseDir } = configuration.content;
177
+ const appLogger = (0, __intlayer_config.getAppLogger)(configuration);
178
+ const _project = project || new ts_morph.Project({ skipAddingFilesFromTsConfig: true });
179
+ let sourceFile;
180
+ try {
181
+ sourceFile = _project.addSourceFileAtPath(filePath);
182
+ } catch {
183
+ sourceFile = _project.getSourceFileOrThrow(filePath);
184
+ }
185
+ const baseName = require_compiler_extractDictionaryKey.extractDictionaryKey(filePath, sourceFile.getText());
186
+ const componentKey = (0, __intlayer_config.camelCaseToKebabCase)(baseName);
187
+ const { extractedContent, replacements } = extractContent(sourceFile);
188
+ if (Object.keys(extractedContent).length === 0) {
189
+ appLogger(`No extractable text found in ${baseName}`);
190
+ if (!project) {}
191
+ return;
192
+ }
193
+ const contentFilePath = await writeContent(extractedContent, componentKey, filePath, configuration, options?.outputDir);
194
+ appLogger(`Created content file: ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(configuration.content.baseDir, contentFilePath))}`);
195
+ await transformComponent(sourceFile, replacements, componentKey, packageName);
196
+ const formatCommand = require_writeContentDeclaration_detectFormatCommand.detectFormatCommand(configuration);
197
+ if (formatCommand) try {
198
+ (0, node_child_process.execSync)(formatCommand.replace("{{file}}", filePath), {
199
+ stdio: "inherit",
200
+ cwd: baseDir
201
+ });
202
+ } catch (error) {
203
+ console.error(error);
204
+ }
205
+ appLogger(`Updated component: ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(baseDir, filePath))}`);
206
+ if (project) sourceFile.forget();
207
+ };
208
+ const transformFiles = async (filePaths, packageName, options) => {
209
+ const appLogger = (0, __intlayer_config.getAppLogger)((0, __intlayer_config.getConfiguration)(options?.configOptions));
210
+ const project = new ts_morph.Project({ skipAddingFilesFromTsConfig: true });
211
+ for (const filePath of filePaths) try {
212
+ await extractIntlayer(filePath, packageName, options, project);
213
+ } catch (error) {
214
+ appLogger(`Failed to transform ${filePath}: ${error.message}`);
215
+ }
216
+ };
217
+
218
+ //#endregion
219
+ exports.extractContent = extractContent;
220
+ exports.extractIntlayer = extractIntlayer;
221
+ exports.shouldExtract = shouldExtract;
222
+ exports.transformComponent = transformComponent;
223
+ exports.transformFiles = transformFiles;
224
+ exports.writeContent = writeContent;
225
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["extractedContent: Record<string, string>","replacements: Replacement[]","Node","current: Node | undefined","writeContentDeclaration","name: string | undefined","Project","sourceFile: SourceFile","extractDictionaryKey","detectFormatCommand"],"sources":["../../../src/compiler/index.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { basename, dirname, extname, join, relative, resolve } from 'node:path';\nimport {\n camelCaseToKebabCase,\n colorizePath,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type { Dictionary, IntlayerConfig } from '@intlayer/types';\nimport { Node, Project, type SourceFile } from 'ts-morph';\nimport { writeContentDeclaration } from '../writeContentDeclaration';\nimport { detectFormatCommand } from '../writeContentDeclaration/detectFormatCommand';\nimport { extractDictionaryKey } from './extractDictionaryKey';\n\nconst ATTRIBUTES_TO_EXTRACT = [\n 'title',\n 'placeholder',\n 'alt',\n 'aria-label',\n 'label',\n];\n\nconst generateKey = (text: string, existingKeys: Set<string>): string => {\n const maxWords = 5;\n let key = text\n .replace(/\\s+/g, ' ') // Normalize whitespace to single spaces\n .replace(/[^a-zA-Z0-9 ]/g, '') // Remove special chars\n .trim()\n .split(' ')\n .filter(Boolean)\n .slice(0, maxWords)\n .map((word, index) =>\n index === 0\n ? word.toLowerCase()\n : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()\n )\n .join('');\n\n // Fallback for empty keys (e.g. only symbols)\n if (!key) key = 'content';\n\n // Handle duplicates\n if (existingKeys.has(key)) {\n let i = 1;\n while (existingKeys.has(`${key}${i}`)) i++;\n key = `${key}${i}`;\n }\n\n return key;\n};\n\ntype Replacement = {\n node: Node;\n key: string;\n type: 'jsx-text' | 'jsx-attribute' | 'string-literal';\n};\n\nexport const shouldExtract = (text: string): boolean => {\n const trimmed = text.trim();\n // 1. Must have some text\n if (!trimmed) return false;\n // 2. Must contain spaces (not a single camelCase/kebab-case word)\n if (!trimmed.includes(' ')) return false;\n // 3. Must start with a capital letter\n // We check the first non-whitespace character\n if (!/^[A-Z]/.test(trimmed)) return false;\n\n return true;\n};\n\n/**\n * 1. Extraction of content\n */\nexport const extractContent = (sourceFile: SourceFile) => {\n const extractedContent: Record<string, string> = {};\n const existingKeys = new Set<string>();\n const replacements: Replacement[] = [];\n\n const processText = (text: string, node: Node, type: Replacement['type']) => {\n if (!shouldExtract(text)) return;\n\n const key = generateKey(text.trim(), existingKeys);\n existingKeys.add(key);\n extractedContent[key] =\n type === 'jsx-text' ? text.replace(/\\s+/g, ' ').trim() : text.trim();\n replacements.push({ node, key, type });\n };\n\n sourceFile.forEachDescendant((node) => {\n // Case A: JSX Text (e.g., <h2>Title</h2>)\n if (Node.isJsxText(node)) {\n processText(node.getText(), node, 'jsx-text');\n }\n\n // Case B: JSX Attributes (e.g., placeholder=\"Search\")\n if (Node.isJsxAttribute(node)) {\n const name = node.getNameNode().getText();\n if (ATTRIBUTES_TO_EXTRACT.includes(name)) {\n const initializer = node.getInitializer();\n if (Node.isStringLiteral(initializer)) {\n processText(initializer.getLiteralValue(), node, 'jsx-attribute');\n }\n }\n }\n\n // Case C: String Literals in specific contexts\n if (Node.isStringLiteral(node)) {\n const parent = node.getParent();\n\n // 1. State initialization: useState('...')\n if (Node.isCallExpression(parent)) {\n const expression = parent.getExpression();\n if (\n Node.isIdentifier(expression) &&\n expression.getText() === 'useState'\n ) {\n processText(node.getLiteralValue(), node, 'string-literal');\n }\n }\n\n // 2. Ternary operators in JSX: { isTrue ? 'Text' : 'Other' }\n if (Node.isConditionalExpression(parent)) {\n // Check if this conditional is inside a JSX expression\n let current: Node | undefined = parent.getParent();\n let isInsideJsx = false;\n while (current) {\n if (Node.isJsxExpression(current)) {\n isInsideJsx = true;\n break;\n }\n if (Node.isBlock(current) || Node.isSourceFile(current)) break;\n current = current.getParent();\n }\n\n if (isInsideJsx) {\n processText(node.getLiteralValue(), node, 'string-literal');\n }\n }\n\n // 3. Array elements (simple heuristic: inside array literal)\n if (Node.isArrayLiteralExpression(parent)) {\n processText(node.getLiteralValue(), node, 'string-literal');\n }\n\n // 4. Object property values (e.g. { value: \"Text\" })\n if (Node.isPropertyAssignment(parent)) {\n const initializer = parent.getInitializer();\n if (initializer === node) {\n processText(node.getLiteralValue(), node, 'string-literal');\n }\n }\n\n // 5. Return statements\n if (Node.isReturnStatement(parent)) {\n processText(node.getLiteralValue(), node, 'string-literal');\n }\n }\n });\n\n return { extractedContent, replacements };\n};\n\n/**\n * 2. Write content declaration\n */\nexport const writeContent = async (\n extractedContent: Record<string, string>,\n componentKey: string,\n filePath: string,\n configuration: IntlayerConfig,\n outputDir?: string\n) => {\n const { defaultLocale } = configuration.internationalization;\n const { baseDir } = configuration.content;\n\n const dirName = outputDir ? resolve(outputDir) : dirname(filePath);\n const ext = extname(filePath);\n const baseName = basename(filePath, ext);\n\n const contentFilePath = join(dirName, `${baseName}.content.ts`);\n const relativeContentFilePath = relative(baseDir, contentFilePath);\n\n const dictionary: Dictionary = {\n key: componentKey,\n content: extractedContent,\n locale: defaultLocale,\n filePath: relativeContentFilePath,\n };\n\n const relativeDir = relative(baseDir, dirName);\n\n await writeContentDeclaration(dictionary, configuration, {\n newDictionariesPath: relativeDir,\n });\n\n return contentFilePath;\n};\n\nconst isComponent = (node: Node): boolean => {\n let name: string | undefined;\n\n if (Node.isFunctionDeclaration(node)) {\n name = node.getName();\n } else if (Node.isFunctionExpression(node) || Node.isArrowFunction(node)) {\n const parent = node.getParent();\n if (Node.isVariableDeclaration(parent)) {\n name = parent.getName();\n }\n }\n\n if (!name) return false;\n // Check for PascalCase\n return /^[A-Z]/.test(name);\n};\n\n/**\n * 3. Transform component\n */\nexport const transformComponent = async (\n sourceFile: SourceFile,\n replacements: Replacement[],\n componentKey: string,\n packageName: string\n) => {\n if (replacements.length === 0) return;\n\n const componentsToInjectHook = new Map<Node, 'hook' | 'function'>();\n\n for (const { node, key, type } of replacements) {\n // Find the parent function/component\n let current = node.getParent();\n while (current) {\n if (\n (Node.isFunctionDeclaration(current) ||\n Node.isArrowFunction(current) ||\n Node.isFunctionExpression(current)) &&\n // Ensure body exists and is a block for injection\n // Using explicit casting/checking to avoid \"undefined\" type error\n (() => {\n const body = (current as any).getBody?.();\n return body && Node.isBlock(body);\n })()\n ) {\n // Determine if it's a component or helper\n const isComp = isComponent(current);\n const injectionType = isComp ? 'hook' : 'function';\n\n // Check if we already decided on a type for this component\n const existing = componentsToInjectHook.get(current);\n if (!existing) {\n componentsToInjectHook.set(current, injectionType);\n } else if (existing === 'function' && injectionType === 'hook') {\n // Upgrade to hook if detected as component by another usage?\n // Actually, isComponent checks the definition, so it shouldn't change.\n // But strictness matters.\n componentsToInjectHook.set(current, 'hook');\n }\n\n break;\n }\n current = current.getParent();\n }\n\n const replaceText = (isJsx: boolean) => {\n const needsValue =\n !isJsx &&\n (packageName === 'react-intlayer' || packageName === 'next-intlayer');\n return needsValue ? `content.${key}.value` : `content.${key}`;\n };\n\n if (type === 'jsx-text' && Node.isJsxText(node)) {\n node.replaceWithText(`{${replaceText(true)}}`);\n } else if (type === 'jsx-attribute' && Node.isJsxAttribute(node)) {\n node.setInitializer(`{${replaceText(false)}}`);\n } else if (type === 'string-literal' && Node.isStringLiteral(node)) {\n node.replaceWithText(replaceText(false));\n }\n }\n\n let injectedUseIntlayer = false;\n let injectedGetIntlayer = false;\n\n // Inject hook/function in all affected components\n for (const [componentBody, injectionType] of componentsToInjectHook) {\n const body = (componentBody as any).getBody();\n if (Node.isBlock(body)) {\n const text = body.getText();\n const statement =\n injectionType === 'hook'\n ? `const content = useIntlayer(\"${componentKey}\");`\n : `const content = getIntlayer(\"${componentKey}\");`;\n\n // Check if already injected (naive check)\n if (\n !text.includes(`useIntlayer(\"${componentKey}\")`) &&\n !text.includes(`getIntlayer(\"${componentKey}\")`)\n ) {\n body.insertStatements(0, statement);\n }\n\n if (injectionType === 'hook') injectedUseIntlayer = true;\n if (injectionType === 'function') injectedGetIntlayer = true;\n }\n }\n\n // Insert Imports\n const importSource =\n packageName === 'next-intlayer'\n ? sourceFile.getText().includes('\"use client\"') ||\n sourceFile.getText().includes(\"'use client'\")\n ? 'next-intlayer'\n : 'next-intlayer/server'\n : packageName;\n\n const existingImport = sourceFile.getImportDeclaration(\n (d) => d.getModuleSpecifierValue() === importSource\n );\n\n const namedImports = new Set<string>();\n if (injectedUseIntlayer) namedImports.add('useIntlayer');\n if (injectedGetIntlayer) namedImports.add('getIntlayer');\n\n if (namedImports.size > 0) {\n if (!existingImport) {\n sourceFile.addImportDeclaration({\n namedImports: Array.from(namedImports),\n moduleSpecifier: importSource,\n });\n } else {\n const currentNamedImports = existingImport\n .getNamedImports()\n .map((n) => n.getName());\n for (const name of namedImports) {\n if (!currentNamedImports.includes(name)) {\n existingImport.addNamedImport(name);\n }\n }\n }\n }\n\n await sourceFile.save();\n};\n\ntype ExtractIntlayer = {\n configOptions?: GetConfigurationOptions;\n outputDir?: string;\n};\n\nexport type PackageName =\n | 'next-intlayer'\n | 'react-intlayer'\n | 'vue-intlayer'\n | 'preact-intlayer'\n | 'solid-intlayer'\n | 'angular-intlayer'\n | 'svelte-intlayer'\n | 'express-intlayer';\n\nexport const extractIntlayer = async (\n filePath: string,\n packageName: PackageName,\n options?: ExtractIntlayer,\n project?: Project\n) => {\n const configuration = getConfiguration(options?.configOptions);\n const { baseDir } = configuration.content;\n const appLogger = getAppLogger(configuration);\n\n // Use provided project or create new one (optimized)\n const _project =\n project ||\n new Project({\n skipAddingFilesFromTsConfig: true,\n });\n\n let sourceFile: SourceFile;\n try {\n sourceFile = _project.addSourceFileAtPath(filePath);\n } catch {\n // If file is already added, get it\n sourceFile = _project.getSourceFileOrThrow(filePath);\n }\n\n const baseName = extractDictionaryKey(filePath, sourceFile.getText());\n const componentKey = camelCaseToKebabCase(baseName);\n\n // 1. Extract content\n const { extractedContent, replacements } = extractContent(sourceFile);\n\n if (Object.keys(extractedContent).length === 0) {\n appLogger(`No extractable text found in ${baseName}`);\n // Cleanup if we created the project just for this file\n if (!project) {\n // _project.removeSourceFile(sourceFile); // Not strictly necessary if process exits, but good practice\n }\n return;\n }\n\n // 2. Write content declaration\n const contentFilePath = await writeContent(\n extractedContent,\n componentKey,\n filePath,\n configuration,\n options?.outputDir\n );\n const relativeContentFilePath = relative(\n configuration.content.baseDir,\n contentFilePath\n );\n\n appLogger(`Created content file: ${colorizePath(relativeContentFilePath)}`);\n\n // 3. Transform component\n await transformComponent(sourceFile, replacements, componentKey, packageName);\n\n const formatCommand = detectFormatCommand(configuration);\n\n if (formatCommand) {\n try {\n execSync(formatCommand.replace('{{file}}', filePath), {\n stdio: 'inherit',\n cwd: baseDir,\n });\n } catch (error) {\n console.error(error);\n }\n }\n\n const relativeFilePath = relative(baseDir, filePath);\n\n appLogger(`Updated component: ${colorizePath(relativeFilePath)}`);\n\n // Cleanup to free memory if we are processing many files and passed a persistent project?\n // If 'project' is passed, we probably want to keep it?\n // Actually, for a CLI command running once, memory growth is acceptable if not too huge.\n // But removing source file is safer if not needed anymore.\n if (project) {\n sourceFile.forget(); // Remove from project to save memory\n }\n};\n\nexport const transformFiles = async (\n filePaths: string[],\n packageName: PackageName,\n options?: ExtractIntlayer\n) => {\n const configuration = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n\n const project = new Project({\n skipAddingFilesFromTsConfig: true,\n });\n\n for (const filePath of filePaths) {\n try {\n await extractIntlayer(filePath, packageName, options, project);\n } catch (error) {\n appLogger(`Failed to transform ${filePath}: ${(error as Error).message}`);\n }\n }\n};\n"],"mappings":"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"}
@@ -23,10 +23,11 @@ const getContentDeclarationFileTemplate = async (key, format, fileParams = {}) =
23
23
  const camelCaseKey = (0, __intlayer_config.kebabCaseToCamelCase)(key);
24
24
  const nonCapitalizedCamelCaseKey = camelCaseKey.charAt(0).toLowerCase() + camelCaseKey.slice(1);
25
25
  const fileParamsString = Object.entries(fileParams).filter(([, value]) => value !== void 0).map(([key$1, value]) => {
26
- if (typeof value === "object") return `\n '${key$1}': ${JSON.stringify(value)},`;
27
- if (typeof value === "boolean" || typeof value === "number") return `\n '${key$1}': ${value},`;
28
- if (typeof value === "string") return `\n '${key$1}': '${value}',`;
29
- return `\n '${key$1}': ${value},`;
26
+ const formattedKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key$1) ? key$1 : JSON.stringify(key$1);
27
+ if (typeof value === "object") return `\n ${formattedKey}: ${JSON.stringify(value)},`;
28
+ if (typeof value === "boolean" || typeof value === "number") return `\n ${formattedKey}: ${value},`;
29
+ if (typeof value === "string") return `\n ${formattedKey}: ${JSON.stringify(value)},`;
30
+ return `\n ${formattedKey}: ${value},`;
30
31
  }).join("");
31
32
  return fileContent.replace("{{key}}", key).replaceAll("{{name}}", nonCapitalizedCamelCaseKey).replace("{{fileParams}}", fileParamsString);
32
33
  };
@@ -1 +1 @@
1
- {"version":3,"file":"getContentDeclarationFileTemplate.cjs","names":["fileTemplate: string","readAsset","key"],"sources":["../../../src/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.ts"],"sourcesContent":["import { readAsset } from 'utils:asset';\nimport { kebabCaseToCamelCase } from '@intlayer/config';\nimport type { Format } from '../utils/getFormatFromExtension';\n\nexport const getContentDeclarationFileTemplate = async (\n key: string,\n format: Format,\n fileParams: Record<string, any> = {}\n) => {\n let fileTemplate: string;\n\n switch (format) {\n case 'ts':\n fileTemplate = './tsTemplate.txt';\n break;\n case 'cjs':\n fileTemplate = './cjsTemplate.txt';\n break;\n case 'json':\n fileTemplate = './jsonTemplate.txt';\n break;\n default:\n fileTemplate = './esmTemplate.txt';\n break;\n }\n\n const fileContent = readAsset(fileTemplate);\n const camelCaseKey = kebabCaseToCamelCase(key);\n const nonCapitalizedCamelCaseKey =\n camelCaseKey.charAt(0).toLowerCase() + camelCaseKey.slice(1);\n\n const fileParamsString = Object.entries(fileParams)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => {\n if (typeof value === 'object') {\n return `\\n '${key}': ${JSON.stringify(value)},`;\n }\n\n if (typeof value === 'boolean' || typeof value === 'number') {\n return `\\n '${key}': ${value},`;\n }\n\n if (typeof value === 'string') {\n return `\\n '${key}': '${value}',`;\n }\n\n return `\\n '${key}': ${value},`;\n })\n .join('');\n\n return fileContent\n .replace('{{key}}', key)\n .replaceAll('{{name}}', nonCapitalizedCamelCaseKey)\n .replace('{{fileParams}}', fileParamsString);\n};\n"],"mappings":";;;;;AAIA,MAAa,oCAAoC,OAC/C,KACA,QACA,aAAkC,EAAE,KACjC;CACH,IAAIA;AAEJ,SAAQ,QAAR;EACE,KAAK;AACH,kBAAe;AACf;EACF,KAAK;AACH,kBAAe;AACf;EACF,KAAK;AACH,kBAAe;AACf;EACF;AACE,kBAAe;AACf;;CAGJ,MAAM,cAAcC,+BAAU,aAAa;CAC3C,MAAM,2DAAoC,IAAI;CAC9C,MAAM,6BACJ,aAAa,OAAO,EAAE,CAAC,aAAa,GAAG,aAAa,MAAM,EAAE;CAE9D,MAAM,mBAAmB,OAAO,QAAQ,WAAW,CAChD,QAAQ,GAAG,WAAW,UAAU,OAAU,CAC1C,KAAK,CAACC,OAAK,WAAW;AACrB,MAAI,OAAO,UAAU,SACnB,QAAO,QAAQA,MAAI,KAAK,KAAK,UAAU,MAAM,CAAC;AAGhD,MAAI,OAAO,UAAU,aAAa,OAAO,UAAU,SACjD,QAAO,QAAQA,MAAI,KAAK,MAAM;AAGhC,MAAI,OAAO,UAAU,SACnB,QAAO,QAAQA,MAAI,MAAM,MAAM;AAGjC,SAAO,QAAQA,MAAI,KAAK,MAAM;GAC9B,CACD,KAAK,GAAG;AAEX,QAAO,YACJ,QAAQ,WAAW,IAAI,CACvB,WAAW,YAAY,2BAA2B,CAClD,QAAQ,kBAAkB,iBAAiB"}
1
+ {"version":3,"file":"getContentDeclarationFileTemplate.cjs","names":["fileTemplate: string","readAsset","key"],"sources":["../../../src/getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.ts"],"sourcesContent":["import { readAsset } from 'utils:asset';\nimport { kebabCaseToCamelCase } from '@intlayer/config';\nimport type { Format } from '../utils/getFormatFromExtension';\n\nexport const getContentDeclarationFileTemplate = async (\n key: string,\n format: Format,\n fileParams: Record<string, any> = {}\n) => {\n let fileTemplate: string;\n\n switch (format) {\n case 'ts':\n fileTemplate = './tsTemplate.txt';\n break;\n case 'cjs':\n fileTemplate = './cjsTemplate.txt';\n break;\n case 'json':\n fileTemplate = './jsonTemplate.txt';\n break;\n default:\n fileTemplate = './esmTemplate.txt';\n break;\n }\n\n const fileContent = readAsset(fileTemplate);\n const camelCaseKey = kebabCaseToCamelCase(key);\n const nonCapitalizedCamelCaseKey =\n camelCaseKey.charAt(0).toLowerCase() + camelCaseKey.slice(1);\n\n const fileParamsString = Object.entries(fileParams)\n .filter(([, value]) => value !== undefined)\n .map(([key, value]) => {\n const formattedKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)\n ? key\n : JSON.stringify(key);\n\n if (typeof value === 'object') {\n return `\\n ${formattedKey}: ${JSON.stringify(value)},`;\n }\n\n if (typeof value === 'boolean' || typeof value === 'number') {\n return `\\n ${formattedKey}: ${value},`;\n }\n\n if (typeof value === 'string') {\n return `\\n ${formattedKey}: ${JSON.stringify(value)},`;\n }\n\n return `\\n ${formattedKey}: ${value},`;\n })\n .join('');\n\n return fileContent\n .replace('{{key}}', key)\n .replaceAll('{{name}}', nonCapitalizedCamelCaseKey)\n .replace('{{fileParams}}', fileParamsString);\n};\n"],"mappings":";;;;;AAIA,MAAa,oCAAoC,OAC/C,KACA,QACA,aAAkC,EAAE,KACjC;CACH,IAAIA;AAEJ,SAAQ,QAAR;EACE,KAAK;AACH,kBAAe;AACf;EACF,KAAK;AACH,kBAAe;AACf;EACF,KAAK;AACH,kBAAe;AACf;EACF;AACE,kBAAe;AACf;;CAGJ,MAAM,cAAcC,+BAAU,aAAa;CAC3C,MAAM,2DAAoC,IAAI;CAC9C,MAAM,6BACJ,aAAa,OAAO,EAAE,CAAC,aAAa,GAAG,aAAa,MAAM,EAAE;CAE9D,MAAM,mBAAmB,OAAO,QAAQ,WAAW,CAChD,QAAQ,GAAG,WAAW,UAAU,OAAU,CAC1C,KAAK,CAACC,OAAK,WAAW;EACrB,MAAM,eAAe,6BAA6B,KAAKA,MAAI,GACvDA,QACA,KAAK,UAAUA,MAAI;AAEvB,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,aAAa,IAAI,KAAK,UAAU,MAAM,CAAC;AAGvD,MAAI,OAAO,UAAU,aAAa,OAAO,UAAU,SACjD,QAAO,OAAO,aAAa,IAAI,MAAM;AAGvC,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,aAAa,IAAI,KAAK,UAAU,MAAM,CAAC;AAGvD,SAAO,OAAO,aAAa,IAAI,MAAM;GACrC,CACD,KAAK,GAAG;AAEX,QAAO,YACJ,QAAQ,WAAW,IAAI,CACvB,WAAW,YAAY,2BAA2B,CAClD,QAAQ,kBAAkB,iBAAiB"}
@@ -22,7 +22,14 @@ const require_handleAdditionalContentDeclarationFile = require('./handleAddition
22
22
  const require_handleContentDeclarationFileChange = require('./handleContentDeclarationFileChange.cjs');
23
23
  const require_listDictionariesPath = require('./listDictionariesPath.cjs');
24
24
  const require_handleUnlinkedContentDeclarationFile = require('./handleUnlinkedContentDeclarationFile.cjs');
25
+ const require_writeContentDeclaration_detectExportedComponentName = require('./writeContentDeclaration/detectExportedComponentName.cjs');
26
+ const require_writeContentDeclaration_transformJSFile = require('./writeContentDeclaration/transformJSFile.cjs');
27
+ const require_utils_getFormatFromExtension = require('./utils/getFormatFromExtension.cjs');
25
28
  const require_getContentDeclarationFileTemplate_getContentDeclarationFileTemplate = require('./getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs');
29
+ const require_writeContentDeclaration_detectFormatCommand = require('./writeContentDeclaration/detectFormatCommand.cjs');
30
+ const require_writeContentDeclaration_writeJSFile = require('./writeContentDeclaration/writeJSFile.cjs');
31
+ const require_writeContentDeclaration_writeContentDeclaration = require('./writeContentDeclaration/writeContentDeclaration.cjs');
32
+ const require_compiler_index = require('./compiler/index.cjs');
26
33
  const require_listGitFiles = require('./listGitFiles.cjs');
27
34
  const require_utils_sortAlphabetically = require('./utils/sortAlphabetically.cjs');
28
35
  const require_loadDictionaries_loadRemoteDictionaries = require('./loadDictionaries/loadRemoteDictionaries.cjs');
@@ -33,17 +40,11 @@ const require_reduceDictionaryContent_reduceDictionaryContent = require('./reduc
33
40
  const require_utils_splitTextByLine = require('./utils/splitTextByLine.cjs');
34
41
  const require_utils_getChunk = require('./utils/getChunk.cjs');
35
42
  const require_utils_chunkJSON = require('./utils/chunkJSON.cjs');
36
- const require_utils_getFormatFromExtension = require('./utils/getFormatFromExtension.cjs');
37
43
  const require_utils_parallelizeGlobal = require('./utils/parallelizeGlobal.cjs');
38
44
  const require_utils_reduceObjectFormat = require('./utils/reduceObjectFormat.cjs');
39
45
  const require_utils_runParallel_index = require('./utils/runParallel/index.cjs');
40
46
  const require_utils_verifyIdenticObjectFormat = require('./utils/verifyIdenticObjectFormat.cjs');
41
47
  const require_watcher = require('./watcher.cjs');
42
- const require_writeContentDeclaration_detectExportedComponentName = require('./writeContentDeclaration/detectExportedComponentName.cjs');
43
- const require_writeContentDeclaration_transformJSFile = require('./writeContentDeclaration/transformJSFile.cjs');
44
- const require_writeContentDeclaration_detectFormatCommand = require('./writeContentDeclaration/detectFormatCommand.cjs');
45
- const require_writeContentDeclaration_writeJSFile = require('./writeContentDeclaration/writeJSFile.cjs');
46
- const require_writeContentDeclaration_writeContentDeclaration = require('./writeContentDeclaration/writeContentDeclaration.cjs');
47
48
 
48
49
  exports.assembleJSON = require_utils_chunkJSON.assembleJSON;
49
50
  exports.buildAndWatchIntlayer = require_watcher.buildAndWatchIntlayer;
@@ -55,6 +56,8 @@ exports.createModuleAugmentation = require_createType_createModuleAugmentation.c
55
56
  exports.createTypes = require_createType_createType.createTypes;
56
57
  exports.detectExportedComponentName = require_writeContentDeclaration_detectExportedComponentName.detectExportedComponentName;
57
58
  exports.detectFormatCommand = require_writeContentDeclaration_detectFormatCommand.detectFormatCommand;
59
+ exports.extractContent = require_compiler_index.extractContent;
60
+ exports.extractIntlayer = require_compiler_index.extractIntlayer;
58
61
  exports.fetchDistantDictionaries = require_fetchDistantDictionaries.fetchDistantDictionaries;
59
62
  exports.formatLocale = require_utils_formatter.formatLocale;
60
63
  exports.formatPath = require_utils_formatter.formatPath;
@@ -94,8 +97,11 @@ exports.runOnce = require_utils_runOnce.runOnce;
94
97
  exports.runParallel = require_utils_runParallel_index.runParallel;
95
98
  exports.sortAlphabetically = require_utils_sortAlphabetically.sortAlphabetically;
96
99
  exports.splitTextByLines = require_utils_splitTextByLine.splitTextByLines;
100
+ exports.transformComponent = require_compiler_index.transformComponent;
101
+ exports.transformFiles = require_compiler_index.transformFiles;
97
102
  exports.transformJSFile = require_writeContentDeclaration_transformJSFile.transformJSFile;
98
103
  exports.verifyIdenticObjectFormat = require_utils_verifyIdenticObjectFormat.verifyIdenticObjectFormat;
99
104
  exports.watch = require_watcher.watch;
105
+ exports.writeContent = require_compiler_index.writeContent;
100
106
  exports.writeContentDeclaration = require_writeContentDeclaration_writeContentDeclaration.writeContentDeclaration;
101
107
  exports.writeJSFile = require_writeContentDeclaration_writeJSFile.writeJSFile;
@@ -1570,7 +1570,7 @@ const serializeMetadataValue = (value) => {
1570
1570
  * Updates a single property in the root object if the value has changed
1571
1571
  */
1572
1572
  const updateMetadataProperty = (rootObject, propertyName, value) => {
1573
- const property = rootObject.getProperty(propertyName);
1573
+ const property = rootObject.getProperty(propertyName) || rootObject.getProperty(`'${propertyName}'`) || rootObject.getProperty(`"${propertyName}"`);
1574
1574
  const serializedValue = serializeMetadataValue(value);
1575
1575
  if (property && ts_morph.Node.isPropertyAssignment(property)) {
1576
1576
  if (property.getInitializer()?.getText() !== serializedValue) {