nexfep 0.4.0 → 0.4.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/README-CN.md CHANGED
@@ -522,7 +522,7 @@ nexfep build -u 7
522
522
  注意不要包括外层的 `metadata` 字段,直接包含内部字段即可,例如:
523
523
 
524
524
  ```json
525
- { "1033": { "FileVersion": ... } }
525
+ { "1033": { "FileVersion": "..." } }
526
526
  ```
527
527
 
528
528
  ## API
package/README.md CHANGED
@@ -522,7 +522,7 @@ For `metadata` parameter, you can refer to [Nexfpack documentation](https://gith
522
522
  Please do not include the outer `metadata` field, just the internal fields. Like this:
523
523
 
524
524
  ```json
525
- { "1033": { "FileVersion": ... } }
525
+ { "1033": { "FileVersion": "..." } }
526
526
  ```
527
527
 
528
528
  ## API
package/package.json CHANGED
@@ -17,7 +17,7 @@
17
17
  "webview",
18
18
  "typescript"
19
19
  ],
20
- "version": "0.4.0",
20
+ "version": "0.4.2",
21
21
  "type": "module",
22
22
  "main": "./index.js",
23
23
  "scripts": {
@@ -40,7 +40,9 @@
40
40
  "src/Application.js",
41
41
  "src/Application.d.ts",
42
42
  "src/Tray.js",
43
- "src/Tray.d.ts"
43
+ "src/Tray.d.ts",
44
+ "src/Logger.js",
45
+ "src/Logger.d.ts"
44
46
  ],
45
47
  "dependencies": {
46
48
  "@webviewjs/webview": "0.4.0"
@@ -0,0 +1,12 @@
1
+ declare class Logger {
2
+ logFilePath: string | undefined;
3
+ constructor(logFilePath?: string);
4
+ __formatConsoleArgs(args: string[]): string;
5
+ __printLog(winid: number, type: string, args: string[], colorANSI?: string, colorRESET?: string): void;
6
+ log(args: string[] | string): void;
7
+ error(args: string[] | string): void;
8
+ warn(args: string[] | string): void;
9
+ info(args: string[] | string): void;
10
+ debug(args: string[] | string): void;
11
+ }
12
+ export { Logger };
package/src/Logger.js ADDED
@@ -0,0 +1,190 @@
1
+ import fs from 'fs';
2
+ class Logger {
3
+ logFilePath;
4
+ constructor(logFilePath) {
5
+ this.logFilePath = logFilePath;
6
+ }
7
+ __formatConsoleArgs(args) {
8
+ if (!Array.isArray(args) || args.length === 0)
9
+ return '';
10
+ const template = args[0];
11
+ if (typeof template !== 'string' || !template.includes('%c')) {
12
+ return args.map(String).join(' ');
13
+ }
14
+ const RESET = '\x1b[0m';
15
+ const parts = template.split(/(%c)/);
16
+ let styleArgIndex = 1;
17
+ let result = '';
18
+ let currentAnsiStyle = '';
19
+ // 命名前景色映射
20
+ const fgColors = {
21
+ black: '\x1b[30m',
22
+ red: '\x1b[31m',
23
+ green: '\x1b[32m',
24
+ yellow: '\x1b[33m',
25
+ blue: '\x1b[34m',
26
+ magenta: '\x1b[35m',
27
+ cyan: '\x1b[36m',
28
+ white: '\x1b[37m',
29
+ gray: '\x1b[90m',
30
+ grey: '\x1b[90m',
31
+ lightred: '\x1b[91m',
32
+ lightgreen: '\x1b[92m',
33
+ lightyellow: '\x1b[93m',
34
+ lightblue: '\x1b[94m',
35
+ lightmagenta: '\x1b[95m',
36
+ lightcyan: '\x1b[96m',
37
+ lightwhite: '\x1b[97m',
38
+ };
39
+ // 命名背景色映射
40
+ const bgColors = {
41
+ black: '\x1b[40m',
42
+ red: '\x1b[41m',
43
+ green: '\x1b[42m',
44
+ yellow: '\x1b[43m',
45
+ blue: '\x1b[44m',
46
+ magenta: '\x1b[45m',
47
+ cyan: '\x1b[46m',
48
+ white: '\x1b[47m',
49
+ };
50
+ // 文字样式:加粗、斜体、下划线
51
+ const textStyles = {
52
+ 'bold': '\x1b[1m',
53
+ 'font-weight:bold': '\x1b[1m',
54
+ 'italic': '\x1b[3m',
55
+ 'font-style:italic': '\x1b[3m',
56
+ 'underline': '\x1b[4m',
57
+ 'text-decoration:underline': '\x1b[4m',
58
+ 'none': RESET,
59
+ };
60
+ /** hex/rgb 转 ANSI 24位真彩色 */
61
+ function colorToAnsi(colorVal, isBg = false) {
62
+ let val = colorVal.trim().toLowerCase();
63
+ // 命名色
64
+ const colorMap = isBg ? bgColors : fgColors;
65
+ if (colorMap[val])
66
+ return colorMap[val];
67
+ // hex #fff #ffffff
68
+ const hexReg = /^#([0-9a-f]{3}|[0-9a-f]{6})$/;
69
+ if (hexReg.test(val)) {
70
+ let hex = val.replace('#', '');
71
+ if (hex.length === 3)
72
+ hex = hex.split('').map(c => c + c).join('');
73
+ const r = parseInt(hex.slice(0, 2), 16);
74
+ const g = parseInt(hex.slice(2, 4), 16);
75
+ const b = parseInt(hex.slice(4, 6), 16);
76
+ return isBg ? `\x1b[48;2;${r};${g};${b}m` : `\x1b[38;2;${r};${g};${b}m`;
77
+ }
78
+ // rgb(r,g,b)
79
+ const rgbReg = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
80
+ const rgbMatch = val.match(rgbReg);
81
+ if (rgbMatch) {
82
+ const [, r, g, b] = rgbMatch;
83
+ return isBg ? `\x1b[48;2;${r};${g};${b}m` : `\x1b[38;2;${r};${g};${b}m`;
84
+ }
85
+ return '';
86
+ }
87
+ /** 解析CSS样式字符串为ANSI序列 */
88
+ function parseColorStyle(styleStr) {
89
+ if (!styleStr)
90
+ return RESET;
91
+ let ansi = '';
92
+ const rules = styleStr.split(';').map(s => s.trim()).filter(Boolean);
93
+ for (const rule of rules) {
94
+ const [prop, ...rest] = rule.split(':');
95
+ const propKey = prop.trim().toLowerCase();
96
+ const value = rest.join(':').trim().toLowerCase();
97
+ // 文字样式
98
+ if (textStyles[`${propKey}:${value}`] || textStyles[value]) {
99
+ ansi += textStyles[`${propKey}:${value}`] ?? textStyles[value];
100
+ continue;
101
+ }
102
+ // 前景色
103
+ if (propKey === 'color') {
104
+ ansi += colorToAnsi(value, false);
105
+ continue;
106
+ }
107
+ // 背景色
108
+ if (propKey === 'background' || propKey === 'background-color') {
109
+ ansi += colorToAnsi(value, true);
110
+ continue;
111
+ }
112
+ }
113
+ return ansi;
114
+ }
115
+ for (const segment of parts) {
116
+ if (segment === '%c') {
117
+ // 取出下一个样式参数,参数不足则重置样式
118
+ const styleStr = args[styleArgIndex];
119
+ styleArgIndex++;
120
+ currentAnsiStyle = parseColorStyle(String(styleStr ?? ''));
121
+ }
122
+ else {
123
+ if (segment === '')
124
+ continue;
125
+ if (currentAnsiStyle) {
126
+ result += currentAnsiStyle + segment;
127
+ }
128
+ else {
129
+ result += segment;
130
+ }
131
+ }
132
+ }
133
+ // 全局末尾统一重置,防止后续日志被染色
134
+ if (currentAnsiStyle)
135
+ result += RESET;
136
+ // 剩余非样式参数直接拼接
137
+ const extraArgs = args.slice(styleArgIndex);
138
+ if (extraArgs.length) {
139
+ result += ' ' + extraArgs.map(String).join(' ');
140
+ }
141
+ return result;
142
+ }
143
+ __printLog(winid, type, args, colorANSI, colorRESET) {
144
+ if (this.logFilePath) {
145
+ fs.appendFileSync(this.logFilePath, `${new Date().toISOString()} [${winid}] ${type}: ${args.join(' ')}\n`);
146
+ }
147
+ console.log(`${colorANSI || ''}[${winid}] ${type}:${colorRESET || ''}`, this.__formatConsoleArgs(args));
148
+ }
149
+ log(args) {
150
+ if (Array.isArray(args)) {
151
+ this.__printLog(0, 'Log', args);
152
+ }
153
+ else {
154
+ this.__printLog(0, 'Log', [args]);
155
+ }
156
+ }
157
+ error(args) {
158
+ if (Array.isArray(args)) {
159
+ this.__printLog(0, 'Error', args, '\x1b[31m', '\x1b[0m');
160
+ }
161
+ else {
162
+ this.__printLog(0, 'Error', [args], '\x1b[31m', '\x1b[0m');
163
+ }
164
+ }
165
+ warn(args) {
166
+ if (Array.isArray(args)) {
167
+ this.__printLog(0, 'Warn', args, '\x1b[33m', '\x1b[0m');
168
+ }
169
+ else {
170
+ this.__printLog(0, 'Warn', [args], '\x1b[33m', '\x1b[0m');
171
+ }
172
+ }
173
+ info(args) {
174
+ if (Array.isArray(args)) {
175
+ this.__printLog(0, 'Info', args, '\x1b[34m', '\x1b[0m');
176
+ }
177
+ else {
178
+ this.__printLog(0, 'Info', [args], '\x1b[34m', '\x1b[0m');
179
+ }
180
+ }
181
+ debug(args) {
182
+ if (Array.isArray(args)) {
183
+ this.__printLog(0, 'Debug', args, '\x1b[90m', '\x1b[0m');
184
+ }
185
+ else {
186
+ this.__printLog(0, 'Debug', [args], '\x1b[90m', '\x1b[0m');
187
+ }
188
+ }
189
+ }
190
+ export { Logger };