xw-devtool-cli 1.0.23 → 1.0.24
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/README.md +1 -0
- package/README_EN.md +1 -0
- package/package.json +1 -1
- package/src/commands/colorPreview.js +72 -0
- package/src/index.js +5 -0
- package/src/locales/en.js +7 -0
- package/src/locales/zh.js +7 -0
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
- **UUID**:生成 UUID v4。
|
|
29
29
|
- **中文转拼音**:将汉字转换为不带声调的拼音。
|
|
30
30
|
- **颜色转换**:Hex <-> RGB 互转。
|
|
31
|
+
- **颜色预览**:输入颜色并在终端显示颜色条,便于快速视觉确认,同时自动复制 Hex 到剪贴板。
|
|
31
32
|
- **变量格式转换**:支持 CamelCase, PascalCase, SnakeCase, KebabCase, ConstantCase 互转。
|
|
32
33
|
- **哈希计算**:支持 MD5, SHA1, SHA256, SHA512, SM3 算法。
|
|
33
34
|
- **二维码生成**:终端直接显示二维码,支持保存为 PNG 图片(带时间戳文件名)。
|
package/README_EN.md
CHANGED
|
@@ -27,6 +27,7 @@ Key features include: Base64 encoding/decoding, image format conversion, image <
|
|
|
27
27
|
- **UUID**: Generate UUID v4.
|
|
28
28
|
- **Pinyin**: Convert Chinese characters to Pinyin (without tone).
|
|
29
29
|
- **Color Converter**: Hex <-> RGB.
|
|
30
|
+
- **Color Preview**: Enter a color and display a color bar in terminal for quick visual confirmation; Hex is auto-copied to clipboard.
|
|
30
31
|
- **Variable Format**: CamelCase, PascalCase, SnakeCase, KebabCase, ConstantCase.
|
|
31
32
|
- **Hash Calculator**: MD5, SHA1, SHA256, SHA512, SM3.
|
|
32
33
|
- **QR Code**: Display QR codes in terminal, save as PNG.
|
package/package.json
CHANGED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import tinycolor from 'tinycolor2';
|
|
3
|
+
import { copy } from '../utils/clipboard.js';
|
|
4
|
+
import i18next from '../i18n.js';
|
|
5
|
+
// No width/height selection per user request; fixed size preview
|
|
6
|
+
|
|
7
|
+
function blend(fg, bg, alpha) {
|
|
8
|
+
const a = Math.max(0, Math.min(1, alpha ?? 1));
|
|
9
|
+
return {
|
|
10
|
+
r: Math.round(a * fg.r + (1 - a) * bg.r),
|
|
11
|
+
g: Math.round(a * fg.g + (1 - a) * bg.g),
|
|
12
|
+
b: Math.round(a * fg.b + (1 - a) * bg.b),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function printColorBar(rgb, width = 50, height = 2, label = '', alpha = 1) {
|
|
17
|
+
const reset = '\x1b[0m';
|
|
18
|
+
const block = ' ';
|
|
19
|
+
if (label) {
|
|
20
|
+
console.log(label);
|
|
21
|
+
}
|
|
22
|
+
const useChecker = alpha < 1;
|
|
23
|
+
const bg1 = { r: 255, g: 255, b: 255 };
|
|
24
|
+
const bg2 = { r: 204, g: 204, b: 204 };
|
|
25
|
+
for (let row = 0; row < height; row++) {
|
|
26
|
+
let line = '';
|
|
27
|
+
for (let col = 0; col < width; col++) {
|
|
28
|
+
const checker = ((Math.floor(row / 1) + Math.floor(col / 2)) % 2 === 0) ? bg1 : bg2;
|
|
29
|
+
const blended = useChecker ? blend(rgb, checker, alpha) : rgb;
|
|
30
|
+
const bg = `\x1b[48;2;${blended.r};${blended.g};${blended.b}m`;
|
|
31
|
+
line += `${bg}${block}`;
|
|
32
|
+
}
|
|
33
|
+
line += reset;
|
|
34
|
+
console.log(line);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isAllowedColorFormat(val) {
|
|
39
|
+
if (!val || typeof val !== 'string') return false;
|
|
40
|
+
const s = val.trim();
|
|
41
|
+
const hex = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
|
|
42
|
+
const rgb = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/i;
|
|
43
|
+
const rgba = /^rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(?:0|1|0?\.\d+)\s*\)$/i;
|
|
44
|
+
const hsl = /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/i;
|
|
45
|
+
const hsla = /^hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(?:0|1|0?\.\d+)\s*\)$/i;
|
|
46
|
+
return hex.test(s) || rgb.test(s) || rgba.test(s) || hsl.test(s) || hsla.test(s);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function colorPreviewHandler() {
|
|
50
|
+
const { input } = await inquirer.prompt([
|
|
51
|
+
{
|
|
52
|
+
type: 'input',
|
|
53
|
+
name: 'input',
|
|
54
|
+
message: i18next.t('colorPreview.input'),
|
|
55
|
+
validate: (val) => isAllowedColorFormat(val) || i18next.t('colorPreview.invalid')
|
|
56
|
+
}
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
const color = tinycolor(input);
|
|
60
|
+
const rgb = color.toRgb();
|
|
61
|
+
const alpha = typeof rgb.a === 'number' ? rgb.a : 1;
|
|
62
|
+
const hex = alpha < 1 ? color.toHex8String().toUpperCase() : color.toHexString().toUpperCase();
|
|
63
|
+
|
|
64
|
+
const width = 50;
|
|
65
|
+
const height = 2;
|
|
66
|
+
|
|
67
|
+
const label = `${i18next.t('colorPreview.preview')} ${hex} ${color.toRgbString()} ${color.toHslString()}`;
|
|
68
|
+
printColorBar(rgb, width, height, label, alpha);
|
|
69
|
+
|
|
70
|
+
await copy(hex);
|
|
71
|
+
console.log(i18next.t('colorPreview.copied', { value: hex }));
|
|
72
|
+
}
|
package/src/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { mockHandler } from './commands/mock.js';
|
|
|
15
15
|
import { uuidHandler } from './commands/uuid.js';
|
|
16
16
|
import { pinyinHandler } from './commands/pinyin.js';
|
|
17
17
|
import { colorHandler } from './commands/color.js';
|
|
18
|
+
import { colorPreviewHandler } from './commands/colorPreview.js';
|
|
18
19
|
import { variableFormatHandler } from './commands/variableFormat.js';
|
|
19
20
|
import { jsonFormatHandler } from './commands/jsonFormat.js';
|
|
20
21
|
import { hashingHandler } from './commands/hashing.js';
|
|
@@ -65,6 +66,7 @@ function getFeatures() {
|
|
|
65
66
|
{ name: i18next.t('menu.features.timeFormat'), value: 'timeFormat' },
|
|
66
67
|
{ name: i18next.t('menu.features.timeCalc'), value: 'timeCalc' },
|
|
67
68
|
{ name: i18next.t('menu.features.color'), value: 'color' },
|
|
69
|
+
{ name: i18next.t('menu.features.colorPreview'), value: 'colorPreview' },
|
|
68
70
|
{ name: i18next.t('menu.features.uuid'), value: 'uuid' },
|
|
69
71
|
{ name: i18next.t('menu.features.hashing'), value: 'hashing' },
|
|
70
72
|
|
|
@@ -200,6 +202,9 @@ async function handleAction(action) {
|
|
|
200
202
|
case 'color':
|
|
201
203
|
await colorHandler();
|
|
202
204
|
break;
|
|
205
|
+
case 'colorPreview':
|
|
206
|
+
await colorPreviewHandler();
|
|
207
|
+
break;
|
|
203
208
|
case 'variableFormat':
|
|
204
209
|
await variableFormatHandler();
|
|
205
210
|
break;
|
package/src/locales/en.js
CHANGED
|
@@ -22,6 +22,7 @@ export default {
|
|
|
22
22
|
timeFormat: 'Time Format / Timestamp',
|
|
23
23
|
timeCalc: 'Time Calculation (Diff/Offset)',
|
|
24
24
|
color: 'Color Converter (Hex <-> RGB)',
|
|
25
|
+
colorPreview: 'Color Preview',
|
|
25
26
|
uuid: 'Get UUID',
|
|
26
27
|
hashing: 'Hash Calculator (MD5/SHA/SM3)',
|
|
27
28
|
mock: 'Mock Text',
|
|
@@ -37,6 +38,12 @@ export default {
|
|
|
37
38
|
saved: 'Language saved. Please restart the tool or continue using the menu.',
|
|
38
39
|
backToMenu: 'Back to Menu'
|
|
39
40
|
},
|
|
41
|
+
colorPreview: {
|
|
42
|
+
input: 'Enter color (Hex/RGB/HSL):',
|
|
43
|
+
invalid: 'Invalid color format',
|
|
44
|
+
preview: 'Preview:',
|
|
45
|
+
copied: 'Copied to clipboard: {{value}}'
|
|
46
|
+
},
|
|
40
47
|
url: {
|
|
41
48
|
title: 'URL Encode/Decode',
|
|
42
49
|
encode: 'Encode',
|
package/src/locales/zh.js
CHANGED
|
@@ -22,6 +22,7 @@ export default {
|
|
|
22
22
|
timeFormat: '时间格式化 / 时间戳',
|
|
23
23
|
timeCalc: '时间计算 (差值/偏移)',
|
|
24
24
|
color: '颜色转换 (Hex <-> RGB)',
|
|
25
|
+
colorPreview: '颜色预览',
|
|
25
26
|
uuid: '生成 UUID',
|
|
26
27
|
hashing: '哈希计算 (MD5/SHA/SM3)',
|
|
27
28
|
mock: 'Mock 文本生成',
|
|
@@ -37,6 +38,12 @@ export default {
|
|
|
37
38
|
saved: '语言已保存。请继续使用。',
|
|
38
39
|
backToMenu: '返回主菜单'
|
|
39
40
|
},
|
|
41
|
+
colorPreview: {
|
|
42
|
+
input: '输入颜色 (Hex/RGB/HSL):',
|
|
43
|
+
invalid: '颜色格式无效',
|
|
44
|
+
preview: '预览:',
|
|
45
|
+
copied: '已复制到剪贴板: {{value}}'
|
|
46
|
+
},
|
|
40
47
|
url: {
|
|
41
48
|
title: 'URL 编码/解码',
|
|
42
49
|
encode: '编码',
|