@zohodesk/client_build_tool 0.0.10-exp.9 → 0.0.11-exp.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,21 +1,6 @@
1
1
  # Changelog and Release Notes
2
2
 
3
- - remove babel-plugin-module-resolver dependencies
4
3
 
5
- # v0.0.10 (12-05-2025)
6
- **Feature:-**
7
- - `alias` support for `build:es` and `build:lib`
8
- - Add babel-plugin-module-resolver dependencies
9
- - Modify getBabelPlugin to include module resolver with aliases
10
-
11
- **Bug Fix:-**
12
- - Enhance runBabelForTSFile to handle both .tsx and .ts file extensions
13
- - Update mockApiHandler to ensure mock function is called correctly
14
-
15
- **Change:-**
16
- - Refactor defaultConfigValues.js to include cli options for enableRTLSplit
17
-
18
- ## v0.0.9
19
4
 
20
5
  **Feature:-**
21
6
  - externals was added to Prevent bundling of certain imported packages and retrieve these external dependencies at runtime.
package/README.md CHANGED
@@ -100,22 +100,7 @@ fixes :-
100
100
 
101
101
  # Changelog and Release Notes
102
102
 
103
- - remove babel-plugin-module-resolver dependencies
104
103
 
105
- # v0.0.10 (12-05-2025)
106
- **Feature:-**
107
- - `alias` support for `build:es` and `build:lib`
108
- - Add babel-plugin-module-resolver dependencies
109
- - Modify getBabelPlugin to include module resolver with aliases
110
-
111
- **Bug Fix:-**
112
- - Enhance runBabelForTSFile to handle both .tsx and .ts file extensions
113
- - Update mockApiHandler to ensure mock function is called correctly
114
-
115
- **Change:-**
116
- - Refactor defaultConfigValues.js to include cli options for enableRTLSplit
117
-
118
- ## v0.0.9
119
104
 
120
105
  **Feature:-**
121
106
  - externals was added to Prevent bundling of certain imported packages and retrieve these external dependencies at runtime.
@@ -115,10 +115,7 @@ var _default = {
115
115
  // Name Suggestions `customizations` this will be easier then `plugin` to understand for developers
116
116
  plugins: {
117
117
  rtlSplit: {
118
- enableRTLSplit: {
119
- value: false,
120
- cli: 'enable_rtl_split'
121
- },
118
+ enableRTLSplit: false,
122
119
  templateLabel: '{{--dir}}',
123
120
  disableMinifySelector: false,
124
121
  dirVarName: 'document.dir'
@@ -174,7 +171,23 @@ var _default = {
174
171
  localeVarName: 'document.documentElement.lang',
175
172
  jsonpFunc: 'console.log',
176
173
  jsResource: null,
177
- propertiesFolder: null
174
+ propertiesFolder: null,
175
+ useNumericIndexing: false
176
+ },
177
+ i18nIndexing: {
178
+ enable: false,
179
+ jsResourcePath: './deskapp/properties/JSResources.properties',
180
+ propertiesFolderPath: './deskapp/properties',
181
+ numericMapPath: './deskapp/properties/i18n-numeric-map.json',
182
+ numericFilenameTemplate: 'i18n-chunk/[locale]/numeric.i18n.js',
183
+ dynamicFilenameTemplate: 'i18n-chunk/[locale]/dynamic.i18n.js',
184
+ singleFileTemplate: 'i18n/[locale].js',
185
+ jsonpFunc: 'window.loadI18nChunk',
186
+ htmlTemplateLabel: '{{--user-locale}}',
187
+ localeVarName: 'window.userLangCode',
188
+ singleFile: false,
189
+ includeContentHash: false,
190
+ generateManifest: false
178
191
  },
179
192
  publicFolders: ['...'],
180
193
  app: {
@@ -94,7 +94,22 @@ var _default = {
94
94
  localeVarName: 'document.documentElement.lang',
95
95
  jsonpFunc: 'console.log',
96
96
  jsResource: null,
97
- propertiesFolder: null
97
+ propertiesFolder: null,
98
+ useNumericIndexing: false
99
+ },
100
+ i18nIndexing: {
101
+ enable: false,
102
+ jsResourcePath: './deskapp/properties/JSResources.properties',
103
+ propertiesFolderPath: './deskapp/properties',
104
+ numericMapPath: './deskapp/properties/i18n-numeric-map.json',
105
+ numericFilenameTemplate: 'i18n-chunk/[locale]/numeric.i18n.js',
106
+ dynamicFilenameTemplate: 'i18n-chunk/[locale]/dynamic.i18n.js',
107
+ jsonpFunc: 'window.loadI18nChunk',
108
+ htmlTemplateLabel: '{{--user-locale}}',
109
+ localeVarName: 'window.userLangCode',
110
+ singleFile: false,
111
+ includeContentHash: false,
112
+ generateManifest: false
98
113
  },
99
114
  publicFolders: ['...', {
100
115
  source: './deskapp/tp/',
@@ -19,8 +19,7 @@ const babelPluginOrder = ['removeAttribute', 'removePropTypes', 'devConsoleExclu
19
19
  function getBabelPlugin(options) {
20
20
  const {
21
21
  mode
22
- } = options; // let customPlugins = [];
23
-
22
+ } = options;
24
23
  let customPlugins = [];
25
24
  const {
26
25
  babelCustomizations
@@ -33,4 +32,6 @@ function getBabelPlugin(options) {
33
32
  }
34
33
 
35
34
  return customPlugins.filter(Boolean);
36
- }
35
+ }
36
+
37
+ ;
@@ -25,6 +25,6 @@ function runBabelForTSFile({
25
25
  // const jsSourceCode = readFileSync(filename).toString();
26
26
  const babelConfig = (0, _babelWebConfig.babelWebConfig)(options, mode);
27
27
  const result = (0, _core.transformFileSync)(filename, babelConfig);
28
- (0, _copyFile.writeFile)(outputFile.replace('.tsx', '.js').replace('.ts', '.js'), result.code);
28
+ (0, _copyFile.writeFile)(outputFile.replace('.tsx', '.js'), result.code);
29
29
  }
30
30
  }
@@ -30,16 +30,6 @@ class BundleIntegrityReport {
30
30
 
31
31
  apply(compiler) {
32
32
  compiler.hooks.done.tapAsync(pluginName, (stats, callback) => {
33
- if (stats.hasErrors()) {
34
- console.error(stats.toString({
35
- all: false,
36
- errors: true,
37
- errorDetails: true,
38
- colors: true
39
- }));
40
- return callback(new Error('Build failed due to compilation errors.'));
41
- }
42
-
43
33
  const statsJson = (0, _objectManipulation.removeKeysFromObject)(stats.toJson(this.statsOptions), this.excludeKeysInStat);
44
34
  this.emitStats(statsJson).on('end', () => {
45
35
  callback();
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
4
+
5
+ const pluginName = 'I18nNumericIndexHtmlInjectorPlugin';
6
+
7
+ class I18nNumericIndexHtmlInjectorPlugin {
8
+ constructor(options) {
9
+ this.options = options;
10
+ }
11
+
12
+ apply(compiler) {
13
+ compiler.hooks.thisCompilation.tap(pluginName, compilation => {
14
+ HtmlWebpackPlugin.getHooks(compilation).beforeAssetTagGeneration.tapAsync(pluginName, (hookData, cb) => {
15
+ const {
16
+ assets
17
+ } = hookData;
18
+ const {
19
+ numericFilenameTemplate,
20
+ dynamicFilenameTemplate,
21
+ htmlTemplateLabel,
22
+ i18nAssetsPublicPathPrefix = ''
23
+ } = this.options;
24
+ const newI18nAssetUrlsToAdd = [];
25
+
26
+ if (numericFilenameTemplate) {
27
+ const numericFilename = numericFilenameTemplate.replace(/\[locale\]/g, htmlTemplateLabel);
28
+ newI18nAssetUrlsToAdd.push(numericFilename);
29
+ }
30
+
31
+ if (dynamicFilenameTemplate) {
32
+ const dynamicFilename = dynamicFilenameTemplate.replace(/\[locale\]/g, htmlTemplateLabel);
33
+ newI18nAssetUrlsToAdd.push(dynamicFilename);
34
+ }
35
+
36
+ if (newI18nAssetUrlsToAdd.length > 0) {
37
+ assets.js = [...assets.js, ...newI18nAssetUrlsToAdd];
38
+ }
39
+
40
+ cb(null, hookData);
41
+ });
42
+ });
43
+ }
44
+
45
+ }
46
+
47
+ module.exports = {
48
+ I18nNumericIndexHtmlInjectorPlugin
49
+ };
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+
3
+ const path = require('path');
4
+
5
+ const {
6
+ sources,
7
+ Compilation,
8
+ util
9
+ } = require('webpack');
10
+
11
+ const {
12
+ decodeUnicodeEscapes
13
+ } = require('../../utils/propertiesParser');
14
+
15
+ const {
16
+ loadNumericMap,
17
+ loadI18nData
18
+ } = require('./utils/i18nDataLoader');
19
+
20
+ const {
21
+ RawSource
22
+ } = sources;
23
+ const pluginName = 'I18nNumericIndexPlugin';
24
+
25
+ class I18nNumericIndexPlugin {
26
+ constructor(options = {}) {
27
+ this.options = { ...options,
28
+ singleFile: options.singleFile || false,
29
+ singleFileTemplate: options.singleFileTemplate,
30
+ includeContentHash: options.includeContentHash || false,
31
+ generateManifest: options.generateManifest || false
32
+ };
33
+ this.numericMap = null;
34
+ this.i18nData = null;
35
+ this.manifest = {};
36
+ }
37
+
38
+ getNumericMap(compilation) {
39
+ if (!this.numericMap) {
40
+ const mapPath = path.resolve(compilation.compiler.context, this.options.numericMapPath);
41
+ this.numericMap = loadNumericMap(mapPath, compilation);
42
+ }
43
+
44
+ return this.numericMap;
45
+ }
46
+
47
+ getI18nData(compilation) {
48
+ if (!this.i18nData) {
49
+ this.i18nData = loadI18nData(this.options, compilation);
50
+ }
51
+
52
+ return this.i18nData;
53
+ }
54
+
55
+ generateContentHash(content, compilation) {
56
+ const {
57
+ hashFunction,
58
+ hashDigest,
59
+ hashDigestLength
60
+ } = compilation.outputOptions;
61
+ const hash = util.createHash(hashFunction || 'xxhash64');
62
+ hash.update(content);
63
+ return hash.digest(hashDigest || 'hex').substring(0, hashDigestLength || 20);
64
+ }
65
+
66
+ emitChunk(compilation, filename, locale, data, fileType = null) {
67
+ const content = decodeUnicodeEscapes(JSON.stringify(data));
68
+ const fileContent = `${this.options.jsonpFunc}(${content});`;
69
+ let outputPath = filename.replace(/\[locale\]/g, locale); // Check if template contains [contenthash] placeholder or use legacy includeContentHash flag
70
+
71
+ const hasContentHashPlaceholder = filename.includes('[contenthash]');
72
+ const shouldIncludeHash = hasContentHashPlaceholder || this.options.includeContentHash;
73
+
74
+ if (shouldIncludeHash) {
75
+ const contentHash = this.generateContentHash(fileContent, compilation);
76
+
77
+ if (hasContentHashPlaceholder) {
78
+ // Replace [contenthash] placeholder with actual hash
79
+ outputPath = outputPath.replace(/\[contenthash\]/g, contentHash);
80
+ } else {
81
+ // Legacy behavior: append hash before .js extension
82
+ outputPath = outputPath.replace(/\.js$/, `.${contentHash}.js`);
83
+ }
84
+ }
85
+
86
+ if (this.options.generateManifest) {
87
+ const cleanName = filename.replace(/\[locale\]/g, locale).replace(/\[contenthash\]/g, '').replace(/\.js$/, '.js');
88
+ const cleanNameWithType = fileType ? cleanName.replace(/\.js$/, `.${fileType}.js`) : cleanName;
89
+ const manifestKey = cleanNameWithType.split('/').pop(); // Extract just the filename for the key
90
+
91
+ this.manifest[manifestKey] = outputPath.split('/').pop();
92
+ }
93
+
94
+ compilation.emitAsset(outputPath, new RawSource(fileContent));
95
+ return outputPath;
96
+ }
97
+
98
+ apply(compiler) {
99
+ compiler.hooks.thisCompilation.tap(pluginName, compilation => {
100
+ compilation.hooks.processAssets.tapAsync({
101
+ name: pluginName,
102
+ stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
103
+ }, (assets, callback) => {
104
+ if (!this.options.enable) {
105
+ return callback();
106
+ }
107
+
108
+ const {
109
+ sortedKeys,
110
+ totalKeys
111
+ } = this.getNumericMap(compilation);
112
+ const {
113
+ jsResourceBase,
114
+ allI18n,
115
+ locales
116
+ } = this.getI18nData(compilation);
117
+ if (!locales.length) return callback();
118
+ const numericKeysSet = new Set(sortedKeys);
119
+ const englishData = allI18n.en_US || jsResourceBase;
120
+ locales.forEach(locale => {
121
+ const localeData = allI18n[locale] || {};
122
+ const numericData = {};
123
+
124
+ for (let i = 0; i < totalKeys; i++) {
125
+ const key = sortedKeys[i];
126
+
127
+ if (key && jsResourceBase[key] !== undefined) {
128
+ numericData[i] = localeData[key] ?? englishData[key];
129
+ }
130
+ }
131
+
132
+ const dynamicData = {};
133
+ Object.keys(jsResourceBase).forEach(key => {
134
+ if (!numericKeysSet.has(key)) {
135
+ dynamicData[key] = localeData[key] ?? englishData[key];
136
+ }
137
+ });
138
+
139
+ if (this.options.singleFile) {
140
+ const combinedData = { ...numericData,
141
+ ...dynamicData
142
+ };
143
+
144
+ if (Object.keys(combinedData).length > 0) {
145
+ const filename = this.options.singleFileTemplate || this.options.numericFilenameTemplate || this.options.dynamicFilenameTemplate;
146
+ this.emitChunk(compilation, filename, locale, combinedData);
147
+ }
148
+ } else {
149
+ if (Object.keys(numericData).length > 0) {
150
+ this.emitChunk(compilation, this.options.numericFilenameTemplate, locale, numericData, 'numeric');
151
+ }
152
+
153
+ if (Object.keys(dynamicData).length > 0) {
154
+ this.emitChunk(compilation, this.options.dynamicFilenameTemplate, locale, dynamicData, 'dynamic');
155
+ }
156
+ }
157
+ });
158
+
159
+ if (this.options.generateManifest && Object.keys(this.manifest).length > 0) {
160
+ const manifestPath = path.dirname(this.options.numericFilenameTemplate) + '/manifest.json';
161
+ const manifestContent = JSON.stringify(this.manifest, null, 2);
162
+ compilation.emitAsset(manifestPath, new RawSource(manifestContent));
163
+ }
164
+
165
+ callback();
166
+ });
167
+ });
168
+ }
169
+
170
+ }
171
+
172
+ module.exports = {
173
+ I18nNumericIndexPlugin
174
+ };
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+
3
+ const fs = require('fs');
4
+
5
+ const path = require('path');
6
+
7
+ const {
8
+ parseProperties
9
+ } = require('../../../utils/propertiesParser');
10
+
11
+ function loadPropertiesFile(filePath, compilation, description) {
12
+ try {
13
+ const content = fs.readFileSync(filePath, 'utf-8');
14
+ const parsed = parseProperties(content);
15
+ return parsed;
16
+ } catch (err) {
17
+ if (compilation) {
18
+ compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error loading ${description}: ${err.message}`));
19
+ }
20
+
21
+ return {};
22
+ }
23
+ }
24
+
25
+ function loadNumericMap(numericMapPath, compilation) {
26
+ try {
27
+ const fileContent = fs.readFileSync(numericMapPath, 'utf-8');
28
+ const parsedData = JSON.parse(fileContent);
29
+ const sortedKeys = new Array(parsedData.totalKeysInMap);
30
+ Object.entries(parsedData.originalKeyToNumericId).forEach(([key, id]) => {
31
+ sortedKeys[id] = key;
32
+ });
33
+ return {
34
+ sortedKeys,
35
+ totalKeys: parsedData.totalKeysInMap
36
+ };
37
+ } catch (err) {
38
+ if (compilation) {
39
+ compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error loading numeric map: ${err.message}`));
40
+ }
41
+
42
+ return {
43
+ sortedKeys: [],
44
+ totalKeys: 0
45
+ };
46
+ }
47
+ }
48
+
49
+ function loadAllLocaleFiles(propertiesPath, baseFileName, compilation, jsResourceBase) {
50
+ const allI18n = {};
51
+ const locales = []; // Always use the jsResourceBase as en_US base
52
+
53
+ allI18n['en_US'] = jsResourceBase;
54
+ locales.push('en_US');
55
+
56
+ try {
57
+ const files = fs.readdirSync(propertiesPath);
58
+ files.forEach(file => {
59
+ if (!file.endsWith('.properties')) return;
60
+ const match = file.match(/^ApplicationResources_([a-z]{2}_[A-Z]{2})\.properties$/);
61
+
62
+ if (match) {
63
+ const locale = match[1];
64
+ const filePath = path.join(propertiesPath, file);
65
+ const localeData = loadPropertiesFile(filePath, compilation, `locale ${locale}`);
66
+ allI18n[locale] = { ...jsResourceBase,
67
+ ...localeData
68
+ };
69
+
70
+ if (!locales.includes(locale)) {
71
+ locales.push(locale);
72
+ }
73
+ }
74
+ });
75
+ } catch (err) {
76
+ if (compilation) {
77
+ compilation.errors.push(new Error(`I18nNumericIndexPlugin: Error reading properties folder: ${err.message}`));
78
+ }
79
+ }
80
+
81
+ return {
82
+ allI18n,
83
+ locales
84
+ };
85
+ }
86
+
87
+ function loadI18nData(options, compilation) {
88
+ const jsResourcePath = path.resolve(compilation.compiler.context, options.jsResourcePath);
89
+ const propertiesPath = path.resolve(compilation.compiler.context, options.propertiesFolderPath);
90
+ const baseFileName = path.basename(options.jsResourcePath, '.properties');
91
+ const jsResourceBase = loadPropertiesFile(jsResourcePath, compilation, 'JS resources');
92
+ const {
93
+ allI18n,
94
+ locales
95
+ } = loadAllLocaleFiles(propertiesPath, baseFileName, compilation, jsResourceBase);
96
+ return {
97
+ jsResourceBase,
98
+ allI18n,
99
+ locales
100
+ };
101
+ }
102
+
103
+ module.exports = {
104
+ loadPropertiesFile,
105
+ loadNumericMap,
106
+ loadAllLocaleFiles,
107
+ loadI18nData
108
+ };
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ const {
4
+ walk
5
+ } = require('estree-walker');
6
+
7
+ const PREFIX_I18N_COMMENT = 'I18N';
8
+ const PREFIX_I18N_COMMENT_DYNAMIC = 'dynamic-i18n-key';
9
+
10
+ function getI18nKeysFromSingleComment(commentNode, validKeysSet) {
11
+ const foundKeysInComment = [];
12
+
13
+ if (!commentNode || typeof commentNode.value !== 'string') {
14
+ return foundKeysInComment;
15
+ }
16
+
17
+ const commentString = commentNode.value.trim();
18
+ let i18nKeyStr;
19
+
20
+ if (commentString.startsWith(PREFIX_I18N_COMMENT)) {
21
+ i18nKeyStr = commentString.slice(PREFIX_I18N_COMMENT.length).trim();
22
+ } else if (commentString.startsWith(PREFIX_I18N_COMMENT_DYNAMIC)) {
23
+ i18nKeyStr = commentString.slice(PREFIX_I18N_COMMENT_DYNAMIC.length).trim();
24
+ }
25
+
26
+ if (!i18nKeyStr) {
27
+ return foundKeysInComment;
28
+ }
29
+
30
+ const potentialKeys = i18nKeyStr.split(',').map(key => key.trim()).filter(key => key);
31
+ potentialKeys.forEach(key => {
32
+ if (validKeysSet.has(key)) {
33
+ foundKeysInComment.push(key);
34
+ }
35
+ });
36
+ return foundKeysInComment;
37
+ }
38
+ /**
39
+ * Traverses an AST and its comments to collect and categorize i18n keys.
40
+ *
41
+ * @param {object} astProgramNode - The Program node of the AST.
42
+ * @param {object[]} commentsArray - An array of comment nodes from the AST.
43
+ * @param {object} allI18nKeysMasterMap - Object map of all valid i18n keys (from JSResources).
44
+ * @param {boolean} [isDebug=false] - Flag for verbose logging.
45
+ * @returns {{literalKeys: Set<string>, commentKeys: Set<string>}}
46
+ * literalKeys: Set of valid i18n keys found as string literals.
47
+ * commentKeys: Set of valid i18n keys found in comments.
48
+ */
49
+
50
+
51
+ function collectAndCategorizeUsedI18nKeys(astProgramNode, commentsArray, allI18nKeysMasterMap, isDebug = false) {
52
+ const foundLiteralKeys = new Set();
53
+ const foundCommentKeys = new Set();
54
+ const validKeysSet = new Set(Object.keys(allI18nKeysMasterMap || {}));
55
+
56
+ if (validKeysSet.size === 0 && isDebug) {
57
+ console.warn('[collectAndCategorizeUsedI18nKeys] allI18nKeysMasterMap is empty. No keys can be collected.');
58
+ } // 1. Collect keys from AST string literals
59
+
60
+
61
+ if (astProgramNode) {
62
+ try {
63
+ walk(astProgramNode, {
64
+ enter(node) {
65
+ if ((node.type === 'Literal' || node.type === 'StringLiteral') && typeof node.value === 'string') {
66
+ if (validKeysSet.has(node.value)) {
67
+ foundLiteralKeys.add(node.value);
68
+ }
69
+ }
70
+ }
71
+
72
+ });
73
+ } catch (error) {
74
+ console.error('[collectAndCategorizeUsedI18nKeys] Error during AST walk:', error);
75
+ }
76
+ } // 2. Collect keys from comments
77
+
78
+
79
+ if (commentsArray && Array.isArray(commentsArray)) {
80
+ commentsArray.forEach(commentNode => {
81
+ const keysFromComment = getI18nKeysFromSingleComment(commentNode, validKeysSet);
82
+ keysFromComment.forEach(key => {
83
+ foundCommentKeys.add(key);
84
+ });
85
+ });
86
+ }
87
+
88
+ return {
89
+ literalKeys: foundLiteralKeys,
90
+ commentKeys: foundCommentKeys
91
+ };
92
+ }
93
+
94
+ module.exports = {
95
+ collectAndCategorizeUsedI18nKeys: collectAndCategorizeUsedI18nKeys
96
+ };
@@ -7,11 +7,29 @@ exports.jsLoaders = jsLoaders;
7
7
 
8
8
  var _babelLoaderConfig = require("./loaderConfigs/babelLoaderConfig");
9
9
 
10
+ const {
11
+ i18nIdReplaceLoaderConfig
12
+ } = require('./loaderConfigs/i18nIdReplaceLoaderConfig');
13
+
10
14
  function jsLoaders(options) {
15
+ const useLoaders = [];
16
+ useLoaders.push((0, _babelLoaderConfig.babelLoaderConfig)(options));
17
+ const shouldUseNumericIndexing = options.i18nIndexing && options.i18nIndexing.enable || options.i18nChunkSplit && options.i18nChunkSplit.chunkSplitEnable && options.i18nChunkSplit.useNumericIndexing;
18
+
19
+ if (shouldUseNumericIndexing) {
20
+ try {
21
+ const loaderConfig = i18nIdReplaceLoaderConfig(options, options.context);
22
+
23
+ if (loaderConfig) {
24
+ useLoaders.push(loaderConfig);
25
+ }
26
+ } catch (err) {// Silently skip if configuration fails
27
+ }
28
+ }
29
+
11
30
  return [{
12
31
  test: /\.js$/,
13
32
  exclude: /node_modules/,
14
- use: [(0, _babelLoaderConfig.babelLoaderConfig)(options)] // include: path.join(appPath, folder)
15
-
33
+ use: useLoaders
16
34
  }];
17
35
  }
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ const path = require('path');
4
+
5
+ const fs = require('fs');
6
+
7
+ const {
8
+ getPropertiesAsJSON
9
+ } = require('../custom_plugins/I18nSplitPlugin/utils/propertiesUtils');
10
+
11
+ function loadJSResourcesOnce(options) {
12
+ let jsResourcePath;
13
+
14
+ if (options.i18nIndexing && options.i18nIndexing.enable) {
15
+ jsResourcePath = options.i18nIndexing.jsResourcePath;
16
+ } else if (options.i18nChunkSplit && options.i18nChunkSplit.chunkSplitEnable && options.i18nChunkSplit.useNumericIndexing) {
17
+ jsResourcePath = options.i18nChunkSplit.jsResource;
18
+ } else {
19
+ throw new Error('i18nIdReplaceLoader requires either i18nIndexing to be enabled or i18nChunkSplit with useNumericIndexing');
20
+ }
21
+
22
+ if (!jsResourcePath) {
23
+ throw new Error('Missing required jsResourcePath in i18n options');
24
+ }
25
+
26
+ try {
27
+ const i18nData = getPropertiesAsJSON(jsResourcePath);
28
+
29
+ if (Object.keys(i18nData).length === 0) {
30
+ console.warn(`[i18nIdReplaceLoaderConfig] Warning: No i18n data found in JSResource file: ${jsResourcePath}`);
31
+ return {};
32
+ }
33
+
34
+ return i18nData;
35
+ } catch (err) {
36
+ throw new Error(`Error reading JSResource file ${jsResourcePath}: ${err.message}`);
37
+ }
38
+ }
39
+
40
+ function i18nIdReplaceLoaderConfig(options, webpackContext) {
41
+ let numericMapPath;
42
+
43
+ if (options.i18nIndexing && options.i18nIndexing.enable) {
44
+ numericMapPath = options.i18nIndexing.numericMapPath;
45
+ } else if (options.i18nChunkSplit && options.i18nChunkSplit.chunkSplitEnable && options.i18nChunkSplit.useNumericIndexing) {
46
+ numericMapPath = options.i18nChunkSplit.numericMapPath;
47
+ } else {
48
+ throw new Error('i18nIdReplaceLoader requires either i18nIndexing to be enabled or i18nChunkSplit with useNumericIndexing');
49
+ }
50
+
51
+ if (!numericMapPath) {
52
+ throw new Error('numericMapPath is required in i18nIndexing or i18nChunkSplit config');
53
+ }
54
+
55
+ const allI18nData = loadJSResourcesOnce(options);
56
+
57
+ const i18nKeyReplaceLoaderPath = require.resolve('../loaders/i18nIdReplaceLoader.js');
58
+
59
+ const loaderOptions = {
60
+ allI18nData: allI18nData,
61
+ sourceMaps: false,
62
+ numericMapPath: numericMapPath,
63
+ includePaths: options.i18nIndexing?.loaderOptions?.includePaths || [],
64
+ excludePaths: options.i18nIndexing?.loaderOptions?.excludePaths || ['node_modules', 'tests']
65
+ };
66
+ return {
67
+ loader: i18nKeyReplaceLoaderPath,
68
+ options: loaderOptions
69
+ };
70
+ }
71
+
72
+ module.exports = {
73
+ i18nIdReplaceLoaderConfig
74
+ };