@lang-tag/cli 0.12.1 → 0.12.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.
- package/algorithms/config-generation/config-keeper.d.ts +14 -0
- package/algorithms/config-generation/path-based-config-generator.d.ts +12 -5
- package/algorithms/index.cjs +40 -12
- package/algorithms/index.js +40 -12
- package/package.json +1 -1
- package/template/base-app.mustache +1 -1
- package/template/base-library.mustache +1 -1
- package/template/placeholder.mustache +6 -1
|
@@ -10,6 +10,20 @@ export interface ConfigKeeperOptions {
|
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
12
|
propertyName?: string;
|
|
13
|
+
/**
|
|
14
|
+
* When true, ensures the keep property is always placed at the end of the configuration object.
|
|
15
|
+
* This improves readability by keeping metadata properties separate from core config.
|
|
16
|
+
* @default true
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* // With keepPropertyAtEnd: true
|
|
20
|
+
* { namespace: 'common', path: 'button', keep: 'namespace' }
|
|
21
|
+
*
|
|
22
|
+
* // With keepPropertyAtEnd: false
|
|
23
|
+
* // Order is not guaranteed
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
keepPropertyAtEnd?: boolean;
|
|
13
27
|
}
|
|
14
28
|
/**
|
|
15
29
|
* Creates a config keeper algorithm that preserves original configuration values
|
|
@@ -24,17 +24,24 @@ export interface PathBasedConfigGeneratorOptions {
|
|
|
24
24
|
*/
|
|
25
25
|
ignoreDirectories?: string[];
|
|
26
26
|
/**
|
|
27
|
-
* When true, automatically
|
|
28
|
-
*
|
|
27
|
+
* When true, automatically removes the root directory from the path if it matches
|
|
28
|
+
* one of the root directories extracted from config.includes patterns.
|
|
29
|
+
* Unlike ignoreDirectories, this only removes the FIRST occurrence if the path starts with it.
|
|
29
30
|
*
|
|
30
31
|
* @default false
|
|
31
32
|
*
|
|
32
33
|
* @example
|
|
33
34
|
* // With includes: ['src/**\/*.{js,ts,jsx,tsx}']
|
|
34
|
-
* //
|
|
35
|
+
* // Path: 'src/components/Button.tsx' → removes root 'src' → 'components/Button.tsx'
|
|
35
36
|
*
|
|
36
|
-
* // With includes: ['
|
|
37
|
-
* //
|
|
37
|
+
* // With includes: ['app/**\/*.{js,ts,jsx,tsx}', 'components/**\/*.{jsx,tsx}']
|
|
38
|
+
* // Path: 'app/dashboard/components/utils.tsx' → removes root 'app' → 'dashboard/components/utils.tsx'
|
|
39
|
+
* // Note: 'components' in the middle is NOT removed (only root occurrences)
|
|
40
|
+
*
|
|
41
|
+
* // With includes: ['(src|app)/**\/*.{js,ts,jsx,tsx}']
|
|
42
|
+
* // Extracts root directories: ['src', 'app']
|
|
43
|
+
* // Path: 'src/features/auth.tsx' → removes root 'src' → 'features/auth.tsx'
|
|
44
|
+
* // Path: 'app/pages/home.tsx' → removes root 'app' → 'pages/home.tsx'
|
|
38
45
|
*/
|
|
39
46
|
ignoreIncludesRootDirectories?: boolean;
|
|
40
47
|
/**
|
package/algorithms/index.cjs
CHANGED
|
@@ -36,11 +36,6 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
36
36
|
return async (event) => {
|
|
37
37
|
const { relativePath, langTagConfig } = event;
|
|
38
38
|
const actualFallbackNamespace = fallbackNamespace ?? langTagConfig.collect?.defaultNamespace;
|
|
39
|
-
let finalIgnoreDirectories = [...ignoreDirectories];
|
|
40
|
-
if (ignoreIncludesRootDirectories && langTagConfig.includes) {
|
|
41
|
-
const extractedDirectories = extractRootDirectoriesFromIncludes(langTagConfig.includes);
|
|
42
|
-
finalIgnoreDirectories = [.../* @__PURE__ */ new Set([...finalIgnoreDirectories, ...extractedDirectories])];
|
|
43
|
-
}
|
|
44
39
|
let pathSegments = relativePath.split(path.sep).filter(Boolean);
|
|
45
40
|
if (pathSegments.length === 0) {
|
|
46
41
|
return;
|
|
@@ -59,8 +54,14 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
59
54
|
}
|
|
60
55
|
return segment;
|
|
61
56
|
}).filter((seg) => seg !== null);
|
|
57
|
+
if (ignoreIncludesRootDirectories && langTagConfig.includes && pathSegments.length > 0) {
|
|
58
|
+
const extractedDirectories = extractRootDirectoriesFromIncludes(langTagConfig.includes);
|
|
59
|
+
if (extractedDirectories.includes(pathSegments[0])) {
|
|
60
|
+
pathSegments = pathSegments.slice(1);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
62
63
|
pathSegments = applyStructuredIgnore(pathSegments, ignoreStructured);
|
|
63
|
-
pathSegments = pathSegments.filter((seg) => !
|
|
64
|
+
pathSegments = pathSegments.filter((seg) => !ignoreDirectories.includes(seg));
|
|
64
65
|
let namespace;
|
|
65
66
|
let path$1;
|
|
66
67
|
if (pathSegments.length >= 1) {
|
|
@@ -107,6 +108,8 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
107
108
|
}
|
|
108
109
|
if (path$1) {
|
|
109
110
|
newConfig.path = path$1;
|
|
111
|
+
} else {
|
|
112
|
+
delete newConfig.path;
|
|
110
113
|
}
|
|
111
114
|
}
|
|
112
115
|
if (Object.keys(newConfig).length > 0) {
|
|
@@ -169,6 +172,7 @@ function extractRootDirectoriesFromIncludes(includes) {
|
|
|
169
172
|
const TRIGGER_NAME = "config-keeper";
|
|
170
173
|
function configKeeper(options = {}) {
|
|
171
174
|
const propertyName = options.propertyName ?? "keep";
|
|
175
|
+
const keepPropertyAtEnd = options.keepPropertyAtEnd ?? true;
|
|
172
176
|
return async (event) => {
|
|
173
177
|
if (!event.isSaved) {
|
|
174
178
|
return;
|
|
@@ -191,14 +195,38 @@ function configKeeper(options = {}) {
|
|
|
191
195
|
} else {
|
|
192
196
|
restoredConfig = { ...event.savedConfig };
|
|
193
197
|
}
|
|
194
|
-
|
|
195
|
-
|
|
198
|
+
let needsSave = false;
|
|
199
|
+
const restorePropertyIfNeeded = (propertyKey) => {
|
|
200
|
+
if (!event.config) return;
|
|
201
|
+
const shouldRestore = (keepMode === propertyKey || keepMode === "both") && event.config[propertyKey] !== void 0;
|
|
202
|
+
if (shouldRestore && restoredConfig[propertyKey] !== event.config[propertyKey]) {
|
|
203
|
+
restoredConfig[propertyKey] = event.config[propertyKey];
|
|
204
|
+
needsSave = true;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
restorePropertyIfNeeded("namespace");
|
|
208
|
+
restorePropertyIfNeeded("path");
|
|
209
|
+
const keepPropertyExistedBefore = event.savedConfig && event.savedConfig[propertyName] !== void 0;
|
|
210
|
+
if (!keepPropertyExistedBefore) {
|
|
211
|
+
needsSave = true;
|
|
212
|
+
}
|
|
213
|
+
if (keepPropertyAtEnd && event.savedConfig && !needsSave) {
|
|
214
|
+
const savedKeys = Object.keys(event.savedConfig);
|
|
215
|
+
const keepIndex = savedKeys.indexOf(propertyName);
|
|
216
|
+
const isKeepAtEnd = keepIndex === savedKeys.length - 1;
|
|
217
|
+
if (!isKeepAtEnd && keepIndex !== -1) {
|
|
218
|
+
needsSave = true;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (!needsSave) {
|
|
222
|
+
return;
|
|
196
223
|
}
|
|
197
|
-
|
|
198
|
-
|
|
224
|
+
const finalConfig = { ...restoredConfig };
|
|
225
|
+
if (keepPropertyAtEnd) {
|
|
226
|
+
delete finalConfig[propertyName];
|
|
199
227
|
}
|
|
200
|
-
|
|
201
|
-
event.save(
|
|
228
|
+
finalConfig[propertyName] = keepMode;
|
|
229
|
+
event.save(finalConfig, TRIGGER_NAME);
|
|
202
230
|
};
|
|
203
231
|
}
|
|
204
232
|
exports.configKeeper = configKeeper;
|
package/algorithms/index.js
CHANGED
|
@@ -17,11 +17,6 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
17
17
|
return async (event) => {
|
|
18
18
|
const { relativePath, langTagConfig } = event;
|
|
19
19
|
const actualFallbackNamespace = fallbackNamespace ?? langTagConfig.collect?.defaultNamespace;
|
|
20
|
-
let finalIgnoreDirectories = [...ignoreDirectories];
|
|
21
|
-
if (ignoreIncludesRootDirectories && langTagConfig.includes) {
|
|
22
|
-
const extractedDirectories = extractRootDirectoriesFromIncludes(langTagConfig.includes);
|
|
23
|
-
finalIgnoreDirectories = [.../* @__PURE__ */ new Set([...finalIgnoreDirectories, ...extractedDirectories])];
|
|
24
|
-
}
|
|
25
20
|
let pathSegments = relativePath.split(sep).filter(Boolean);
|
|
26
21
|
if (pathSegments.length === 0) {
|
|
27
22
|
return;
|
|
@@ -40,8 +35,14 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
40
35
|
}
|
|
41
36
|
return segment;
|
|
42
37
|
}).filter((seg) => seg !== null);
|
|
38
|
+
if (ignoreIncludesRootDirectories && langTagConfig.includes && pathSegments.length > 0) {
|
|
39
|
+
const extractedDirectories = extractRootDirectoriesFromIncludes(langTagConfig.includes);
|
|
40
|
+
if (extractedDirectories.includes(pathSegments[0])) {
|
|
41
|
+
pathSegments = pathSegments.slice(1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
43
44
|
pathSegments = applyStructuredIgnore(pathSegments, ignoreStructured);
|
|
44
|
-
pathSegments = pathSegments.filter((seg) => !
|
|
45
|
+
pathSegments = pathSegments.filter((seg) => !ignoreDirectories.includes(seg));
|
|
45
46
|
let namespace;
|
|
46
47
|
let path;
|
|
47
48
|
if (pathSegments.length >= 1) {
|
|
@@ -88,6 +89,8 @@ function pathBasedConfigGenerator(options = {}) {
|
|
|
88
89
|
}
|
|
89
90
|
if (path) {
|
|
90
91
|
newConfig.path = path;
|
|
92
|
+
} else {
|
|
93
|
+
delete newConfig.path;
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
if (Object.keys(newConfig).length > 0) {
|
|
@@ -150,6 +153,7 @@ function extractRootDirectoriesFromIncludes(includes) {
|
|
|
150
153
|
const TRIGGER_NAME = "config-keeper";
|
|
151
154
|
function configKeeper(options = {}) {
|
|
152
155
|
const propertyName = options.propertyName ?? "keep";
|
|
156
|
+
const keepPropertyAtEnd = options.keepPropertyAtEnd ?? true;
|
|
153
157
|
return async (event) => {
|
|
154
158
|
if (!event.isSaved) {
|
|
155
159
|
return;
|
|
@@ -172,14 +176,38 @@ function configKeeper(options = {}) {
|
|
|
172
176
|
} else {
|
|
173
177
|
restoredConfig = { ...event.savedConfig };
|
|
174
178
|
}
|
|
175
|
-
|
|
176
|
-
|
|
179
|
+
let needsSave = false;
|
|
180
|
+
const restorePropertyIfNeeded = (propertyKey) => {
|
|
181
|
+
if (!event.config) return;
|
|
182
|
+
const shouldRestore = (keepMode === propertyKey || keepMode === "both") && event.config[propertyKey] !== void 0;
|
|
183
|
+
if (shouldRestore && restoredConfig[propertyKey] !== event.config[propertyKey]) {
|
|
184
|
+
restoredConfig[propertyKey] = event.config[propertyKey];
|
|
185
|
+
needsSave = true;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
restorePropertyIfNeeded("namespace");
|
|
189
|
+
restorePropertyIfNeeded("path");
|
|
190
|
+
const keepPropertyExistedBefore = event.savedConfig && event.savedConfig[propertyName] !== void 0;
|
|
191
|
+
if (!keepPropertyExistedBefore) {
|
|
192
|
+
needsSave = true;
|
|
193
|
+
}
|
|
194
|
+
if (keepPropertyAtEnd && event.savedConfig && !needsSave) {
|
|
195
|
+
const savedKeys = Object.keys(event.savedConfig);
|
|
196
|
+
const keepIndex = savedKeys.indexOf(propertyName);
|
|
197
|
+
const isKeepAtEnd = keepIndex === savedKeys.length - 1;
|
|
198
|
+
if (!isKeepAtEnd && keepIndex !== -1) {
|
|
199
|
+
needsSave = true;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (!needsSave) {
|
|
203
|
+
return;
|
|
177
204
|
}
|
|
178
|
-
|
|
179
|
-
|
|
205
|
+
const finalConfig = { ...restoredConfig };
|
|
206
|
+
if (keepPropertyAtEnd) {
|
|
207
|
+
delete finalConfig[propertyName];
|
|
180
208
|
}
|
|
181
|
-
|
|
182
|
-
event.save(
|
|
209
|
+
finalConfig[propertyName] = keepMode;
|
|
210
|
+
event.save(finalConfig, TRIGGER_NAME);
|
|
183
211
|
};
|
|
184
212
|
}
|
|
185
213
|
export {
|
package/package.json
CHANGED
|
@@ -49,7 +49,12 @@ export function processPlaceholders(
|
|
|
49
49
|
return parts.join('');
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
return parts
|
|
52
|
+
return parts.map((part, index) => {
|
|
53
|
+
if (React.isValidElement(part)) {
|
|
54
|
+
return React.cloneElement(part, { key: index });
|
|
55
|
+
}
|
|
56
|
+
return React.createElement(React.Fragment, { key: index }, part);
|
|
57
|
+
}){{#isTypeScript}} as unknown as string{{/isTypeScript}};
|
|
53
58
|
}
|
|
54
59
|
{{/isReact}}
|
|
55
60
|
|