@willwade/aac-processors 0.1.20 → 0.2.0
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/dist/browser/core/baseProcessor.js +4 -0
- package/dist/browser/processors/applePanelsProcessor.js +33 -40
- package/dist/browser/processors/astericsGridProcessor.js +31 -26
- package/dist/browser/processors/dotProcessor.js +11 -12
- package/dist/browser/processors/gridset/colorUtils.js +354 -0
- package/dist/browser/processors/gridset/helpers.js +60 -53
- package/dist/browser/processors/gridset/index.js +61 -0
- package/dist/browser/processors/gridset/styleHelpers.js +205 -0
- package/dist/browser/processors/gridset/symbolExtractor.js +331 -0
- package/dist/browser/processors/gridset/symbolSearch.js +248 -0
- package/dist/browser/processors/gridset/symbols.js +39 -72
- package/dist/browser/processors/gridsetProcessor.js +39 -48
- package/dist/browser/processors/obfProcessor.js +39 -53
- package/dist/browser/processors/opmlProcessor.js +11 -12
- package/dist/browser/processors/snap/helpers.js +57 -49
- package/dist/browser/processors/snapProcessor.js +48 -51
- package/dist/browser/processors/touchchatProcessor.js +60 -52
- package/dist/browser/utilities/analytics/history.js +24 -18
- package/dist/browser/utilities/analytics/metrics/comparison.js +16 -16
- package/dist/browser/utilities/analytics/metrics/vocabulary.js +2 -2
- package/dist/browser/utilities/analytics/reference/browser.js +16 -16
- package/dist/browser/utilities/analytics/reference/index.js +44 -35
- package/dist/browser/utils/io.js +78 -21
- package/dist/browser/utils/sqlite.js +8 -10
- package/dist/browser/utils/zip.js +43 -43
- package/dist/browser/validation/baseValidator.js +5 -0
- package/dist/browser/validation/gridsetValidator.js +12 -20
- package/dist/browser/validation/obfValidator.js +6 -5
- package/dist/browser/validation/snapValidator.js +11 -7
- package/dist/browser/validation/touchChatValidator.js +23 -13
- package/dist/cli/index.js +22 -24
- package/dist/core/baseProcessor.d.ts +7 -7
- package/dist/core/baseProcessor.js +4 -0
- package/dist/processors/applePanelsProcessor.js +32 -39
- package/dist/processors/astericsGridProcessor.d.ts +4 -4
- package/dist/processors/astericsGridProcessor.js +30 -25
- package/dist/processors/dotProcessor.js +10 -11
- package/dist/processors/excelProcessor.d.ts +3 -3
- package/dist/processors/excelProcessor.js +14 -20
- package/dist/processors/gridset/helpers.d.ts +12 -14
- package/dist/processors/gridset/helpers.js +60 -79
- package/dist/processors/gridset/imageDebug.d.ts +3 -5
- package/dist/processors/gridset/imageDebug.js +4 -4
- package/dist/processors/gridset/password.d.ts +1 -1
- package/dist/processors/gridset/symbolExtractor.d.ts +5 -3
- package/dist/processors/gridset/symbolExtractor.js +15 -38
- package/dist/processors/gridset/symbolSearch.d.ts +11 -10
- package/dist/processors/gridset/symbolSearch.js +29 -51
- package/dist/processors/gridset/symbols.d.ts +8 -6
- package/dist/processors/gridset/symbols.js +38 -71
- package/dist/processors/gridset/wordlistHelpers.d.ts +4 -6
- package/dist/processors/gridset/wordlistHelpers.js +15 -74
- package/dist/processors/gridsetProcessor.d.ts +2 -2
- package/dist/processors/gridsetProcessor.js +38 -70
- package/dist/processors/obfProcessor.d.ts +2 -2
- package/dist/processors/obfProcessor.js +38 -75
- package/dist/processors/obfsetProcessor.js +2 -3
- package/dist/processors/opmlProcessor.js +10 -11
- package/dist/processors/snap/helpers.d.ts +9 -9
- package/dist/processors/snap/helpers.js +58 -76
- package/dist/processors/snapProcessor.d.ts +2 -2
- package/dist/processors/snapProcessor.js +47 -50
- package/dist/processors/touchchatProcessor.d.ts +2 -2
- package/dist/processors/touchchatProcessor.js +59 -51
- package/dist/types/aac.d.ts +2 -2
- package/dist/utilities/analytics/history.d.ts +8 -8
- package/dist/utilities/analytics/history.js +24 -18
- package/dist/utilities/analytics/index.d.ts +3 -2
- package/dist/utilities/analytics/index.js +9 -10
- package/dist/utilities/analytics/metrics/comparison.d.ts +1 -1
- package/dist/utilities/analytics/metrics/comparison.js +16 -16
- package/dist/utilities/analytics/metrics/vocabulary.d.ts +1 -1
- package/dist/utilities/analytics/metrics/vocabulary.js +2 -2
- package/dist/utilities/analytics/reference/browser.d.ts +9 -9
- package/dist/utilities/analytics/reference/browser.js +16 -16
- package/dist/utilities/analytics/reference/index.d.ts +25 -23
- package/dist/utilities/analytics/reference/index.js +43 -34
- package/dist/utilities/symbolTools.d.ts +8 -6
- package/dist/utilities/symbolTools.js +21 -18
- package/dist/utils/io.d.ts +24 -6
- package/dist/utils/io.js +79 -25
- package/dist/utils/sqlite.d.ts +3 -1
- package/dist/utils/sqlite.js +7 -9
- package/dist/utils/zip.d.ts +7 -3
- package/dist/utils/zip.js +43 -43
- package/dist/validation/applePanelsValidator.d.ts +2 -1
- package/dist/validation/applePanelsValidator.js +10 -11
- package/dist/validation/astericsValidator.d.ts +2 -1
- package/dist/validation/astericsValidator.js +5 -4
- package/dist/validation/baseValidator.d.ts +2 -2
- package/dist/validation/baseValidator.js +5 -0
- package/dist/validation/dotValidator.d.ts +2 -1
- package/dist/validation/dotValidator.js +5 -4
- package/dist/validation/excelValidator.d.ts +2 -1
- package/dist/validation/excelValidator.js +5 -4
- package/dist/validation/gridsetValidator.d.ts +2 -1
- package/dist/validation/gridsetValidator.js +11 -22
- package/dist/validation/index.d.ts +2 -2
- package/dist/validation/index.js +5 -4
- package/dist/validation/obfValidator.d.ts +2 -1
- package/dist/validation/obfValidator.js +5 -4
- package/dist/validation/obfsetValidator.d.ts +2 -1
- package/dist/validation/obfsetValidator.js +5 -4
- package/dist/validation/opmlValidator.d.ts +2 -1
- package/dist/validation/opmlValidator.js +5 -4
- package/dist/validation/snapValidator.d.ts +2 -1
- package/dist/validation/snapValidator.js +10 -6
- package/dist/validation/touchChatValidator.d.ts +4 -6
- package/dist/validation/touchChatValidator.js +22 -12
- package/dist/validation/validationTypes.d.ts +8 -1
- package/package.json +1 -1
- package/dist/core/fileProcessor.d.ts +0 -7
- package/dist/core/fileProcessor.js +0 -57
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grid3 Color Utilities
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive color handling for Grid3 format, including:
|
|
5
|
+
* - CSS color name lookup (147 named colors)
|
|
6
|
+
* - Color format conversion (hex, RGB, RGBA, named colors)
|
|
7
|
+
* - Color manipulation (darkening, normalization)
|
|
8
|
+
* - Grid3-specific color formatting (8-digit ARGB hex)
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* CSS color names to RGB values
|
|
12
|
+
* Supports 147 standard CSS color names
|
|
13
|
+
*/
|
|
14
|
+
const CSS_COLORS = {
|
|
15
|
+
aliceblue: [240, 248, 255],
|
|
16
|
+
antiquewhite: [250, 235, 215],
|
|
17
|
+
aqua: [0, 255, 255],
|
|
18
|
+
aquamarine: [127, 255, 212],
|
|
19
|
+
azure: [240, 255, 255],
|
|
20
|
+
beige: [245, 245, 220],
|
|
21
|
+
bisque: [255, 228, 196],
|
|
22
|
+
black: [0, 0, 0],
|
|
23
|
+
blanchedalmond: [255, 235, 205],
|
|
24
|
+
blue: [0, 0, 255],
|
|
25
|
+
blueviolet: [138, 43, 226],
|
|
26
|
+
brown: [165, 42, 42],
|
|
27
|
+
burlywood: [222, 184, 135],
|
|
28
|
+
cadetblue: [95, 158, 160],
|
|
29
|
+
chartreuse: [127, 255, 0],
|
|
30
|
+
chocolate: [210, 105, 30],
|
|
31
|
+
coral: [255, 127, 80],
|
|
32
|
+
cornflowerblue: [100, 149, 237],
|
|
33
|
+
cornsilk: [255, 248, 220],
|
|
34
|
+
crimson: [220, 20, 60],
|
|
35
|
+
cyan: [0, 255, 255],
|
|
36
|
+
darkblue: [0, 0, 139],
|
|
37
|
+
darkcyan: [0, 139, 139],
|
|
38
|
+
darkgoldenrod: [184, 134, 11],
|
|
39
|
+
darkgray: [169, 169, 169],
|
|
40
|
+
darkgreen: [0, 100, 0],
|
|
41
|
+
darkgrey: [169, 169, 169],
|
|
42
|
+
darkkhaki: [189, 183, 107],
|
|
43
|
+
darkmagenta: [139, 0, 139],
|
|
44
|
+
darkolivegreen: [85, 107, 47],
|
|
45
|
+
darkorange: [255, 140, 0],
|
|
46
|
+
darkorchid: [153, 50, 204],
|
|
47
|
+
darkred: [139, 0, 0],
|
|
48
|
+
darksalmon: [233, 150, 122],
|
|
49
|
+
darkseagreen: [143, 188, 143],
|
|
50
|
+
darkslateblue: [72, 61, 139],
|
|
51
|
+
darkslategray: [47, 79, 79],
|
|
52
|
+
darkslategrey: [47, 79, 79],
|
|
53
|
+
darkturquoise: [0, 206, 209],
|
|
54
|
+
darkviolet: [148, 0, 211],
|
|
55
|
+
deeppink: [255, 20, 147],
|
|
56
|
+
deepskyblue: [0, 191, 255],
|
|
57
|
+
dimgray: [105, 105, 105],
|
|
58
|
+
dimgrey: [105, 105, 105],
|
|
59
|
+
dodgerblue: [30, 144, 255],
|
|
60
|
+
firebrick: [178, 34, 34],
|
|
61
|
+
floralwhite: [255, 250, 240],
|
|
62
|
+
forestgreen: [34, 139, 34],
|
|
63
|
+
fuchsia: [255, 0, 255],
|
|
64
|
+
gainsboro: [220, 220, 220],
|
|
65
|
+
ghostwhite: [248, 248, 255],
|
|
66
|
+
gold: [255, 215, 0],
|
|
67
|
+
goldenrod: [218, 165, 32],
|
|
68
|
+
gray: [128, 128, 128],
|
|
69
|
+
grey: [128, 128, 128],
|
|
70
|
+
green: [0, 128, 0],
|
|
71
|
+
greenyellow: [173, 255, 47],
|
|
72
|
+
honeydew: [240, 255, 240],
|
|
73
|
+
hotpink: [255, 105, 180],
|
|
74
|
+
indianred: [205, 92, 92],
|
|
75
|
+
indigo: [75, 0, 130],
|
|
76
|
+
ivory: [255, 255, 240],
|
|
77
|
+
khaki: [240, 230, 140],
|
|
78
|
+
lavender: [230, 230, 250],
|
|
79
|
+
lavenderblush: [255, 240, 245],
|
|
80
|
+
lawngreen: [124, 252, 0],
|
|
81
|
+
lemonchiffon: [255, 250, 205],
|
|
82
|
+
lightblue: [173, 216, 230],
|
|
83
|
+
lightcoral: [240, 128, 128],
|
|
84
|
+
lightcyan: [224, 255, 255],
|
|
85
|
+
lightgoldenrodyellow: [250, 250, 210],
|
|
86
|
+
lightgray: [211, 211, 211],
|
|
87
|
+
lightgreen: [144, 238, 144],
|
|
88
|
+
lightgrey: [211, 211, 211],
|
|
89
|
+
lightpink: [255, 182, 193],
|
|
90
|
+
lightsalmon: [255, 160, 122],
|
|
91
|
+
lightseagreen: [32, 178, 170],
|
|
92
|
+
lightskyblue: [135, 206, 250],
|
|
93
|
+
lightslategray: [119, 136, 153],
|
|
94
|
+
lightslategrey: [119, 136, 153],
|
|
95
|
+
lightsteelblue: [176, 196, 222],
|
|
96
|
+
lightyellow: [255, 255, 224],
|
|
97
|
+
lime: [0, 255, 0],
|
|
98
|
+
limegreen: [50, 205, 50],
|
|
99
|
+
linen: [250, 240, 230],
|
|
100
|
+
magenta: [255, 0, 255],
|
|
101
|
+
maroon: [128, 0, 0],
|
|
102
|
+
mediumaquamarine: [102, 205, 170],
|
|
103
|
+
mediumblue: [0, 0, 205],
|
|
104
|
+
mediumorchid: [186, 85, 211],
|
|
105
|
+
mediumpurple: [147, 112, 219],
|
|
106
|
+
mediumseagreen: [60, 179, 113],
|
|
107
|
+
mediumslateblue: [123, 104, 238],
|
|
108
|
+
mediumspringgreen: [0, 250, 154],
|
|
109
|
+
mediumturquoise: [72, 209, 204],
|
|
110
|
+
mediumvioletred: [199, 21, 133],
|
|
111
|
+
midnightblue: [25, 25, 112],
|
|
112
|
+
mintcream: [245, 255, 250],
|
|
113
|
+
mistyrose: [255, 228, 225],
|
|
114
|
+
moccasin: [255, 228, 181],
|
|
115
|
+
navajowhite: [255, 222, 173],
|
|
116
|
+
navy: [0, 0, 128],
|
|
117
|
+
oldlace: [253, 245, 230],
|
|
118
|
+
olive: [128, 128, 0],
|
|
119
|
+
olivedrab: [107, 142, 35],
|
|
120
|
+
orange: [255, 165, 0],
|
|
121
|
+
orangered: [255, 69, 0],
|
|
122
|
+
orchid: [218, 112, 214],
|
|
123
|
+
palegoldenrod: [238, 232, 170],
|
|
124
|
+
palegreen: [152, 251, 152],
|
|
125
|
+
paleturquoise: [175, 238, 238],
|
|
126
|
+
palevioletred: [219, 112, 147],
|
|
127
|
+
papayawhip: [255, 239, 213],
|
|
128
|
+
peachpuff: [255, 218, 185],
|
|
129
|
+
peru: [205, 133, 63],
|
|
130
|
+
pink: [255, 192, 203],
|
|
131
|
+
plum: [221, 160, 221],
|
|
132
|
+
powderblue: [176, 224, 230],
|
|
133
|
+
purple: [128, 0, 128],
|
|
134
|
+
rebeccapurple: [102, 51, 153],
|
|
135
|
+
red: [255, 0, 0],
|
|
136
|
+
rosybrown: [188, 143, 143],
|
|
137
|
+
royalblue: [65, 105, 225],
|
|
138
|
+
saddlebrown: [139, 69, 19],
|
|
139
|
+
salmon: [250, 128, 114],
|
|
140
|
+
sandybrown: [244, 164, 96],
|
|
141
|
+
seagreen: [46, 139, 87],
|
|
142
|
+
seashell: [255, 245, 238],
|
|
143
|
+
sienna: [160, 82, 45],
|
|
144
|
+
silver: [192, 192, 192],
|
|
145
|
+
skyblue: [135, 206, 235],
|
|
146
|
+
slateblue: [106, 90, 205],
|
|
147
|
+
slategray: [112, 128, 144],
|
|
148
|
+
slategrey: [112, 128, 144],
|
|
149
|
+
snow: [255, 250, 250],
|
|
150
|
+
springgreen: [0, 255, 127],
|
|
151
|
+
steelblue: [70, 130, 180],
|
|
152
|
+
tan: [210, 180, 140],
|
|
153
|
+
teal: [0, 128, 128],
|
|
154
|
+
thistle: [216, 191, 216],
|
|
155
|
+
tomato: [255, 99, 71],
|
|
156
|
+
turquoise: [64, 224, 208],
|
|
157
|
+
violet: [238, 130, 238],
|
|
158
|
+
wheat: [245, 222, 179],
|
|
159
|
+
white: [255, 255, 255],
|
|
160
|
+
whitesmoke: [245, 245, 245],
|
|
161
|
+
yellow: [255, 255, 0],
|
|
162
|
+
yellowgreen: [154, 205, 50],
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Get RGB values for a CSS color name
|
|
166
|
+
* @param name - CSS color name (case-insensitive)
|
|
167
|
+
* @returns RGB tuple [r, g, b] or undefined if not found
|
|
168
|
+
*/
|
|
169
|
+
export function getNamedColor(name) {
|
|
170
|
+
const color = CSS_COLORS[name.toLowerCase()];
|
|
171
|
+
return color;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Convert RGBA values to hex format
|
|
175
|
+
* @param r - Red channel (0-255)
|
|
176
|
+
* @param g - Green channel (0-255)
|
|
177
|
+
* @param b - Blue channel (0-255)
|
|
178
|
+
* @param a - Alpha channel (0-1)
|
|
179
|
+
* @returns Hex color string in format #RRGGBBAA
|
|
180
|
+
*/
|
|
181
|
+
export function rgbaToHex(r, g, b, a) {
|
|
182
|
+
const red = channelToHex(r);
|
|
183
|
+
const green = channelToHex(g);
|
|
184
|
+
const blue = channelToHex(b);
|
|
185
|
+
const alpha = channelToHex(Math.round(a * 255));
|
|
186
|
+
return `#${red}${green}${blue}${alpha}`;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Convert a single color channel value to hex
|
|
190
|
+
* @param value - Channel value (0-255)
|
|
191
|
+
* @returns Two-digit hex string
|
|
192
|
+
*/
|
|
193
|
+
export function channelToHex(value) {
|
|
194
|
+
const clamped = Math.max(0, Math.min(255, Math.round(value)));
|
|
195
|
+
return clamped.toString(16).padStart(2, '0').toUpperCase();
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Clamp RGB channel value to valid range
|
|
199
|
+
* @param value - Channel value
|
|
200
|
+
* @returns Clamped value (0-255)
|
|
201
|
+
*/
|
|
202
|
+
export function clampColorChannel(value) {
|
|
203
|
+
if (Number.isNaN(value)) {
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
return Math.max(0, Math.min(255, value));
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Clamp alpha value to valid range
|
|
210
|
+
* @param value - Alpha value
|
|
211
|
+
* @returns Clamped value (0-1)
|
|
212
|
+
*/
|
|
213
|
+
export function clampAlpha(value) {
|
|
214
|
+
if (Number.isNaN(value)) {
|
|
215
|
+
return 1;
|
|
216
|
+
}
|
|
217
|
+
return Math.max(0, Math.min(1, value));
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Convert any color format to hex
|
|
221
|
+
* Supports: hex (#RGB, #RRGGBB, #RRGGBBAA), RGB/RGBA, and CSS color names
|
|
222
|
+
* @param value - Color string in any supported format
|
|
223
|
+
* @returns Hex color string (#RRGGBBAA) or undefined if invalid
|
|
224
|
+
*/
|
|
225
|
+
export function toHexColor(value) {
|
|
226
|
+
// Try hex format
|
|
227
|
+
const hexMatch = value.match(/^#([0-9a-f]{3}|[0-9a-f]{4}|[0-9a-f]{6}|[0-9a-f]{8})$/i);
|
|
228
|
+
if (hexMatch) {
|
|
229
|
+
const hex = hexMatch[1];
|
|
230
|
+
if (hex.length === 3 || hex.length === 4) {
|
|
231
|
+
return `#${hex
|
|
232
|
+
.split('')
|
|
233
|
+
.map((char) => char + char)
|
|
234
|
+
.join('')}`;
|
|
235
|
+
}
|
|
236
|
+
return `#${hex}`;
|
|
237
|
+
}
|
|
238
|
+
// Try RGB/RGBA format
|
|
239
|
+
const rgbMatch = value.match(/^rgba?\((.+)\)$/i);
|
|
240
|
+
if (rgbMatch) {
|
|
241
|
+
const parts = rgbMatch[1]
|
|
242
|
+
.split(',')
|
|
243
|
+
.map((part) => part.trim())
|
|
244
|
+
.filter(Boolean);
|
|
245
|
+
if (parts.length === 3 || parts.length === 4) {
|
|
246
|
+
const [r, g, b, a] = parts;
|
|
247
|
+
const red = clampColorChannel(parseFloat(r));
|
|
248
|
+
const green = clampColorChannel(parseFloat(g));
|
|
249
|
+
const blue = clampColorChannel(parseFloat(b));
|
|
250
|
+
const alpha = parts.length === 4 ? clampAlpha(parseFloat(a)) : 1;
|
|
251
|
+
return rgbaToHex(red, green, blue, alpha);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Try CSS color name
|
|
255
|
+
const rgb = getNamedColor(value);
|
|
256
|
+
if (rgb) {
|
|
257
|
+
return rgbaToHex(rgb[0], rgb[1], rgb[2], 1);
|
|
258
|
+
}
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Darken a hex color by a specified amount
|
|
263
|
+
* @param hex - Hex color string
|
|
264
|
+
* @param amount - Amount to darken (0-255)
|
|
265
|
+
* @returns Darkened hex color
|
|
266
|
+
*/
|
|
267
|
+
export function darkenColor(hex, amount) {
|
|
268
|
+
const normalized = ensureAlphaChannel(hex).substring(1); // strip #
|
|
269
|
+
const rgb = normalized.substring(0, 6);
|
|
270
|
+
const alpha = normalized.substring(6) || 'FF';
|
|
271
|
+
const r = parseInt(rgb.substring(0, 2), 16);
|
|
272
|
+
const g = parseInt(rgb.substring(2, 4), 16);
|
|
273
|
+
const b = parseInt(rgb.substring(4, 6), 16);
|
|
274
|
+
const clamp = (val) => Math.max(0, Math.min(255, val));
|
|
275
|
+
const newR = clamp(r - amount);
|
|
276
|
+
const newG = clamp(g - amount);
|
|
277
|
+
const newB = clamp(b - amount);
|
|
278
|
+
return `#${channelToHex(newR)}${channelToHex(newG)}${channelToHex(newB)}${alpha.toUpperCase()}`;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Lighten a hex color by a specified amount
|
|
282
|
+
* @param hex - Hex color string
|
|
283
|
+
* @param amount - Amount to lighten (0-255)
|
|
284
|
+
* @returns Lightened hex color
|
|
285
|
+
*/
|
|
286
|
+
export function lightenColor(hex, amount) {
|
|
287
|
+
const normalized = ensureAlphaChannel(hex).substring(1); // strip #
|
|
288
|
+
const rgb = normalized.substring(0, 6);
|
|
289
|
+
const alpha = normalized.substring(6) || 'FF';
|
|
290
|
+
const r = parseInt(rgb.substring(0, 2), 16);
|
|
291
|
+
const g = parseInt(rgb.substring(2, 4), 16);
|
|
292
|
+
const b = parseInt(rgb.substring(4, 6), 16);
|
|
293
|
+
const clamp = (val) => Math.max(0, Math.min(255, val));
|
|
294
|
+
const newR = clamp(r + amount);
|
|
295
|
+
const newG = clamp(g + amount);
|
|
296
|
+
const newB = clamp(b + amount);
|
|
297
|
+
return `#${channelToHex(newR)}${channelToHex(newG)}${channelToHex(newB)}${alpha.toUpperCase()}`;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Convert hex color to RGBA object
|
|
301
|
+
* @param hex - Hex color string (#RRGGBB or #RRGGBBAA)
|
|
302
|
+
* @returns RGBA object with r, g, b, a properties (0-1 for alpha)
|
|
303
|
+
*/
|
|
304
|
+
export function hexToRgba(hex) {
|
|
305
|
+
const normalized = ensureAlphaChannel(hex).substring(1); // strip #
|
|
306
|
+
const rgb = normalized.substring(0, 6);
|
|
307
|
+
const alphaHex = normalized.substring(6) || 'FF';
|
|
308
|
+
const r = parseInt(rgb.substring(0, 2), 16);
|
|
309
|
+
const g = parseInt(rgb.substring(2, 4), 16);
|
|
310
|
+
const b = parseInt(rgb.substring(4, 6), 16);
|
|
311
|
+
const a = parseInt(alphaHex, 16) / 255;
|
|
312
|
+
return { r, g, b, a };
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Normalize any color format to Grid3's 8-digit hex format
|
|
316
|
+
* @param input - Color string in any supported format
|
|
317
|
+
* @param fallback - Fallback color if input is invalid (default: white)
|
|
318
|
+
* @returns Normalized color in format #AARRGGBBFF
|
|
319
|
+
*/
|
|
320
|
+
export function normalizeColor(input, fallback = '#FFFFFFFF') {
|
|
321
|
+
const trimmed = input.trim();
|
|
322
|
+
if (!trimmed) {
|
|
323
|
+
return fallback;
|
|
324
|
+
}
|
|
325
|
+
const hex = toHexColor(trimmed);
|
|
326
|
+
if (hex) {
|
|
327
|
+
return ensureAlphaChannel(hex).toUpperCase();
|
|
328
|
+
}
|
|
329
|
+
return fallback;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Ensure a color has an alpha channel (Grid3 format requires 8-digit ARGB)
|
|
333
|
+
* @param color - Color string (hex format)
|
|
334
|
+
* @returns Color with alpha channel in format #AARRGGBBFF
|
|
335
|
+
*/
|
|
336
|
+
export function ensureAlphaChannel(color) {
|
|
337
|
+
if (!color)
|
|
338
|
+
return '#FFFFFFFF';
|
|
339
|
+
// If already 8 digits (with alpha), return as is
|
|
340
|
+
if (color.match(/^#[0-9A-Fa-f]{8}$/))
|
|
341
|
+
return color;
|
|
342
|
+
// If 6 digits (no alpha), add FF for fully opaque
|
|
343
|
+
if (color.match(/^#[0-9A-Fa-f]{6}$/))
|
|
344
|
+
return color + 'FF';
|
|
345
|
+
// If 3 digits (shorthand), expand to 8
|
|
346
|
+
if (color.match(/^#[0-9A-Fa-f]{3}$/)) {
|
|
347
|
+
const r = color[1];
|
|
348
|
+
const g = color[2];
|
|
349
|
+
const b = color[3];
|
|
350
|
+
return `#${r}${r}${g}${g}${b}${b}FF`;
|
|
351
|
+
}
|
|
352
|
+
// Invalid or unknown format, return white
|
|
353
|
+
return '#FFFFFFFF';
|
|
354
|
+
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { XMLBuilder } from 'fast-xml-parser';
|
|
2
2
|
import { AACSemanticCategory, AACSemanticIntent, } from '../../core/treeStructure';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
import * as path from 'path';
|
|
5
|
-
import { execSync } from 'child_process';
|
|
6
|
-
import Database from 'better-sqlite3';
|
|
7
3
|
import { dotNetTicksToDate } from '../../utils/dotnetTicks';
|
|
8
4
|
import { getZipEntriesFromAdapter, resolveGridsetPasswordFromEnv } from './password';
|
|
9
|
-
import {
|
|
5
|
+
import { defaultFileAdapter, extname, getNodeRequire, joinWin32, } from '../../utils/io';
|
|
6
|
+
import { getZipAdapter } from '../../utils/zip';
|
|
7
|
+
import { requireBetterSqlite3 } from '../../utils/sqlite';
|
|
10
8
|
function normalizeZipPath(p) {
|
|
11
9
|
const unified = p.replace(/\\/g, '/');
|
|
12
10
|
try {
|
|
@@ -52,11 +50,11 @@ export function getAllowedImageEntries(tree) {
|
|
|
52
50
|
* @param entryPath Entry name inside the zip
|
|
53
51
|
* @returns Image data buffer or null if not found
|
|
54
52
|
*/
|
|
55
|
-
export async function openImage(gridsetBuffer, entryPath, password = resolveGridsetPasswordFromEnv(), zipAdapter) {
|
|
53
|
+
export async function openImage(gridsetBuffer, entryPath, password = resolveGridsetPasswordFromEnv(), fileAdapter = defaultFileAdapter, zipAdapter) {
|
|
56
54
|
try {
|
|
57
|
-
const
|
|
55
|
+
const zip = zipAdapter
|
|
58
56
|
? await zipAdapter(gridsetBuffer)
|
|
59
|
-
: await
|
|
57
|
+
: await getZipAdapter(gridsetBuffer, fileAdapter);
|
|
60
58
|
const entries = getZipEntriesFromAdapter(zip, password);
|
|
61
59
|
const want = normalizeZipPath(entryPath);
|
|
62
60
|
const entry = entries.find((e) => normalizeZipPath(e.entryName) === want);
|
|
@@ -149,8 +147,9 @@ export function getCommonDocumentsPath() {
|
|
|
149
147
|
}
|
|
150
148
|
try {
|
|
151
149
|
// Query registry for Common Documents path
|
|
150
|
+
const child_process = getNodeRequire()('child_process');
|
|
152
151
|
const command = 'REG.EXE QUERY "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" /V "Common Documents"';
|
|
153
|
-
const output = execSync(command, { encoding: 'utf-8', windowsHide: true });
|
|
152
|
+
const output = child_process.execSync(command, { encoding: 'utf-8', windowsHide: true });
|
|
154
153
|
// Parse the output to extract the path
|
|
155
154
|
const match = output.match(/Common Documents\s+REG_SZ\s+(.+)/);
|
|
156
155
|
if (match && match[1]) {
|
|
@@ -171,7 +170,8 @@ export function getCommonDocumentsPath() {
|
|
|
171
170
|
* C:\Users\Public\Documents\Smartbox\Grid 3\Users\{UserName}\Grid Sets\
|
|
172
171
|
* @returns Array of Grid3 user path information
|
|
173
172
|
*/
|
|
174
|
-
export function findGrid3UserPaths() {
|
|
173
|
+
export async function findGrid3UserPaths(fileAdapter = defaultFileAdapter) {
|
|
174
|
+
const { pathExists, listDir, isDirectory } = fileAdapter;
|
|
175
175
|
const results = [];
|
|
176
176
|
// Only works on Windows
|
|
177
177
|
if (process.platform !== 'win32') {
|
|
@@ -180,28 +180,28 @@ export function findGrid3UserPaths() {
|
|
|
180
180
|
try {
|
|
181
181
|
const commonDocs = getCommonDocumentsPath();
|
|
182
182
|
// Use Windows path joining so tests that mock a Windows platform stay consistent even on POSIX runners
|
|
183
|
-
const grid3BasePath =
|
|
183
|
+
const grid3BasePath = joinWin32(commonDocs, 'Smartbox', 'Grid 3', 'Users');
|
|
184
184
|
// Check if Grid3 Users directory exists
|
|
185
|
-
if (!
|
|
185
|
+
if (!(await pathExists(grid3BasePath))) {
|
|
186
186
|
return results;
|
|
187
187
|
}
|
|
188
188
|
// Enumerate users
|
|
189
|
-
const users =
|
|
189
|
+
const users = await listDir(grid3BasePath);
|
|
190
190
|
for (const userDir of users) {
|
|
191
|
-
if (!
|
|
191
|
+
if (!(await isDirectory(userDir)))
|
|
192
192
|
continue;
|
|
193
|
-
const userName = userDir
|
|
194
|
-
const userPath =
|
|
193
|
+
const userName = userDir;
|
|
194
|
+
const userPath = joinWin32(grid3BasePath, userName);
|
|
195
195
|
// Enumerate language codes
|
|
196
|
-
const langDirs =
|
|
196
|
+
const langDirs = await listDir(userPath);
|
|
197
197
|
for (const langDir of langDirs) {
|
|
198
|
-
if (!
|
|
198
|
+
if (!(await isDirectory(langDir)))
|
|
199
199
|
continue;
|
|
200
|
-
const langCode = langDir
|
|
201
|
-
const basePath =
|
|
202
|
-
const historyDbPath =
|
|
200
|
+
const langCode = langDir;
|
|
201
|
+
const basePath = joinWin32(userPath, langCode);
|
|
202
|
+
const historyDbPath = joinWin32(basePath, 'Phrases', 'history.sqlite');
|
|
203
203
|
// Only include if history database exists
|
|
204
|
-
if (
|
|
204
|
+
if (await pathExists(historyDbPath)) {
|
|
205
205
|
results.push({
|
|
206
206
|
userName,
|
|
207
207
|
langCode,
|
|
@@ -222,50 +222,52 @@ export function findGrid3UserPaths() {
|
|
|
222
222
|
* Convenience method that returns just the database file paths
|
|
223
223
|
* @returns Array of paths to history.sqlite files
|
|
224
224
|
*/
|
|
225
|
-
export function findGrid3HistoryDatabases() {
|
|
226
|
-
|
|
225
|
+
export async function findGrid3HistoryDatabases(fileAdapter) {
|
|
226
|
+
const userPaths = await findGrid3UserPaths(fileAdapter);
|
|
227
|
+
return userPaths.map((userPath) => userPath.historyDbPath);
|
|
227
228
|
}
|
|
228
229
|
/**
|
|
229
230
|
* Get Grid 3 users (alias of findGrid3UserPaths for clarity)
|
|
230
231
|
*/
|
|
231
|
-
export function findGrid3Users() {
|
|
232
|
-
return findGrid3UserPaths();
|
|
232
|
+
export async function findGrid3Users() {
|
|
233
|
+
return await findGrid3UserPaths();
|
|
233
234
|
}
|
|
234
235
|
/**
|
|
235
236
|
* Find Grid 3 gridset/vocabulary files for each user
|
|
236
237
|
* @param userName Optional user filter; matches case-insensitively
|
|
237
238
|
* @returns Array of user/gridset path pairs
|
|
238
239
|
*/
|
|
239
|
-
export function findGrid3Vocabularies(userName) {
|
|
240
|
+
export async function findGrid3Vocabularies(userName, fileAdapter = defaultFileAdapter) {
|
|
241
|
+
const { pathExists, listDir, isDirectory } = fileAdapter;
|
|
240
242
|
const results = [];
|
|
241
243
|
if (process.platform !== 'win32') {
|
|
242
244
|
return results;
|
|
243
245
|
}
|
|
244
246
|
const commonDocs = getCommonDocumentsPath();
|
|
245
|
-
const grid3BasePath =
|
|
246
|
-
if (!
|
|
247
|
+
const grid3BasePath = joinWin32(commonDocs, 'Smartbox', 'Grid 3', 'Users');
|
|
248
|
+
if (!(await pathExists(grid3BasePath))) {
|
|
247
249
|
return results;
|
|
248
250
|
}
|
|
249
251
|
const normalizedUser = userName?.toLowerCase();
|
|
250
|
-
const users =
|
|
252
|
+
const users = await listDir(grid3BasePath);
|
|
251
253
|
for (const userDir of users) {
|
|
252
|
-
if (!
|
|
254
|
+
if (!(await isDirectory(userDir)))
|
|
253
255
|
continue;
|
|
254
|
-
if (normalizedUser && userDir.
|
|
256
|
+
if (normalizedUser && userDir.toLowerCase() !== normalizedUser)
|
|
255
257
|
continue;
|
|
256
|
-
const userRoot =
|
|
257
|
-
const gridSetsDir =
|
|
258
|
-
if (!
|
|
258
|
+
const userRoot = joinWin32(grid3BasePath, userDir);
|
|
259
|
+
const gridSetsDir = joinWin32(userRoot, 'Grid Sets');
|
|
260
|
+
if (!(await pathExists(gridSetsDir)))
|
|
259
261
|
continue;
|
|
260
|
-
const entries =
|
|
262
|
+
const entries = await listDir(gridSetsDir);
|
|
261
263
|
for (const entry of entries) {
|
|
262
|
-
if (!entry
|
|
264
|
+
if (!(await pathExists(entry)) || (await isDirectory(entry)))
|
|
263
265
|
continue;
|
|
264
|
-
const ext =
|
|
266
|
+
const ext = extname(entry).toLowerCase();
|
|
265
267
|
if (ext === '.gridset' || ext === '.gridsetx' || ext === '.grd' || ext === '.grdl') {
|
|
266
268
|
results.push({
|
|
267
|
-
userName: userDir
|
|
268
|
-
gridsetPath:
|
|
269
|
+
userName: userDir,
|
|
270
|
+
gridsetPath: joinWin32(gridSetsDir, entry),
|
|
269
271
|
});
|
|
270
272
|
}
|
|
271
273
|
}
|
|
@@ -278,26 +280,28 @@ export function findGrid3Vocabularies(userName) {
|
|
|
278
280
|
* @param langCode Optional language code filter (case-insensitive)
|
|
279
281
|
* @returns Path to history.sqlite or null if not found
|
|
280
282
|
*/
|
|
281
|
-
export function findGrid3UserHistory(userName, langCode) {
|
|
283
|
+
export async function findGrid3UserHistory(userName, langCode, fileAdapter) {
|
|
282
284
|
if (!userName)
|
|
283
285
|
return null;
|
|
284
286
|
const normalizedUser = userName.toLowerCase();
|
|
285
287
|
const normalizedLang = langCode?.toLowerCase();
|
|
286
|
-
const
|
|
288
|
+
const userPaths = await findGrid3UserPaths(fileAdapter);
|
|
289
|
+
const match = userPaths.find((u) => u.userName.toLowerCase() === normalizedUser &&
|
|
287
290
|
(!normalizedLang || u.langCode.toLowerCase() === normalizedLang));
|
|
288
291
|
return match?.historyDbPath ?? null;
|
|
289
292
|
}
|
|
290
293
|
/**
|
|
291
294
|
* Check whether Grid 3 appears to be installed (Windows only)
|
|
292
295
|
*/
|
|
293
|
-
export function isGrid3Installed() {
|
|
296
|
+
export async function isGrid3Installed(fileAdapter = defaultFileAdapter) {
|
|
297
|
+
const { pathExists } = fileAdapter;
|
|
294
298
|
if (process.platform !== 'win32')
|
|
295
299
|
return false;
|
|
296
300
|
const commonDocs = getCommonDocumentsPath();
|
|
297
301
|
if (!commonDocs)
|
|
298
302
|
return false;
|
|
299
|
-
const grid3BasePath =
|
|
300
|
-
return
|
|
303
|
+
const grid3BasePath = joinWin32(commonDocs, 'Smartbox', 'Grid 3', 'Users');
|
|
304
|
+
return await pathExists(grid3BasePath);
|
|
301
305
|
}
|
|
302
306
|
function parseGrid3ContentXml(xmlContent) {
|
|
303
307
|
const regex = /<r>(?:<!\[CDATA\[)?(.*?)(?:\]\]>)?<\/r>/gis;
|
|
@@ -316,9 +320,11 @@ function parseGrid3ContentXml(xmlContent) {
|
|
|
316
320
|
* @param historyDbPath Absolute path to the history database
|
|
317
321
|
* @returns Parsed history entries grouped by phrase
|
|
318
322
|
*/
|
|
319
|
-
export function readGrid3History(historyDbPath) {
|
|
320
|
-
|
|
323
|
+
export async function readGrid3History(historyDbPath, fileAdapter = defaultFileAdapter) {
|
|
324
|
+
const { pathExists } = fileAdapter;
|
|
325
|
+
if (!(await pathExists(historyDbPath)))
|
|
321
326
|
return [];
|
|
327
|
+
const Database = requireBetterSqlite3();
|
|
322
328
|
const db = new Database(historyDbPath, { readonly: true });
|
|
323
329
|
const rows = db
|
|
324
330
|
.prepare(`
|
|
@@ -376,17 +382,18 @@ export function readGrid3History(historyDbPath) {
|
|
|
376
382
|
* @param langCode Optional language code to narrow selection (case-insensitive)
|
|
377
383
|
* @returns History entries for that user/language, or empty array if none
|
|
378
384
|
*/
|
|
379
|
-
export function readGrid3HistoryForUser(userName, langCode) {
|
|
380
|
-
const dbPath = findGrid3UserHistory(userName, langCode);
|
|
385
|
+
export async function readGrid3HistoryForUser(userName, langCode) {
|
|
386
|
+
const dbPath = await findGrid3UserHistory(userName, langCode);
|
|
381
387
|
if (!dbPath)
|
|
382
388
|
return [];
|
|
383
|
-
return readGrid3History(dbPath);
|
|
389
|
+
return await readGrid3History(dbPath);
|
|
384
390
|
}
|
|
385
391
|
/**
|
|
386
392
|
* Load all available Grid 3 histories on the machine.
|
|
387
393
|
* @returns Combined history entries from every discovered history.sqlite
|
|
388
394
|
*/
|
|
389
|
-
export function readAllGrid3History() {
|
|
390
|
-
const paths = findGrid3HistoryDatabases();
|
|
391
|
-
|
|
395
|
+
export async function readAllGrid3History() {
|
|
396
|
+
const paths = await findGrid3HistoryDatabases();
|
|
397
|
+
const history = await Promise.all(paths.map(async (p) => await readGrid3History(p)));
|
|
398
|
+
return history.flat();
|
|
392
399
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grid 3 Enhanced Support Module
|
|
3
|
+
*
|
|
4
|
+
* This module exports all enhanced Grid 3 functionality including:
|
|
5
|
+
* - Cell shape detection and support
|
|
6
|
+
* - Plugin cell type detection (Workspace, LiveCell, AutoContent)
|
|
7
|
+
* - Comprehensive command definitions and detection
|
|
8
|
+
* - Color utilities and style helpers
|
|
9
|
+
* - Image resolution helpers
|
|
10
|
+
*/
|
|
11
|
+
// Style helpers
|
|
12
|
+
export { CellBackgroundShape, SHAPE_NAMES, DEFAULT_GRID3_STYLES, CATEGORY_STYLES, createDefaultStylesXml, createCategoryStyle, } from './styleHelpers';
|
|
13
|
+
// Plugin cell type detection
|
|
14
|
+
export { detectPluginCellType, Grid3CellType, WORKSPACE_TYPES, LIVECELL_TYPES, AUTOCONTENT_TYPES, getCellTypeDisplayName, isWorkspaceCell, isLiveCell, isAutoContentCell, isRegularCell, } from './pluginTypes';
|
|
15
|
+
// Command definitions and detection
|
|
16
|
+
export { detectCommand, getCommandDefinition, getCommandsByPlugin, getCommandsByCategory, getAllCommandIds, getAllPluginIds, extractCommandParameters, GRID3_COMMANDS, Grid3CommandCategory, } from './commands';
|
|
17
|
+
// Import for local use in constant definitions
|
|
18
|
+
import { getAllCommandIds, getAllPluginIds } from './commands';
|
|
19
|
+
import { CellBackgroundShape } from './styleHelpers';
|
|
20
|
+
import { Grid3CellType } from './pluginTypes';
|
|
21
|
+
import { Grid3CommandCategory } from './commands';
|
|
22
|
+
// Color utilities
|
|
23
|
+
export { ensureAlphaChannel, darkenColor, lightenColor, hexToRgba, rgbaToHex } from './colorUtils';
|
|
24
|
+
// Password handling
|
|
25
|
+
export { resolveGridsetPassword, getZipEntriesWithPassword, getZipEntriesFromAdapter, resolveGridsetPasswordFromEnv, } from './password';
|
|
26
|
+
// Helper functions
|
|
27
|
+
export { getPageTokenImageMap, getAllowedImageEntries, openImage, generateGrid3Guid, createSettingsXml, createFileMapXml, getCommonDocumentsPath, findGrid3UserPaths, findGrid3HistoryDatabases, findGrid3Vocabularies, findGrid3UserHistory, findGrid3Users, isGrid3Installed, readGrid3History, readGrid3HistoryForUser, readAllGrid3History, } from './helpers';
|
|
28
|
+
// Symbol library handling
|
|
29
|
+
export { parseSymbolReference, isSymbolReference, resolveSymbolReference, getAvailableSymbolLibraries, getSymbolLibraryInfo, extractSymbolReferences, analyzeSymbolUsage, createSymbolReference, getSymbolLibraryName, getSymbolPath, isKnownSymbolLibrary, getSymbolLibraryDisplayName, getDefaultGrid3Path, getSymbolLibrariesDir, getSymbolSearchIndexesDir, symbolReferenceToFilename, SYMBOL_LIBRARIES, } from './symbols';
|
|
30
|
+
// Backward compatibility aliases for old function names
|
|
31
|
+
export { getSymbolsDir, getSymbolSearchDir } from './symbols';
|
|
32
|
+
// Image resolution
|
|
33
|
+
export { resolveGrid3CellImage, isSymbolLibraryReference, parseImageSymbolReference, } from './resolver';
|
|
34
|
+
// Symbol extraction and conversion
|
|
35
|
+
export { extractButtonImage, extractSymbolLibraryImage, convertToAstericsImage, analyzeSymbolExtraction, suggestExtractionStrategy, exportSymbolReferencesToCsv, createSymbolManifest, } from './symbolExtractor';
|
|
36
|
+
// Symbol search functionality
|
|
37
|
+
export { parsePixFile, loadSearchIndexes, searchSymbols, searchSymbolsWithReferences, getSymbolFilename, getSymbolDisplayName, getAllSearchTerms, getSearchSuggestions, countLibrarySymbols, getSymbolSearchStats, } from './symbolSearch';
|
|
38
|
+
/**
|
|
39
|
+
* Get all Grid 3 command IDs as a readonly array
|
|
40
|
+
* Useful for validation and autocomplete
|
|
41
|
+
*/
|
|
42
|
+
export const GRID3_COMMAND_IDS = Object.freeze(getAllCommandIds());
|
|
43
|
+
/**
|
|
44
|
+
* Get all Grid 3 plugin IDs as a readonly array
|
|
45
|
+
*/
|
|
46
|
+
export const GRID3_PLUGIN_IDS = Object.freeze(getAllPluginIds());
|
|
47
|
+
/**
|
|
48
|
+
* Grid 3 cell shapes enum values
|
|
49
|
+
*/
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
51
|
+
export const GRID3_CELL_SHAPES = Object.freeze(Object.values(CellBackgroundShape));
|
|
52
|
+
/**
|
|
53
|
+
* Grid 3 cell types enum values
|
|
54
|
+
*/
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
56
|
+
export const GRID3_CELL_TYPES = Object.freeze(Object.values(Grid3CellType));
|
|
57
|
+
/**
|
|
58
|
+
* Grid 3 command categories enum values
|
|
59
|
+
*/
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
61
|
+
export const GRID3_COMMAND_CATEGORIES = Object.freeze(Object.values(Grid3CommandCategory));
|