@zohodesk/react-cli 1.1.29-exp.1 → 1.1.29-exp.2

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 (221) hide show
  1. package/lib/babel/babel-option-utils/babel-preset-react-option.js +0 -3
  2. package/lib/babel/cmjs-plugins-presets.js +1 -8
  3. package/lib/babel/es-plugins-presets.js +1 -8
  4. package/lib/common/buildEs.js +1 -0
  5. package/lib/common/getEntries.js +2 -13
  6. package/lib/common/getPublicPathConfig.js +0 -6
  7. package/lib/common/index.js +1 -6
  8. package/lib/common/runPreProcess.js +6 -15
  9. package/lib/common/splitChunks.js +2 -21
  10. package/lib/common/sslcertUpdater.js +7 -18
  11. package/lib/common/templateParameters.js +0 -2
  12. package/lib/common/testPattern.js +10 -21
  13. package/lib/common/valueReplacer.js +1 -16
  14. package/lib/configs/jest.config.js +1 -10
  15. package/lib/configs/libAlias.js +8 -14
  16. package/lib/configs/resolvers.js +4 -14
  17. package/lib/configs/webpack.component.umd.config.js +1 -6
  18. package/lib/configs/webpack.css.umd.config.js +6 -14
  19. package/lib/configs/webpack.dev.config.js +1 -14
  20. package/lib/configs/webpack.docs.config.js +1 -9
  21. package/lib/configs/webpack.impact.config.js +1 -8
  22. package/lib/configs/webpack.prod.config.js +4 -17
  23. package/lib/constants.js +9 -18
  24. package/lib/deprecationLogger.js +0 -7
  25. package/lib/hooks/docsProptypeHook.js +4 -8
  26. package/lib/jest/commitedFilesResult.js +4 -46
  27. package/lib/jest/coverageCollector.js +1 -12
  28. package/lib/jest/jsonMaker.js +0 -6
  29. package/lib/jest/preProcessors/cssPreprocessor.js +1 -9
  30. package/lib/jest/preProcessors/jsPreprocessor.js +1 -6
  31. package/lib/jest/preProcessors/otherFilesPreprocessor.js +1 -4
  32. package/lib/jest/result.js +1 -23
  33. package/lib/jest/run.js +7 -18
  34. package/lib/jest/setup.js +8 -60
  35. package/lib/loaderUtils/configsAssetsLoaders.js +2 -12
  36. package/lib/loaderUtils/getCSSLoaders.js +10 -22
  37. package/lib/loaderUtils/getDevJsLoaders.js +4 -13
  38. package/lib/loaderUtils/index.js +1 -4
  39. package/lib/loaderUtils/tests/windowsModification.test.js +0 -1
  40. package/lib/loaderUtils/windowsModification.js +2 -3
  41. package/lib/loaders/__test__/markdownLoader.spec.js +0 -1
  42. package/lib/loaders/composeLoader.js +13 -37
  43. package/lib/loaders/docsLoader.js +1 -12
  44. package/lib/loaders/docsPropsLoader.js +4 -8
  45. package/lib/loaders/enhancedReactLiveConverter.js +2 -23
  46. package/lib/loaders/fileBountryLoader.js +1 -3
  47. package/lib/loaders/fileLoader.js +12 -23
  48. package/lib/loaders/markdownLoader.js +14 -19
  49. package/lib/loaders/reactLiveConvertor.js +5 -15
  50. package/lib/loaders/scriptInstrumentLoader.js +7 -16
  51. package/lib/loaders/selectorMappingLoader.js +7 -26
  52. package/lib/loaders/workerLoader.js +9 -24
  53. package/lib/logger.js +0 -4
  54. package/lib/middlewares/HMRMiddleware.js +13 -27
  55. package/lib/middlewares/SSTMiddleware.js +1 -5
  56. package/lib/pluginUtils/configHtmlWebpackPlugins.js +1 -24
  57. package/lib/pluginUtils/getDevPlugins.js +9 -42
  58. package/lib/pluginUtils/getDocsPlugins.js +3 -13
  59. package/lib/pluginUtils/getLibraryImactPlugins.js +5 -6
  60. package/lib/pluginUtils/getLibraryPlugins.js +2 -8
  61. package/lib/pluginUtils/getProdPlugins.js +8 -47
  62. package/lib/pluginUtils/getServerPlugins.js +2 -8
  63. package/lib/pluginUtils/getUMDCSSPlugins.js +2 -10
  64. package/lib/pluginUtils/getUMDComponentPlugins.js +2 -10
  65. package/lib/pluginUtils/index.js +1 -9
  66. package/lib/plugins/CdnChangePlugin.js +2 -18
  67. package/lib/plugins/CleanupStatsPlugin.js +0 -5
  68. package/lib/plugins/CssOrderControlPlugin.js +3 -6
  69. package/lib/plugins/CustomAttributePlugin.js +14 -19
  70. package/lib/plugins/CustomScriptLoadingStrategyPlugin.js +3 -23
  71. package/lib/plugins/EFCPlugin.js +20 -34
  72. package/lib/plugins/EFCTemplatePlugin.js +19 -30
  73. package/lib/plugins/EfcResourceCleanupPlugin.js +0 -3
  74. package/lib/plugins/EventsHandlingPlugin.js +2 -4
  75. package/lib/plugins/I18NInjectIntoIndexPlugin.js +11 -37
  76. package/lib/plugins/I18nSplitPlugin/I18nDebugPlugin.js +10 -15
  77. package/lib/plugins/I18nSplitPlugin/I18nDependency.js +4 -10
  78. package/lib/plugins/I18nSplitPlugin/I18nDownlodLogic.js +12 -25
  79. package/lib/plugins/I18nSplitPlugin/I18nFilesEmitter.js +55 -133
  80. package/lib/plugins/I18nSplitPlugin/I18nKeysIdentifer.js +12 -23
  81. package/lib/plugins/I18nSplitPlugin/index.js +13 -24
  82. package/lib/plugins/I18nSplitPlugin/utils/applyMetaManifest.js +64 -58
  83. package/lib/plugins/I18nSplitPlugin/utils/collectI18nKeys.js +2 -12
  84. package/lib/plugins/I18nSplitPlugin/utils/createMetaManifest.js +10 -29
  85. package/lib/plugins/I18nSplitPlugin/utils/createRegularManifest.js +8 -19
  86. package/lib/plugins/I18nSplitPlugin/utils/getI18nFileUrlPathTemplate.js +0 -1
  87. package/lib/plugins/I18nSplitPlugin/utils/getI18nKeysFormModules.js +0 -5
  88. package/lib/plugins/I18nSplitPlugin/utils/hashUtils.js +1 -8
  89. package/lib/plugins/I18nSplitPlugin/utils/index.js +0 -4
  90. package/lib/plugins/I18nSplitPlugin/utils/propertiesUtils.js +0 -20
  91. package/lib/plugins/I18nSplitPlugin/utils/unicodeConversion.js +0 -1
  92. package/lib/plugins/ManifestPlugin.js +1 -18
  93. package/lib/plugins/MinifyPlugin.js +1 -10
  94. package/lib/plugins/ModuleStatsPlugin.js +1 -24
  95. package/lib/plugins/OptimizeJSPlugin.js +2 -10
  96. package/lib/plugins/PublicPathCallbackPlugin.js +1 -12
  97. package/lib/plugins/PublicPathChangePlugin.js +6 -39
  98. package/lib/plugins/ReportGeneratePlugin.js +5 -32
  99. package/lib/plugins/RequireVariablePublicPlugin.js +1 -8
  100. package/lib/plugins/ResourceHintsPlugin.js +4 -13
  101. package/lib/plugins/RtlSplitPlugin/OverwriteCssPathForRTL.js +12 -17
  102. package/lib/plugins/RtlSplitPlugin/RtlCssPlugin.js +10 -17
  103. package/lib/plugins/RtlSplitPlugin/replaceCssDirTemplate.js +2 -5
  104. package/lib/plugins/ScriptInstrumentPlugin.js +1 -8
  105. package/lib/plugins/SelectorPlugin.js +6 -32
  106. package/lib/plugins/ServiceWorkerPlugin.js +5 -22
  107. package/lib/plugins/ShadowDOMSupportPlugin.js +4 -41
  108. package/lib/plugins/SourceMapHookPlugin.js +2 -12
  109. package/lib/plugins/StatsPlugin.js +0 -14
  110. package/lib/plugins/TPHashMappingPlugin.js +3 -18
  111. package/lib/plugins/UnusedFilesFindPlugin.js +4 -39
  112. package/lib/plugins/VariableConversionCollector.js +15 -42
  113. package/lib/plugins/index.js +1 -20
  114. package/lib/plugins/libraryImpactPlugin.js +1 -33
  115. package/lib/plugins/newi18nsplitplugin/18nPlugin1.js +306 -0
  116. package/lib/plugins/newi18nsplitplugin/18nPlugin2.js +363 -0
  117. package/lib/plugins/newi18nsplitplugin/18nPlugin3.js +694 -0
  118. package/lib/plugins/newi18nsplitplugin/18nPlugin_hashed.js +1258 -0
  119. package/lib/plugins/newi18nsplitplugin/18nPlugin_working.js +542 -0
  120. package/lib/plugins/newi18nsplitplugin/18nplugin.js +974 -0
  121. package/lib/plugins/newi18nsplitplugin/ChunkManager.js +131 -0
  122. package/lib/plugins/newi18nsplitplugin/GenerateModuleIdToKeysMapPlugin.js +59 -0
  123. package/lib/plugins/newi18nsplitplugin/I18nDiffPlugin.js +262 -0
  124. package/lib/plugins/newi18nsplitplugin/I18nDownloadLogic.js +166 -0
  125. package/lib/plugins/newi18nsplitplugin/I18nPropertiesPlugin.js +111 -0
  126. package/lib/plugins/newi18nsplitplugin/KeyCollector.js +163 -0
  127. package/lib/plugins/newi18nsplitplugin/ManifestGenerator.js +88 -0
  128. package/lib/plugins/newi18nsplitplugin/UnicodeConversionPlugin.js +101 -0
  129. package/lib/plugins/newi18nsplitplugin/constants.js +162 -0
  130. package/lib/plugins/newi18nsplitplugin/utils/I18nKeyHasher.js +78 -0
  131. package/lib/plugins/newi18nsplitplugin/utils/getJsResourceKeys.js +22 -0
  132. package/lib/plugins/newi18nsplitplugin/utils/i18nChunkUtils.js +18 -0
  133. package/lib/plugins/newi18nsplitplugin/utils/manifestGenerator.js +580 -0
  134. package/lib/plugins/newi18nsplitplugin/utils/propertiesUtils.js +54 -0
  135. package/lib/plugins/utils/classHandling.js +0 -6
  136. package/lib/plugins/utils/fileHandling.js +6 -15
  137. package/lib/plugins/utils/tests/fileHandling.test.js +0 -4
  138. package/lib/plugins/variableConvertorUtils.js +14 -29
  139. package/lib/plugins/webpackwatchrunplugin.js +0 -5
  140. package/lib/postcss-plugins/EmptyPlugin.js +3 -4
  141. package/lib/postcss-plugins/ExcludePlugin.js +1 -5
  142. package/lib/postcss-plugins/IncludePlugin.js +1 -5
  143. package/lib/postcss-plugins/RTLSplitPlugin.js +14 -27
  144. package/lib/postcss-plugins/SelectorReplace.js +1 -16
  145. package/lib/postcss-plugins/ValueReplacer.js +7 -6
  146. package/lib/postcss-plugins/__test__/hoverActivePlugin.spec.js +0 -3
  147. package/lib/postcss-plugins/__test__/selectorReplace.test.js +6 -3
  148. package/lib/postcss-plugins/__test__/valueReplacer.spec.js +2 -5
  149. package/lib/postcss-plugins/hoverActivePlugin.js +31 -67
  150. package/lib/postcss-plugins/variableModificationPlugin/ErrorHandler.js +0 -7
  151. package/lib/postcss-plugins/variableModificationPlugin/index.js +28 -49
  152. package/lib/schemas/index.js +3 -9
  153. package/lib/servers/clusterHubServer.js +1 -11
  154. package/lib/servers/devBuild.js +14 -26
  155. package/lib/servers/docsServer.js +1 -3
  156. package/lib/servers/docsServerCore.js +1 -22
  157. package/lib/servers/getCliPath.js +0 -9
  158. package/lib/servers/helpServer.js +1 -6
  159. package/lib/servers/httpsOptions.js +2 -8
  160. package/lib/servers/impactServer.js +3 -35
  161. package/lib/servers/mockserver.js +1 -10
  162. package/lib/servers/nowatchserver.js +12 -37
  163. package/lib/servers/requireLocalOrGlobal.js +6 -17
  164. package/lib/servers/scrServer.js +14 -21
  165. package/lib/servers/server.js +6 -36
  166. package/lib/servers/ssServer.js +1 -17
  167. package/lib/templates/CoverageScriptTemplate.js +0 -14
  168. package/lib/templates/WMSTemplate.js +7 -13
  169. package/lib/templates/linterConstant.js +2 -4
  170. package/lib/utils/babelPresets.js +3 -7
  171. package/lib/utils/clean.js +3 -9
  172. package/lib/utils/copy.js +1 -7
  173. package/lib/utils/copyTimezones.js +1 -9
  174. package/lib/utils/createEventStream.js +1 -6
  175. package/lib/utils/cssClassNameGenerate.js +10 -30
  176. package/lib/utils/cssURLReplacer.js +1 -22
  177. package/lib/utils/dependencyPostPublish.js +1 -10
  178. package/lib/utils/deprecationSupport.js +7 -32
  179. package/lib/utils/fileUtils.js +1 -28
  180. package/lib/utils/folderIterator.js +2 -13
  181. package/lib/utils/getComponents.js +0 -21
  182. package/lib/utils/getCurrentBranch.js +0 -5
  183. package/lib/utils/getDependenciesImpactList.js +1 -22
  184. package/lib/utils/getFileType.js +2 -10
  185. package/lib/utils/getHash.js +1 -8
  186. package/lib/utils/getIp.js +0 -2
  187. package/lib/utils/getOptions.js +16 -53
  188. package/lib/utils/getServerURL.js +1 -10
  189. package/lib/utils/index.js +4 -51
  190. package/lib/utils/init.js +0 -1
  191. package/lib/utils/initPreCommitHook.js +7 -30
  192. package/lib/utils/jsonHelper.js +3 -22
  193. package/lib/utils/libraryImpactConfig.js +2 -5
  194. package/lib/utils/lint/addScripts.js +2 -5
  195. package/lib/utils/lint/checkExistingConfig.js +3 -12
  196. package/lib/utils/lint/copyConfigs.js +0 -3
  197. package/lib/utils/lint/index.js +0 -9
  198. package/lib/utils/lint/lintScripts.js +0 -1
  199. package/lib/utils/lint/lintSetup.js +3 -4
  200. package/lib/utils/lint/lintStagedPreCommitHook.js +0 -1
  201. package/lib/utils/lint/question.js +0 -7
  202. package/lib/utils/lintReporter.js +0 -20
  203. package/lib/utils/log.js +0 -1
  204. package/lib/utils/mailSender.js +1 -8
  205. package/lib/utils/object-manipulation.js +1 -17
  206. package/lib/utils/pullOrigin.js +0 -4
  207. package/lib/utils/reinstallDependencies.js +1 -29
  208. package/lib/utils/removeAttributes.js +1 -8
  209. package/lib/utils/repoClone.js +3 -28
  210. package/lib/utils/request.js +0 -12
  211. package/lib/utils/rtl.js +5 -17
  212. package/lib/utils/selectorReplacer.js +10 -16
  213. package/lib/utils/setEnvVariables.js +0 -2
  214. package/lib/utils/ssTestHack.js +1 -11
  215. package/lib/utils/switchBranch.js +0 -5
  216. package/lib/utils/typeCheck.js +0 -1
  217. package/lib/utils/urlConcat.js +0 -4
  218. package/lib/utils/useExitCleanup.js +9 -10
  219. package/lib/utils/variableConverter.js +22 -31
  220. package/{npm-shrinkwrap.json → package-lock.json} +2098 -1999
  221. package/package.json +1 -1
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+
3
+ // I18nPropertiesPlugin.js
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ class I18nPropertiesPlugin {
7
+ constructor(options = {}) {
8
+ // Default options
9
+ this.options = Object.assign({
10
+ propertiesDir: '',
11
+ // Directory containing .properties files
12
+ outputDir: 'i18n',
13
+ // Output directory in the build output
14
+ outputFormat: 'json',
15
+ // Output format: 'json' or 'js'
16
+ encoding: 'utf8' // File encoding
17
+ }, options);
18
+ }
19
+ apply(compiler) {
20
+ compiler.hooks.thisCompilation.tap('I18nPropertiesPlugin', compilation => {
21
+ compilation.hooks.processAssets.tapAsync({
22
+ name: 'I18nPropertiesPlugin',
23
+ stage: compilation.constructor.PROCESS_ASSETS_STAGE_ADDITIONS
24
+ }, (assets, callback) => {
25
+ this.processPropertiesFiles(compilation).then(() => callback()).catch(error => callback(error));
26
+ });
27
+ });
28
+ }
29
+ async processPropertiesFiles(compilation) {
30
+ const propertiesDir = path.resolve(this.options.propertiesDir);
31
+ const files = await this.getPropertiesFiles(propertiesDir);
32
+ for (const file of files) {
33
+ const content = fs.readFileSync(file, this.options.encoding);
34
+ const transformed = this.transformProperties(content);
35
+ const relativePath = path.relative(propertiesDir, file);
36
+ const outputFileName = this.getOutputFileName(relativePath);
37
+ const outputContent = this.getOutputContent(transformed); // Emit the file into the Webpack output
38
+
39
+ compilation.emitAsset(outputFileName, {
40
+ source: () => outputContent,
41
+ size: () => outputContent.length
42
+ });
43
+ }
44
+ }
45
+ async getPropertiesFiles(dir) {
46
+ const entries = fs.readdirSync(dir, {
47
+ withFileTypes: true
48
+ });
49
+ const files = [];
50
+ for (const entry of entries) {
51
+ const fullPath = path.join(dir, entry.name);
52
+ if (entry.isDirectory()) {
53
+ files.push(...(await this.getPropertiesFiles(fullPath)));
54
+ } else if (entry.isFile() && entry.name.endsWith('.properties')) {
55
+ files.push(fullPath);
56
+ }
57
+ }
58
+ return files;
59
+ }
60
+ transformProperties(content) {
61
+ const properties = this.parseProperties(content);
62
+ const transformed = {};
63
+ for (const [key, value] of Object.entries(properties)) {
64
+ transformed[key] = this.convertUnicodeToNative(value);
65
+ }
66
+ return transformed;
67
+ }
68
+ parseProperties(content) {
69
+ const result = {};
70
+ const lines = content.split(/\r?\n/);
71
+ for (let line of lines) {
72
+ line = line.trim();
73
+ if (line && !line.startsWith('#')) {
74
+ const [key, ...valueParts] = line.split('=');
75
+ if (key && valueParts.length > 0) {
76
+ const value = valueParts.join('=').trim();
77
+ result[key.trim()] = value;
78
+ }
79
+ }
80
+ }
81
+ return result;
82
+ }
83
+ convertUnicodeToNative(str) {
84
+ return str.replace(/\\u([0-9a-fA-F]{4})/g, (match, hex) => {
85
+ try {
86
+ return String.fromCharCode(parseInt(hex, 16));
87
+ } catch (err) {
88
+ return match;
89
+ }
90
+ });
91
+ }
92
+ getOutputFileName(relativePath) {
93
+ const ext = path.extname(relativePath);
94
+ const baseName = path.basename(relativePath, ext);
95
+ const dirName = path.dirname(relativePath);
96
+ let outputFileName = `${baseName}.${this.options.outputFormat}`;
97
+ if (dirName && dirName !== '.') {
98
+ outputFileName = path.join(dirName, outputFileName);
99
+ }
100
+ return path.join(this.options.outputDir, outputFileName);
101
+ }
102
+ getOutputContent(transformed) {
103
+ if (this.options.outputFormat === 'json') {
104
+ return JSON.stringify(transformed, null, 2);
105
+ } else if (this.options.outputFormat === 'js') {
106
+ return `module.exports = ${JSON.stringify(transformed, null, 2)};`;
107
+ }
108
+ throw new Error(`Unsupported output format: ${this.options.outputFormat}`);
109
+ }
110
+ }
111
+ module.exports = I18nPropertiesPlugin;
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const crypto = require('crypto');
6
+ const {
7
+ walk
8
+ } = require('estree-walker');
9
+ const {
10
+ RawSource
11
+ } = require('webpack-sources');
12
+ const parser = require('@babel/parser');
13
+ const generate = require('@babel/generator').default;
14
+ const pluginName = 'I18nKeyHashPlugin';
15
+ class I18nKeyHashPlugin {
16
+ constructor(options = {}) {
17
+ const {
18
+ jsResourcePath
19
+ } = options;
20
+ if (!jsResourcePath) {
21
+ throw new Error('jsResourcePath is required');
22
+ }
23
+ this.jsResourcePath = jsResourcePath;
24
+ this.keyToHashMap = new Map();
25
+ this.processedFiles = new WeakSet();
26
+ this.preserveStringKeys = new Set(['Delete',
27
+ // Common UI strings that shouldn't be hashed
28
+ 'Cancel', 'Save', 'Close']);
29
+ }
30
+ hashKey(key) {
31
+ // Don't hash preserved strings
32
+ if (this.preserveStringKeys.has(key)) {
33
+ return key;
34
+ }
35
+ if (this.keyToHashMap.has(key)) {
36
+ return this.keyToHashMap.get(key);
37
+ }
38
+ const hash = crypto.createHash('md5').update(key).digest('hex').substring(0, 7);
39
+ this.keyToHashMap.set(key, hash);
40
+ return hash;
41
+ }
42
+ loadI18nKeys() {
43
+ try {
44
+ const content = fs.readFileSync(this.jsResourcePath, 'utf8');
45
+ const i18nObj = {};
46
+ content.split(/\r?\n/).forEach(line => {
47
+ const trimmedLine = line.trim();
48
+ if (!trimmedLine || trimmedLine.startsWith('#')) return;
49
+ const ind = trimmedLine.indexOf('=');
50
+ if (ind <= 0) return;
51
+ const key = trimmedLine.slice(0, ind).trim();
52
+ const value = trimmedLine.slice(ind + 1).trim();
53
+ if (key && value) {
54
+ i18nObj[key] = value; // Pre-generate hash
55
+
56
+ this.hashKey(key);
57
+ }
58
+ });
59
+ return i18nObj;
60
+ } catch (err) {
61
+ return {};
62
+ }
63
+ }
64
+ safeGenerateCode(ast) {
65
+ try {
66
+ const result = generate(ast, {
67
+ retainLines: true,
68
+ compact: false,
69
+ concise: false,
70
+ quotes: 'single',
71
+ jsonCompatibleStrings: true
72
+ });
73
+ return result.code;
74
+ } catch (err) {
75
+ throw new Error(`Code generation failed: ${err.message}`);
76
+ }
77
+ }
78
+ processSafeStringLiteral(node, hash) {
79
+ // Handle template literals more carefully
80
+ if (node.type === 'TemplateLiteral') {
81
+ return; // Skip template literals for safety
82
+ } // Handle regular string literals
83
+
84
+ if ((node.type === 'StringLiteral' || node.type === 'Literal') && typeof node.value === 'string') {
85
+ node.value = hash;
86
+ node.raw = `'${hash}'`;
87
+ if (node.extra) {
88
+ node.extra.raw = `'${hash}'`;
89
+ node.extra.rawValue = hash;
90
+ }
91
+ }
92
+ }
93
+ processAST(ast, i18nKeys) {
94
+ let modified = false;
95
+ try {
96
+ walk(ast, {
97
+ enter: node => {
98
+ // Handle string literals in JSX attributes
99
+ if ((node.type === 'StringLiteral' || node.type === 'Literal') && typeof node.value === 'string' && i18nKeys[node.value]) {
100
+ const hash = this.hashKey(node.value);
101
+ this.processSafeStringLiteral(node, hash);
102
+ modified = true;
103
+ } // Handle JSXText differently
104
+
105
+ if (node.type === 'JSXText' && i18nKeys[node.value.trim()]) {
106
+ const key = node.value.trim();
107
+ const hash = this.hashKey(key);
108
+ node.value = hash;
109
+ modified = true;
110
+ }
111
+ }
112
+ });
113
+ } catch (err) {
114
+ throw new Error(`AST processing failed: ${err.message}`);
115
+ }
116
+ return modified;
117
+ }
118
+ apply(compiler) {
119
+ let i18nKeys;
120
+ compiler.hooks.compilation.tap(pluginName, compilation => {
121
+ if (!i18nKeys) {
122
+ i18nKeys = this.loadI18nKeys();
123
+ }
124
+ compilation.hooks.succeedModule.tap(pluginName, module => {
125
+ if (!module.resource || !/\.(js|jsx|ts|tsx)$/.test(module.resource) || this.processedFiles.has(module)) {
126
+ return;
127
+ }
128
+ try {
129
+ const source = module._source.source(); // Parse with more precise settings
130
+
131
+ const ast = parser.parse(source, {
132
+ sourceType: 'module',
133
+ plugins: ['jsx', 'typescript', 'classProperties', 'decorators-legacy'],
134
+ tokens: true,
135
+ errorRecovery: true
136
+ });
137
+ if (this.processAST(ast, i18nKeys)) {
138
+ const newCode = this.safeGenerateCode(ast);
139
+ module._source = new RawSource(newCode); // Update module hash
140
+
141
+ module.buildInfo.hash = crypto.createHash('md5').update(newCode).digest('hex');
142
+ }
143
+ this.processedFiles.add(module);
144
+ } catch (err) {
145
+ // Log error but don't fail the build
146
+ compilation.warnings.push(new Error(`[${pluginName}] Processing ${module.resource} failed: ${err.message}`));
147
+ }
148
+ }); // Generate manifest after processing
149
+
150
+ compilation.hooks.afterOptimizeModules.tap(pluginName, () => {
151
+ const manifest = {
152
+ hashMapping: Object.fromEntries(this.keyToHashMap),
153
+ metadata: {
154
+ totalKeys: this.keyToHashMap.size,
155
+ timestamp: Date.now()
156
+ }
157
+ };
158
+ compilation.assets['i18n-hash-manifest.json'] = new RawSource(JSON.stringify(manifest, null, 2));
159
+ });
160
+ });
161
+ }
162
+ }
163
+ module.exports = I18nKeyHashPlugin;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ const {
4
+ RawSource
5
+ } = require('webpack-sources');
6
+ function generateManifests({
7
+ compilation,
8
+ allI18nKeys,
9
+ moduleToKeysMap,
10
+ cacheGroupToModulesMap,
11
+ jsResourceI18nKeys
12
+ }) {
13
+ const manifest = {
14
+ cacheGroupToI18nMap: {},
15
+ locales: {}
16
+ };
17
+ const metaManifest = {
18
+ keyToCacheGroupMap: {}
19
+ };
20
+ const locales = Object.keys(allI18nKeys); // Map keys to cache groups
21
+
22
+ const keyToCacheGroupMap = {};
23
+ for (const [cacheGroupName, moduleResources] of cacheGroupToModulesMap.entries()) {
24
+ const cacheGroupI18nKeys = new Set();
25
+ for (const moduleResource of moduleResources) {
26
+ const keys = moduleToKeysMap.get(moduleResource);
27
+ if (keys) {
28
+ keys.forEach(key => {
29
+ if (jsResourceI18nKeys.hasOwnProperty(key)) {
30
+ cacheGroupI18nKeys.add(key); // Map key to cache group for meta manifest
31
+
32
+ if (!keyToCacheGroupMap[key]) {
33
+ keyToCacheGroupMap[key] = new Set();
34
+ }
35
+ keyToCacheGroupMap[key].add(cacheGroupName);
36
+ }
37
+ });
38
+ }
39
+ } // Generate i18n files per cache group and locale
40
+
41
+ for (const locale of locales) {
42
+ const i18nData = {};
43
+ const localeData = allI18nKeys[locale];
44
+ for (const key of cacheGroupI18nKeys) {
45
+ // Find the key in the locale data
46
+ let found = false;
47
+ for (const section of Object.values(localeData)) {
48
+ if (section.hasOwnProperty(key)) {
49
+ i18nData[key] = section[key];
50
+ found = true;
51
+ break;
52
+ }
53
+ }
54
+ if (!found) {
55
+ console.warn(`Key "${key}" not found in locale "${locale}"`);
56
+ }
57
+ } // Create the i18n chunk file
58
+
59
+ const moduleSource = `window.loadI18nChunk(${JSON.stringify(i18nData, null, 2)});`;
60
+ const filename = `i18n-chunks/${locale}/${cacheGroupName}.js`;
61
+ compilation.emitAsset(filename, new RawSource(moduleSource)); // Update the main manifest
62
+
63
+ if (!manifest.locales[locale]) {
64
+ manifest.locales[locale] = {};
65
+ }
66
+ manifest.locales[locale][cacheGroupName] = filename;
67
+ } // Update the cacheGroupToI18nMap
68
+
69
+ manifest.cacheGroupToI18nMap[cacheGroupName] = cacheGroupName;
70
+ } // Generate the meta manifest by converting Sets to Arrays
71
+
72
+ for (const [key, cacheGroupsSet] of Object.entries(keyToCacheGroupMap)) {
73
+ metaManifest.keyToCacheGroupMap[key] = Array.from(cacheGroupsSet);
74
+ } // Emit the main manifest file
75
+
76
+ const manifestSource = new RawSource(`window.i18n = window.i18n || {}; window.i18n.manifest = ${JSON.stringify(manifest, null, 2)};`);
77
+ const manifestFilename = 'i18n-chunk/manifest.js';
78
+ compilation.emitAsset(manifestFilename, manifestSource);
79
+ console.log(`Emitted i18n manifest: ${manifestFilename}`); // Emit the meta manifest file
80
+
81
+ const metaManifestSource = new RawSource(JSON.stringify(metaManifest, null, 2));
82
+ const metaManifestFilename = 'i18n-chunk/metaManifest.json';
83
+ compilation.emitAsset(metaManifestFilename, metaManifestSource);
84
+ console.log(`Emitted i18n meta manifest: ${metaManifestFilename}`);
85
+ }
86
+ module.exports = {
87
+ generateManifests
88
+ };
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _webpackSources = require("webpack-sources");
8
+ var _path = _interopRequireDefault(require("path"));
9
+ var _fs = _interopRequireDefault(require("fs"));
10
+ function _interopRequireDefault(obj) {
11
+ return obj && obj.__esModule ? obj : {
12
+ default: obj
13
+ };
14
+ }
15
+
16
+ // UnicodeConversionPlugin.js
17
+ class UnicodeConversionPlugin {
18
+ constructor(options = {}) {
19
+ this.options = {
20
+ test: '',
21
+ // i18nPublicPath
22
+ encoding: 'utf8',
23
+ debug: false,
24
+ ...options
25
+ };
26
+ }
27
+ apply(compiler) {
28
+ // Run before the I18n plugin
29
+ compiler.hooks.beforeRun.tapAsync('UnicodeConversionPlugin', (compiler, callback) => {
30
+ try {
31
+ const targetPath = _path.default.resolve(compiler.context, this.options.test);
32
+ if (!_fs.default.existsSync(targetPath)) {
33
+ throw new Error(`Path not found: ${targetPath}`);
34
+ } // Convert files in place
35
+
36
+ this.convertFilesInPlace(targetPath);
37
+ callback();
38
+ } catch (err) {
39
+ callback(err);
40
+ }
41
+ });
42
+ }
43
+ convertFilesInPlace(targetPath) {
44
+ const processDir = dir => {
45
+ const files = _fs.default.readdirSync(dir);
46
+ files.forEach(file => {
47
+ const fullPath = _path.default.join(dir, file);
48
+ const stat = _fs.default.statSync(fullPath);
49
+ if (stat.isDirectory()) {
50
+ processDir(fullPath);
51
+ } else if (file.endsWith('.properties')) {
52
+ try {
53
+ // Read file
54
+ const content = _fs.default.readFileSync(fullPath, this.options.encoding); // Convert content
55
+
56
+ const convertedContent = this.convertUnicode(content); // Write back to same file
57
+
58
+ _fs.default.writeFileSync(fullPath, convertedContent, this.options.encoding);
59
+ if (this.options.debug) {
60
+ console.log(`[UnicodeConversionPlugin] Converted: ${_path.default.relative(targetPath, fullPath)}`);
61
+ }
62
+ } catch (error) {
63
+ console.error(`Error processing ${fullPath}: ${error.message}`);
64
+ }
65
+ }
66
+ });
67
+ };
68
+ processDir(targetPath);
69
+ }
70
+ convertUnicode(content) {
71
+ const lines = content.split(/\r?\n/);
72
+ const converted = lines.map(line => {
73
+ // Skip comments and empty lines
74
+ if (line.startsWith('#') || !line.trim()) {
75
+ return line;
76
+ } // Find key-value separator
77
+
78
+ const equalIndex = line.indexOf('=');
79
+ if (equalIndex === -1) {
80
+ return line;
81
+ }
82
+ const key = line.substring(0, equalIndex).trim();
83
+ const value = line.substring(equalIndex + 1).trim(); // Convert unicode escapes in the value
84
+
85
+ const convertedValue = this.convertUnicodeEscapes(value);
86
+ return `${key}=${convertedValue}`;
87
+ });
88
+ return converted.join('\n');
89
+ }
90
+ convertUnicodeEscapes(str) {
91
+ return str.replace(/\\u([0-9a-fA-F]{4})/g, (match, hex) => {
92
+ try {
93
+ return String.fromCharCode(parseInt(hex, 16));
94
+ } catch (err) {
95
+ throw new Error(`Invalid unicode escape sequence: ${match}`);
96
+ }
97
+ });
98
+ }
99
+ }
100
+ var _default = UnicodeConversionPlugin;
101
+ exports.default = _default;
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.VALIDATION = exports.RUNTIME_CONFIG = exports.RETRY_STRATEGY = exports.PERFORMANCE = exports.MANIFEST_FIELDS = exports.LOADING_MODES = exports.FILE_PATTERNS = exports.FILE_DEFAULTS = exports.FEATURES = exports.ERROR_MESSAGES = exports.CHUNK_SIZE_LIMITS = exports.CHUNK_HINTS = exports.CACHE_CONFIG = exports.ALL_I18N_KEYS = void 0;
7
+ // constants.js
8
+ // Chunk size limits
9
+ const CHUNK_SIZE_LIMITS = {
10
+ // Maximum keys in a single chunk (prevent >60% keys in one chunk)
11
+ MAX_CHUNK_SIZE: 200,
12
+ // Minimum keys before considering chunk merge
13
+ MIN_CHUNK_SIZE: 50,
14
+ // Ideal chunk size for optimal loading
15
+ IDEAL_CHUNK_SIZE: 100,
16
+ // Maximum percentage of total keys in one chunk
17
+ MAX_CHUNK_PERCENTAGE: 0.2,
18
+ // 20%
19
+ // Chunk size variance allowed before rebalancing
20
+ CHUNK_SIZE_VARIANCE: 0.2 // 20% variance allowed
21
+ }; // Cache settings
22
+
23
+ exports.CHUNK_SIZE_LIMITS = CHUNK_SIZE_LIMITS;
24
+ const CACHE_CONFIG = {
25
+ // Maximum number of chunks to cache
26
+ MAX_CACHED_CHUNKS: 50,
27
+ // Maximum age of cached chunks (ms)
28
+ CACHE_TTL: 3600000,
29
+ // 1 hour
30
+ // Cache version for cache busting
31
+ CACHE_VERSION: '1.0.0'
32
+ }; // File patterns
33
+
34
+ exports.CACHE_CONFIG = CACHE_CONFIG;
35
+ const FILE_PATTERNS = {
36
+ // JavaScript file extensions to scan
37
+ JS_EXTENSIONS: /\.(js|jsx|ts|tsx)$/,
38
+ // i18n key patterns to match
39
+ I18N_KEY_PATTERN: /^[a-zA-Z0-9_.-]+$/,
40
+ // Comment patterns for i18n keys
41
+ I18N_COMMENT_PATTERN: /^i18n:/
42
+ }; // Loading modes
43
+
44
+ exports.FILE_PATTERNS = FILE_PATTERNS;
45
+ const LOADING_MODES = {
46
+ EAGER: 'eager',
47
+ // Load chunks immediately
48
+ LAZY: 'lazy',
49
+ // Load chunks on demand
50
+ PREFETCH: 'prefetch',
51
+ // Load chunks after main content
52
+ PRELOAD: 'preload' // Load chunks with high priority
53
+ }; // Default file names and paths
54
+
55
+ exports.LOADING_MODES = LOADING_MODES;
56
+ const FILE_DEFAULTS = {
57
+ // Default manifest file name
58
+ MANIFEST_FILE: 'i18n-manifest.json',
59
+ // Fallback manifest file name
60
+ FALLBACK_MANIFEST_FILE: 'i18n-manifest.main.json',
61
+ // Stats file name
62
+ STATS_FILE: 'i18n-stats.json',
63
+ // Default chunk file pattern
64
+ CHUNK_FILENAME: 'i18n-chunk/[locale]/[name].[chunkhash].i18n.js'
65
+ }; // Error messages
66
+
67
+ exports.FILE_DEFAULTS = FILE_DEFAULTS;
68
+ const ERROR_MESSAGES = {
69
+ NO_LOCALES: 'No locales specified in plugin options',
70
+ INVALID_KEY: 'Invalid i18n key format',
71
+ CHUNK_OVERFLOW: 'Chunk size exceeds maximum limit',
72
+ MANIFEST_ERROR: 'Failed to generate manifest',
73
+ LOAD_ERROR: 'Failed to load i18n chunk',
74
+ INVALID_CONFIG: 'Invalid plugin configuration'
75
+ }; // Feature flags for experimental features
76
+
77
+ exports.ERROR_MESSAGES = ERROR_MESSAGES;
78
+ const FEATURES = {
79
+ ENABLE_KEY_MOVEMENT_TRACKING: true,
80
+ ENABLE_CHUNK_STATS: true,
81
+ ENABLE_SMART_LOADING: true,
82
+ ENABLE_CACHE_OPTIMIZATION: true,
83
+ ENABLE_DEBUG_LOGGING: false
84
+ }; // Performance thresholds
85
+
86
+ exports.FEATURES = FEATURES;
87
+ const PERFORMANCE = {
88
+ // Maximum time to spend on chunk balancing (ms)
89
+ MAX_BALANCE_TIME: 1000,
90
+ // Maximum keys to process in one batch
91
+ BATCH_SIZE: 1000,
92
+ // Warning thresholds
93
+ WARNINGS: {
94
+ CHUNK_SIZE: 150,
95
+ // Warn when chunk exceeds this size
96
+ TOTAL_SIZE: 5000,
97
+ // Warn when total keys exceed this
98
+ LOAD_TIME: 500 // Warn when chunk load exceeds this (ms)
99
+ }
100
+ }; // Runtime configurations that can be overridden
101
+
102
+ exports.PERFORMANCE = PERFORMANCE;
103
+ const RUNTIME_CONFIG = {
104
+ // Default timeout for chunk loading (ms)
105
+ CHUNK_TIMEOUT: 30000,
106
+ // Number of retry attempts for failed loads
107
+ MAX_RETRIES: 3,
108
+ // Delay between retries (ms)
109
+ RETRY_DELAY: 1000,
110
+ // Enable verbose logging
111
+ DEBUG_MODE: false
112
+ }; // Manifest metadata fields
113
+
114
+ exports.RUNTIME_CONFIG = RUNTIME_CONFIG;
115
+ const MANIFEST_FIELDS = {
116
+ // Required fields in manifest
117
+ REQUIRED: ['version', 'generated', 'chunks', 'locales'],
118
+ // Optional metadata fields
119
+ METADATA: ['description', 'environment', 'buildId', 'commitHash']
120
+ }; // Default retry strategy
121
+
122
+ exports.MANIFEST_FIELDS = MANIFEST_FIELDS;
123
+ const RETRY_STRATEGY = {
124
+ // Initial delay (ms)
125
+ initialDelay: 1000,
126
+ // Maximum delay (ms)
127
+ maxDelay: 10000,
128
+ // Backoff factor
129
+ factor: 2,
130
+ // Maximum number of retries
131
+ maxRetries: 3
132
+ }; // Chunk optimization hints
133
+
134
+ exports.RETRY_STRATEGY = RETRY_STRATEGY;
135
+ const CHUNK_HINTS = {
136
+ // Threshold for splitting chunks
137
+ SPLIT_THRESHOLD: 0.8,
138
+ // 80% of max size
139
+ // Threshold for merging chunks
140
+ MERGE_THRESHOLD: 0.3,
141
+ // 30% of max size
142
+ // Preferred chunk size ranges
143
+ RANGES: {
144
+ SMALL: 50,
145
+ MEDIUM: 100,
146
+ LARGE: 150
147
+ }
148
+ }; // Validation schemas (using simple pattern matching)
149
+
150
+ exports.CHUNK_HINTS = CHUNK_HINTS;
151
+ const VALIDATION = {
152
+ KEY_PATTERN: /^[a-zA-Z0-9_.]+$/,
153
+ LOCALE_PATTERN: /^[a-z]{2}(_[A-Z]{2})?$/,
154
+ CHUNK_NAME_PATTERN: /^[a-zA-Z0-9-_]+$/
155
+ }; // Export all i18n keys for validation (this would be populated from your source)
156
+
157
+ exports.VALIDATION = VALIDATION;
158
+ const ALL_I18N_KEYS = new Set([
159
+ // Example keys - in real implementation, these would be loaded from your source
160
+ 'common.ok', 'common.cancel', 'errors.notFound' // ... more keys
161
+ ]);
162
+ exports.ALL_I18N_KEYS = ALL_I18N_KEYS;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ const esprima = require('esprima');
4
+ const crypto = require('crypto');
5
+ class I18nKeyHasher {
6
+ constructor() {
7
+ this.keyHashMap = new Map();
8
+ this.hashKeyMap = new Map();
9
+ this.usedHashes = new Set();
10
+ this.hashLength = 5;
11
+ }
12
+ generateHash(key) {
13
+ const fullHash = crypto.createHash('md5').update(key).digest('hex');
14
+ let hash = fullHash.substring(0, this.hashLength);
15
+ let counter = 0;
16
+ let finalHash = hash;
17
+ while (this.usedHashes.has(finalHash)) {
18
+ counter++;
19
+ finalHash = hash + counter;
20
+ }
21
+ this.usedHashes.add(finalHash);
22
+ return finalHash;
23
+ }
24
+ hashKey(key) {
25
+ if (this.keyHashMap.has(key)) {
26
+ return this.keyHashMap.get(key);
27
+ }
28
+ const hash = this.generateHash(key);
29
+ this.keyHashMap.set(key, hash);
30
+ this.hashKeyMap.set(hash, key);
31
+ return hash;
32
+ }
33
+ replaceKeysInSource(sourceCode) {
34
+ try {
35
+ // Parse source using esprima
36
+ const ast = esprima.parse(sourceCode, {
37
+ range: true,
38
+ tokens: true,
39
+ comment: true,
40
+ jsx: true
41
+ }); // Track string literals to replace
42
+
43
+ const replacements = []; // Walk the AST to find string literals
44
+
45
+ const traverse = node => {
46
+ if (node.type === 'Literal' && typeof node.value === 'string' && this.keyHashMap.has(node.value)) {
47
+ replacements.push({
48
+ range: node.range,
49
+ value: this.keyHashMap.get(node.value)
50
+ });
51
+ } // Traverse child nodes
52
+
53
+ for (const key in node) {
54
+ if (node[key] && typeof node[key] === 'object') {
55
+ if (Array.isArray(node[key])) {
56
+ node[key].forEach(child => child && traverse(child));
57
+ } else {
58
+ traverse(node[key]);
59
+ }
60
+ }
61
+ }
62
+ };
63
+ traverse(ast); // Apply replacements in reverse order
64
+
65
+ replacements.sort((a, b) => b.range[0] - a.range[0]).forEach(({
66
+ range,
67
+ value
68
+ }) => {
69
+ sourceCode = sourceCode.slice(0, range[0]) + `"${value}"` + sourceCode.slice(range[1]);
70
+ });
71
+ return sourceCode;
72
+ } catch (err) {
73
+ console.warn('Error during source transformation:', err);
74
+ return sourceCode; // Return original source if transformation fails
75
+ }
76
+ }
77
+ }
78
+ module.exports = I18nKeyHasher;