i18ntk 2.4.0 โ 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CODE_OF_CONDUCT.md +133 -0
- package/CONTRIBUTING.md +41 -0
- package/FUNDING.md +5 -0
- package/README.md +62 -15
- package/SECURITY.md +52 -0
- package/main/manage/commands/FixerCommand.js +97 -97
- package/main/manage/managers/DebugMenu.js +10 -9
- package/package.json +59 -184
- package/runtime/index.js +14 -8
- package/utils/admin-auth.js +655 -576
- package/utils/config-manager.js +72 -72
- package/utils/env-manager.js +117 -26
- package/utils/i18n-helper.js +50 -49
- package/utils/json-output.js +13 -12
- package/utils/logger.js +7 -6
- package/utils/prompt-helper.js +44 -41
- package/utils/secure-errors.js +156 -154
- package/utils/security.js +235 -233
- package/utils/setup-enforcer.js +110 -109
- package/utils/terminal-icons.js +164 -163
- package/settings/i18ntk-config.json +0 -283
- package/utils/admin-pin.js +0 -520
- package/utils/arg-parser.js +0 -40
- package/utils/cli-args.js +0 -210
- package/utils/mini-commander.js +0 -179
- package/utils/missing-key-validator.js +0 -858
- package/utils/path-utils.js +0 -33
- package/utils/performance-optimizer.js +0 -246
- package/utils/prompt-new.js +0 -55
- package/utils/promptPin.js +0 -76
- package/utils/safe-json.js +0 -40
- package/utils/secure-backup.js +0 -340
- package/utils/security-check-improved.js +0 -393
- package/utils/security-config.js +0 -239
- package/utils/setup-validator.js +0 -717
- package/utils/ultra-performance-optimizer.js +0 -352
package/utils/setup-enforcer.js
CHANGED
|
@@ -9,25 +9,26 @@
|
|
|
9
9
|
|
|
10
10
|
const { getIcon } = require('./terminal-icons');
|
|
11
11
|
const fs = require('fs');
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const { blue, yellow, gray, cyan, green, red } = require('./colors-new');
|
|
14
|
-
const SecurityUtils = require('./security');
|
|
15
|
-
const I18nSetupModule = require('../main/i18ntk-setup');
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { blue, yellow, gray, cyan, green, red } = require('./colors-new');
|
|
14
|
+
const SecurityUtils = require('./security');
|
|
15
|
+
const I18nSetupModule = require('../main/i18ntk-setup');
|
|
16
|
+
const { envManager } = require('./env-manager');
|
|
17
|
+
|
|
18
|
+
async function runSetupModule() {
|
|
19
|
+
if (I18nSetupModule && typeof I18nSetupModule.run === 'function') {
|
|
20
|
+
return await I18nSetupModule.run();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (typeof I18nSetupModule === 'function') {
|
|
24
|
+
const setupManager = new I18nSetupModule();
|
|
25
|
+
if (typeof setupManager.setup === 'function') {
|
|
26
|
+
return await setupManager.setup();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throw new Error('Setup module does not expose a runnable entrypoint');
|
|
31
|
+
}
|
|
31
32
|
|
|
32
33
|
class SetupEnforcer {
|
|
33
34
|
static _setupCheckInProgress = false;
|
|
@@ -40,30 +41,30 @@ class SetupEnforcer {
|
|
|
40
41
|
static isNonInteractive() {
|
|
41
42
|
return !process.stdout.isTTY ||
|
|
42
43
|
!process.stdin.isTTY ||
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
envManager.getBoolean('CI') ||
|
|
45
|
+
envManager.getBoolean('CONTINUOUS_INTEGRATION') ||
|
|
46
|
+
envManager.get('NODE_ENV') === 'test' ||
|
|
47
|
+
envManager.get('npm_lifecycle_event') === 'test' ||
|
|
48
|
+
envManager.getBoolean('NO_INTERACTIVE');
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
static checkSetupComplete() {
|
|
51
|
-
// Avoid circular dependency - use direct path resolution
|
|
52
|
-
const path = require('path');
|
|
53
|
-
const configPath = path.join(process.cwd(), '.i18ntk-config');
|
|
54
|
-
const exists = SecurityUtils.safeExistsSync(configPath);
|
|
55
|
-
if (!exists) {
|
|
56
|
-
this.handleMissingSetup();
|
|
57
|
-
return;
|
|
51
|
+
static checkSetupComplete() {
|
|
52
|
+
// Avoid circular dependency - use direct path resolution
|
|
53
|
+
const path = require('path');
|
|
54
|
+
const configPath = path.join(process.cwd(), '.i18ntk-config');
|
|
55
|
+
const exists = SecurityUtils.safeExistsSync(configPath);
|
|
56
|
+
if (!exists) {
|
|
57
|
+
this.handleMissingSetup();
|
|
58
|
+
return;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
try {
|
|
61
|
-
const configRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
62
|
-
const config = SecurityUtils.safeParseJSON(configRaw);
|
|
63
|
-
if (!config || typeof config !== 'object') {
|
|
64
|
-
this.handleInvalidConfig();
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
62
|
+
const configRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
63
|
+
const config = SecurityUtils.safeParseJSON(configRaw);
|
|
64
|
+
if (!config || typeof config !== 'object') {
|
|
65
|
+
this.handleInvalidConfig();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
67
68
|
|
|
68
69
|
// Check if setup has been explicitly marked as completed
|
|
69
70
|
if (config.setup && config.setup.completed === true) {
|
|
@@ -123,22 +124,22 @@ class SetupEnforcer {
|
|
|
123
124
|
process.exit(0);
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
console.log(green(`${getIcon('rocket')} Running setup...`));
|
|
127
|
-
|
|
128
|
-
try {
|
|
129
|
-
// Import once at module scope and execute the stable entrypoint.
|
|
130
|
-
const setupPath = path.join(__dirname, '..', 'main', 'i18ntk-setup.js');
|
|
131
|
-
if (!SecurityUtils.safeExistsSync(setupPath)) {
|
|
132
|
-
console.error(red(`${getIcon('cross')} Setup script not found. Please run:`));
|
|
133
|
-
console.error(cyan(' npm run i18ntk-setup'));
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
await runSetupModule();
|
|
137
|
-
console.log(gray('You can now run your original command.'));
|
|
138
|
-
resolve(true);
|
|
139
|
-
} catch (error) {
|
|
140
|
-
console.error(red(`${getIcon('cross')} Error running setup:`), error.message);
|
|
141
|
-
console.error(cyan(' npm run i18ntk-setup'));
|
|
127
|
+
console.log(green(`${getIcon('rocket')} Running setup...`));
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
// Import once at module scope and execute the stable entrypoint.
|
|
131
|
+
const setupPath = path.join(__dirname, '..', 'main', 'i18ntk-setup.js');
|
|
132
|
+
if (!SecurityUtils.safeExistsSync(setupPath)) {
|
|
133
|
+
console.error(red(`${getIcon('cross')} Setup script not found. Please run:`));
|
|
134
|
+
console.error(cyan(' npm run i18ntk-setup'));
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
await runSetupModule();
|
|
138
|
+
console.log(gray('You can now run your original command.'));
|
|
139
|
+
resolve(true);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error(red(`${getIcon('cross')} Error running setup:`), error.message);
|
|
142
|
+
console.error(cyan(' npm run i18ntk-setup'));
|
|
142
143
|
process.exit(1);
|
|
143
144
|
}
|
|
144
145
|
});
|
|
@@ -184,20 +185,20 @@ static async handleIncompleteSetup() {
|
|
|
184
185
|
process.exit(0);
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
console.log(green(`${getIcon('rocket')} Running setup...`));
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
const setupPath = path.join(__dirname, '..', 'main', 'i18ntk-setup.js');
|
|
191
|
-
if (!SecurityUtils.safeExistsSync(setupPath)) {
|
|
192
|
-
console.error(red(`${getIcon('cross')} Setup script not found. Please run:`));
|
|
193
|
-
console.error(cyan(' npm run i18ntk-setup'));
|
|
194
|
-
process.exit(1);
|
|
195
|
-
}
|
|
196
|
-
await runSetupModule();
|
|
197
|
-
resolve(true);
|
|
198
|
-
} catch (error) {
|
|
199
|
-
console.error(red(`${getIcon('cross')} Error running setup:`), error.message);
|
|
200
|
-
process.exit(1);
|
|
188
|
+
console.log(green(`${getIcon('rocket')} Running setup...`));
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
const setupPath = path.join(__dirname, '..', 'main', 'i18ntk-setup.js');
|
|
192
|
+
if (!SecurityUtils.safeExistsSync(setupPath)) {
|
|
193
|
+
console.error(red(`${getIcon('cross')} Setup script not found. Please run:`));
|
|
194
|
+
console.error(cyan(' npm run i18ntk-setup'));
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
197
|
+
await runSetupModule();
|
|
198
|
+
resolve(true);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.error(red(`${getIcon('cross')} Error running setup:`), error.message);
|
|
201
|
+
process.exit(1);
|
|
201
202
|
}
|
|
202
203
|
});
|
|
203
204
|
});
|
|
@@ -242,20 +243,20 @@ static async handleInvalidConfig() {
|
|
|
242
243
|
process.exit(0);
|
|
243
244
|
}
|
|
244
245
|
|
|
245
|
-
console.log(green(`${getIcon('rocket')} Running setup...`));
|
|
246
|
-
|
|
247
|
-
try {
|
|
248
|
-
const setupPath = path.join(__dirname, '..', 'main', 'i18ntk-setup.js');
|
|
249
|
-
if (!SecurityUtils.safeExistsSync(setupPath)) {
|
|
250
|
-
console.error(red(`${getIcon('cross')} Setup script not found. Please run:`));
|
|
251
|
-
console.error(cyan(' npm run i18ntk-setup'));
|
|
252
|
-
process.exit(1);
|
|
253
|
-
}
|
|
254
|
-
await runSetupModule();
|
|
255
|
-
resolve(true);
|
|
256
|
-
} catch (error) {
|
|
257
|
-
console.error(red(`${getIcon('cross')} Error running setup:`), error.message);
|
|
258
|
-
process.exit(1);
|
|
246
|
+
console.log(green(`${getIcon('rocket')} Running setup...`));
|
|
247
|
+
|
|
248
|
+
try {
|
|
249
|
+
const setupPath = path.join(__dirname, '..', 'main', 'i18ntk-setup.js');
|
|
250
|
+
if (!SecurityUtils.safeExistsSync(setupPath)) {
|
|
251
|
+
console.error(red(`${getIcon('cross')} Setup script not found. Please run:`));
|
|
252
|
+
console.error(cyan(' npm run i18ntk-setup'));
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
await runSetupModule();
|
|
256
|
+
resolve(true);
|
|
257
|
+
} catch (error) {
|
|
258
|
+
console.error(red(`${getIcon('cross')} Error running setup:`), error.message);
|
|
259
|
+
process.exit(1);
|
|
259
260
|
}
|
|
260
261
|
});
|
|
261
262
|
});
|
|
@@ -273,28 +274,28 @@ static async handleInvalidConfig() {
|
|
|
273
274
|
SetupEnforcer._setupCheckPromise = new Promise(async (resolve, reject) => {
|
|
274
275
|
try {
|
|
275
276
|
// Avoid circular dependency - use direct path resolution
|
|
276
|
-
const path = require('path');
|
|
277
|
-
const configPath = path.join(process.cwd(), '.i18ntk-config');
|
|
278
|
-
const exists = SecurityUtils.safeExistsSync(configPath);
|
|
279
|
-
if (!exists) {
|
|
280
|
-
await SetupEnforcer.handleMissingSetup();
|
|
281
|
-
// After setup is done, re-check the config
|
|
282
|
-
const existsAfter = SecurityUtils.safeExistsSync(configPath);
|
|
283
|
-
if (existsAfter) {
|
|
284
|
-
resolve(true);
|
|
285
|
-
} else {
|
|
277
|
+
const path = require('path');
|
|
278
|
+
const configPath = path.join(process.cwd(), '.i18ntk-config');
|
|
279
|
+
const exists = SecurityUtils.safeExistsSync(configPath);
|
|
280
|
+
if (!exists) {
|
|
281
|
+
await SetupEnforcer.handleMissingSetup();
|
|
282
|
+
// After setup is done, re-check the config
|
|
283
|
+
const existsAfter = SecurityUtils.safeExistsSync(configPath);
|
|
284
|
+
if (existsAfter) {
|
|
285
|
+
resolve(true);
|
|
286
|
+
} else {
|
|
286
287
|
process.exit(0);
|
|
287
288
|
}
|
|
288
289
|
return;
|
|
289
290
|
}
|
|
290
291
|
|
|
291
292
|
try {
|
|
292
|
-
const configRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
293
|
-
const config = SecurityUtils.safeParseJSON(configRaw);
|
|
294
|
-
if (!config || typeof config !== 'object') {
|
|
295
|
-
await SetupEnforcer.handleInvalidConfig();
|
|
296
|
-
process.exit(0);
|
|
297
|
-
}
|
|
293
|
+
const configRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
294
|
+
const config = SecurityUtils.safeParseJSON(configRaw);
|
|
295
|
+
if (!config || typeof config !== 'object') {
|
|
296
|
+
await SetupEnforcer.handleInvalidConfig();
|
|
297
|
+
process.exit(0);
|
|
298
|
+
}
|
|
298
299
|
|
|
299
300
|
// Check if setup has been explicitly marked as completed
|
|
300
301
|
if (config.setup && config.setup.completed === true) {
|
|
@@ -306,11 +307,11 @@ static async handleInvalidConfig() {
|
|
|
306
307
|
if (!config.version || !config.sourceDir || (!config.detectedFramework && !(config.framework && config.framework.detected !== false))) {
|
|
307
308
|
await SetupEnforcer.handleIncompleteSetup();
|
|
308
309
|
// After setup is done, re-check the config
|
|
309
|
-
const newConfigRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
310
|
-
const newConfig = SecurityUtils.safeParseJSON(newConfigRaw);
|
|
311
|
-
if (!newConfig || typeof newConfig !== 'object') {
|
|
312
|
-
process.exit(0);
|
|
313
|
-
}
|
|
310
|
+
const newConfigRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
311
|
+
const newConfig = SecurityUtils.safeParseJSON(newConfigRaw);
|
|
312
|
+
if (!newConfig || typeof newConfig !== 'object') {
|
|
313
|
+
process.exit(0);
|
|
314
|
+
}
|
|
314
315
|
if (newConfig.setup && newConfig.setup.completed === true) {
|
|
315
316
|
resolve(true);
|
|
316
317
|
} else if (newConfig.version && newConfig.sourceDir && (newConfig.detectedFramework || (newConfig.framework && newConfig.framework.detected !== false))) {
|
|
@@ -326,11 +327,11 @@ static async handleInvalidConfig() {
|
|
|
326
327
|
await SetupEnforcer.handleInvalidConfig();
|
|
327
328
|
// After setup is done, re-check the config
|
|
328
329
|
try {
|
|
329
|
-
const newConfigRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
330
|
-
const newConfig = SecurityUtils.safeParseJSON(newConfigRaw);
|
|
331
|
-
if (!newConfig || typeof newConfig !== 'object') {
|
|
332
|
-
process.exit(0);
|
|
333
|
-
}
|
|
330
|
+
const newConfigRaw = SecurityUtils.safeReadFileSync(configPath, path.dirname(configPath), 'utf8');
|
|
331
|
+
const newConfig = SecurityUtils.safeParseJSON(newConfigRaw);
|
|
332
|
+
if (!newConfig || typeof newConfig !== 'object') {
|
|
333
|
+
process.exit(0);
|
|
334
|
+
}
|
|
334
335
|
if (newConfig.setup && newConfig.setup.completed === true) {
|
|
335
336
|
resolve(true);
|
|
336
337
|
} else if (newConfig.version && newConfig.sourceDir && (newConfig.detectedFramework || (newConfig.framework && newConfig.framework.detected !== false))) {
|
|
@@ -353,4 +354,4 @@ static async handleInvalidConfig() {
|
|
|
353
354
|
}
|
|
354
355
|
}
|
|
355
356
|
|
|
356
|
-
module.exports = SetupEnforcer;
|
|
357
|
+
module.exports = SetupEnforcer;
|
package/utils/terminal-icons.js
CHANGED
|
@@ -1,163 +1,164 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Terminal Icons Utility
|
|
3
|
-
*
|
|
4
|
-
* Provides Unicode emoji support with fallbacks for terminals that don't support them.
|
|
5
|
-
* Automatically detects terminal capabilities and provides appropriate symbols.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const os = require('os');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
*
|
|
115
|
-
* @
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
*
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
*
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
*
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
//
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
//
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Icons Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides Unicode emoji support with fallbacks for terminals that don't support them.
|
|
5
|
+
* Automatically detects terminal capabilities and provides appropriate symbols.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const os = require('os');
|
|
9
|
+
const { envManager } = require('./env-manager');
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
// Detect if terminal supports Unicode/emoji
|
|
13
|
+
function supportsUnicode() {
|
|
14
|
+
// Check if we're on Windows
|
|
15
|
+
if (os.platform() !== 'win32') {
|
|
16
|
+
return true; // Assume Unix-like systems support Unicode
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Check if we're in a TTY
|
|
20
|
+
if (!process.stdout.isTTY) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
// Try to detect Windows Terminal, VS Code terminal, or other modern terminals
|
|
26
|
+
const terminal = envManager.get('TERM_PROGRAM') || envManager.get('WT_SESSION') || '';
|
|
27
|
+
|
|
28
|
+
// Modern terminals that support Unicode
|
|
29
|
+
const unicodeTerminals = [
|
|
30
|
+
'vscode', // VS Code integrated terminal
|
|
31
|
+
'hyper', // Hyper terminal
|
|
32
|
+
'tabby', // Tabby terminal
|
|
33
|
+
'fluent-terminal', // Fluent Terminal
|
|
34
|
+
'windows-terminal', // Windows Terminal
|
|
35
|
+
'wt' // Windows Terminal (WT_SESSION)
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
if (unicodeTerminals.some(term => terminal.toLowerCase().includes(term))) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Check for Windows Terminal environment variable
|
|
43
|
+
if (envManager.get('WT_SESSION')) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check for modern PowerShell or pwsh
|
|
48
|
+
if (envManager.get('PSModulePath') || envManager.get('POWERSHELL_EDITION')) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Default to false for older Windows terminals
|
|
53
|
+
return false;
|
|
54
|
+
|
|
55
|
+
} catch (error) {
|
|
56
|
+
// If detection fails, default to safe option
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Icon definitions with fallbacks
|
|
62
|
+
const ICONS = {
|
|
63
|
+
// Setup and configuration
|
|
64
|
+
wrench: { emoji: '๐ง', fallback: '[SETUP]' },
|
|
65
|
+
gear: { emoji: 'โ๏ธ', fallback: '[CONFIG]' },
|
|
66
|
+
checkmark: { emoji: 'โ
', fallback: '[OK]' },
|
|
67
|
+
cross: { emoji: 'โ', fallback: '[ERROR]' },
|
|
68
|
+
warning: { emoji: 'โ ๏ธ', fallback: '[WARN]' },
|
|
69
|
+
info: { emoji: 'โน๏ธ', fallback: '[INFO]' },
|
|
70
|
+
|
|
71
|
+
// Actions
|
|
72
|
+
rocket: { emoji: '๐', fallback: '[START]' },
|
|
73
|
+
search: { emoji: '๐', fallback: '[SEARCH]' },
|
|
74
|
+
analyze: { emoji: '๐', fallback: '[ANALYZE]' },
|
|
75
|
+
fix: { emoji: '๐ง', fallback: '[FIX]' },
|
|
76
|
+
complete: { emoji: '๐', fallback: '[DONE]' },
|
|
77
|
+
clean: { emoji: '๐งน', fallback: '[CLEAN]' },
|
|
78
|
+
|
|
79
|
+
// Status
|
|
80
|
+
success: { emoji: 'โ
', fallback: '[SUCCESS]' },
|
|
81
|
+
error: { emoji: 'โ', fallback: '[ERROR]' },
|
|
82
|
+
pending: { emoji: 'โณ', fallback: '[PENDING]' },
|
|
83
|
+
processing: { emoji: 'โ๏ธ', fallback: '[WORKING]' },
|
|
84
|
+
|
|
85
|
+
// Files and directories
|
|
86
|
+
file: { emoji: '๐', fallback: '[FILE]' },
|
|
87
|
+
folder: { emoji: '๐', fallback: '[DIR]' },
|
|
88
|
+
report: { emoji: '๐', fallback: '[REPORT]' },
|
|
89
|
+
backup: { emoji: '๐พ', fallback: '[BACKUP]' },
|
|
90
|
+
|
|
91
|
+
// Languages and frameworks
|
|
92
|
+
javascript: { emoji: '๐จ', fallback: '[JS]' },
|
|
93
|
+
python: { emoji: '๐', fallback: '[PY]' },
|
|
94
|
+
java: { emoji: 'โ', fallback: '[JAVA]' },
|
|
95
|
+
php: { emoji: '๐', fallback: '[PHP]' },
|
|
96
|
+
go: { emoji: '๐น', fallback: '[GO]' },
|
|
97
|
+
react: { emoji: 'โ๏ธ', fallback: '[REACT]' },
|
|
98
|
+
vue: { emoji: '๐', fallback: '[VUE]' },
|
|
99
|
+
angular: { emoji: '๐
ฐ๏ธ', fallback: '[ANGULAR]' },
|
|
100
|
+
|
|
101
|
+
// UI elements
|
|
102
|
+
bullet: { emoji: 'โข', fallback: '-' },
|
|
103
|
+
arrow: { emoji: 'โ', fallback: '->' },
|
|
104
|
+
separator: { emoji: 'โ', fallback: '=' },
|
|
105
|
+
corner: { emoji: 'โ', fallback: '+' },
|
|
106
|
+
line: { emoji: 'โ', fallback: '|' },
|
|
107
|
+
end: { emoji: 'โ', fallback: '+' }
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Cache the Unicode support detection
|
|
111
|
+
const _supportsUnicode = supportsUnicode();
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get the appropriate icon for the current terminal
|
|
115
|
+
* @param {string} iconName - Name of the icon from ICONS
|
|
116
|
+
* @returns {string} - The icon or fallback text
|
|
117
|
+
*/
|
|
118
|
+
function getIcon(iconName) {
|
|
119
|
+
const icon = ICONS[iconName];
|
|
120
|
+
if (!icon) {
|
|
121
|
+
return `[${iconName.toUpperCase()}]`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return _supportsUnicode ? icon.emoji : icon.fallback;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get all available icon names
|
|
129
|
+
* @returns {string[]} - Array of icon names
|
|
130
|
+
*/
|
|
131
|
+
function getAvailableIcons() {
|
|
132
|
+
return Object.keys(ICONS);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Check if terminal supports Unicode
|
|
137
|
+
* @returns {boolean} - True if Unicode is supported
|
|
138
|
+
*/
|
|
139
|
+
function isUnicodeSupported() {
|
|
140
|
+
return _supportsUnicode;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Force enable/disable Unicode support (for testing)
|
|
145
|
+
* @param {boolean} enabled - Whether to enable Unicode
|
|
146
|
+
*/
|
|
147
|
+
function setUnicodeSupport(enabled) {
|
|
148
|
+
// This is mainly for testing purposes
|
|
149
|
+
// In production, detection should be automatic
|
|
150
|
+
if (typeof enabled === 'boolean') {
|
|
151
|
+
// Note: This won't actually change terminal capabilities,
|
|
152
|
+
// just the detection result for this module
|
|
153
|
+
console.warn('Warning: setUnicodeSupport() only affects this module\'s detection, not actual terminal capabilities');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Export functions
|
|
158
|
+
module.exports = {
|
|
159
|
+
getIcon,
|
|
160
|
+
getAvailableIcons,
|
|
161
|
+
isUnicodeSupported,
|
|
162
|
+
setUnicodeSupport,
|
|
163
|
+
ICONS
|
|
164
|
+
};
|