@willwade/aac-processors 0.0.3 → 0.0.5
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 -1
- package/dist/processors/gridset/styleHelpers.d.ts +46 -0
- package/dist/processors/gridset/styleHelpers.js +211 -0
- package/dist/processors/gridset/wordlistHelpers.d.ts +82 -0
- package/dist/processors/gridset/wordlistHelpers.js +234 -0
- package/dist/processors/index.d.ts +2 -0
- package/dist/processors/index.js +14 -1
- package/docs/Grid3-Styling-Guide.md +287 -0
- package/examples/README.md +33 -21
- package/package.json +1 -1
- package/examples/demo.js +0 -143
- package/examples/gemini_response.txt +0 -845
- package/examples/image-map.js +0 -45
- package/examples/package-lock.json +0 -1326
- package/examples/package.json +0 -10
- package/examples/styling-example.ts +0 -316
- package/examples/translate.js +0 -39
- package/examples/translate_demo.js +0 -254
- package/examples/translation_cache.json +0 -44894
- package/examples/typescript-demo.ts +0 -251
- package/examples/unified-interface-demo.ts +0 -183
package/README.md
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grid3 Style Helpers
|
|
3
|
+
*
|
|
4
|
+
* Utilities for creating and managing Grid3 styles, including default styles,
|
|
5
|
+
* style XML generation, and style conversion utilities.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Grid3 Style object structure
|
|
9
|
+
*/
|
|
10
|
+
export interface Grid3Style {
|
|
11
|
+
BackColour?: string;
|
|
12
|
+
TileColour?: string;
|
|
13
|
+
BorderColour?: string;
|
|
14
|
+
FontColour?: string;
|
|
15
|
+
FontName?: string;
|
|
16
|
+
FontSize?: string | number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Default Grid3 styles for common use cases
|
|
20
|
+
* Colors are in 8-digit ARGB hex format (#AARRGGBBFF)
|
|
21
|
+
*/
|
|
22
|
+
export declare const DEFAULT_GRID3_STYLES: Record<string, Grid3Style>;
|
|
23
|
+
/**
|
|
24
|
+
* Category-specific styles for navigation and organization
|
|
25
|
+
*/
|
|
26
|
+
export declare const CATEGORY_STYLES: Record<string, Grid3Style>;
|
|
27
|
+
/**
|
|
28
|
+
* Ensure a color has an alpha channel (Grid3 format requires 8-digit ARGB)
|
|
29
|
+
* @param color - Color string (hex format)
|
|
30
|
+
* @returns Color with alpha channel in format #AARRGGBBFF
|
|
31
|
+
*/
|
|
32
|
+
export declare function ensureAlphaChannel(color: string | undefined): string;
|
|
33
|
+
/**
|
|
34
|
+
* Create a Grid3 style XML string with default and category styles
|
|
35
|
+
* @param includeCategories - Whether to include category-specific styles (default: true)
|
|
36
|
+
* @returns XML string for Settings0/styles.xml
|
|
37
|
+
*/
|
|
38
|
+
export declare function createDefaultStylesXml(includeCategories?: boolean): string;
|
|
39
|
+
/**
|
|
40
|
+
* Create a custom category style
|
|
41
|
+
* @param categoryName - Name of the category
|
|
42
|
+
* @param backgroundColor - Background color in hex format
|
|
43
|
+
* @param fontColor - Font color in hex format (default: white)
|
|
44
|
+
* @returns Grid3Style object
|
|
45
|
+
*/
|
|
46
|
+
export declare function createCategoryStyle(categoryName: string, backgroundColor: string, fontColor?: string): Grid3Style;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Grid3 Style Helpers
|
|
4
|
+
*
|
|
5
|
+
* Utilities for creating and managing Grid3 styles, including default styles,
|
|
6
|
+
* style XML generation, and style conversion utilities.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = void 0;
|
|
10
|
+
exports.ensureAlphaChannel = ensureAlphaChannel;
|
|
11
|
+
exports.createDefaultStylesXml = createDefaultStylesXml;
|
|
12
|
+
exports.createCategoryStyle = createCategoryStyle;
|
|
13
|
+
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
14
|
+
/**
|
|
15
|
+
* Default Grid3 styles for common use cases
|
|
16
|
+
* Colors are in 8-digit ARGB hex format (#AARRGGBBFF)
|
|
17
|
+
*/
|
|
18
|
+
exports.DEFAULT_GRID3_STYLES = {
|
|
19
|
+
Default: {
|
|
20
|
+
BackColour: '#E2EDF8FF',
|
|
21
|
+
TileColour: '#FFFFFFFF',
|
|
22
|
+
BorderColour: '#000000FF',
|
|
23
|
+
FontColour: '#000000FF',
|
|
24
|
+
FontName: 'Arial',
|
|
25
|
+
FontSize: '16',
|
|
26
|
+
},
|
|
27
|
+
Workspace: {
|
|
28
|
+
BackColour: '#FFFFFFFF',
|
|
29
|
+
TileColour: '#FFFFFFFF',
|
|
30
|
+
BorderColour: '#CCCCCCFF',
|
|
31
|
+
FontColour: '#000000FF',
|
|
32
|
+
FontName: 'Arial',
|
|
33
|
+
FontSize: '14',
|
|
34
|
+
},
|
|
35
|
+
'Auto content': {
|
|
36
|
+
BackColour: '#E8F4F8FF',
|
|
37
|
+
TileColour: '#E8F4F8FF',
|
|
38
|
+
BorderColour: '#2C82C9FF',
|
|
39
|
+
FontColour: '#000000FF',
|
|
40
|
+
FontName: 'Arial',
|
|
41
|
+
FontSize: '14',
|
|
42
|
+
},
|
|
43
|
+
'Vocab cell': {
|
|
44
|
+
BackColour: '#E8F4F8FF',
|
|
45
|
+
TileColour: '#E8F4F8FF',
|
|
46
|
+
BorderColour: '#2C82C9FF',
|
|
47
|
+
FontColour: '#000000FF',
|
|
48
|
+
FontName: 'Arial',
|
|
49
|
+
FontSize: '14',
|
|
50
|
+
},
|
|
51
|
+
'Keyboard key': {
|
|
52
|
+
BackColour: '#F0F0F0FF',
|
|
53
|
+
TileColour: '#F0F0F0FF',
|
|
54
|
+
BorderColour: '#808080FF',
|
|
55
|
+
FontColour: '#000000FF',
|
|
56
|
+
FontName: 'Arial',
|
|
57
|
+
FontSize: '12',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Category-specific styles for navigation and organization
|
|
62
|
+
*/
|
|
63
|
+
exports.CATEGORY_STYLES = {
|
|
64
|
+
'Actions category style': {
|
|
65
|
+
BackColour: '#4472C4FF',
|
|
66
|
+
TileColour: '#4472C4FF',
|
|
67
|
+
BorderColour: '#2F5496FF',
|
|
68
|
+
FontColour: '#FFFFFFFF',
|
|
69
|
+
FontName: 'Arial',
|
|
70
|
+
FontSize: '16',
|
|
71
|
+
},
|
|
72
|
+
'People category style': {
|
|
73
|
+
BackColour: '#ED7D31FF',
|
|
74
|
+
TileColour: '#ED7D31FF',
|
|
75
|
+
BorderColour: '#C65911FF',
|
|
76
|
+
FontColour: '#FFFFFFFF',
|
|
77
|
+
FontName: 'Arial',
|
|
78
|
+
FontSize: '16',
|
|
79
|
+
},
|
|
80
|
+
'Places category style': {
|
|
81
|
+
BackColour: '#A5A5A5FF',
|
|
82
|
+
TileColour: '#A5A5A5FF',
|
|
83
|
+
BorderColour: '#595959FF',
|
|
84
|
+
FontColour: '#FFFFFFFF',
|
|
85
|
+
FontName: 'Arial',
|
|
86
|
+
FontSize: '16',
|
|
87
|
+
},
|
|
88
|
+
'Descriptive category style': {
|
|
89
|
+
BackColour: '#70AD47FF',
|
|
90
|
+
TileColour: '#70AD47FF',
|
|
91
|
+
BorderColour: '#4F7C2FFF',
|
|
92
|
+
FontColour: '#FFFFFFFF',
|
|
93
|
+
FontName: 'Arial',
|
|
94
|
+
FontSize: '16',
|
|
95
|
+
},
|
|
96
|
+
'Social category style': {
|
|
97
|
+
BackColour: '#FFC000FF',
|
|
98
|
+
TileColour: '#FFC000FF',
|
|
99
|
+
BorderColour: '#BF8F00FF',
|
|
100
|
+
FontColour: '#000000FF',
|
|
101
|
+
FontName: 'Arial',
|
|
102
|
+
FontSize: '16',
|
|
103
|
+
},
|
|
104
|
+
'Questions category style': {
|
|
105
|
+
BackColour: '#5B9BD5FF',
|
|
106
|
+
TileColour: '#5B9BD5FF',
|
|
107
|
+
BorderColour: '#2E5C8AFF',
|
|
108
|
+
FontColour: '#FFFFFFFF',
|
|
109
|
+
FontName: 'Arial',
|
|
110
|
+
FontSize: '16',
|
|
111
|
+
},
|
|
112
|
+
'Little words category style': {
|
|
113
|
+
BackColour: '#C55A11FF',
|
|
114
|
+
TileColour: '#C55A11FF',
|
|
115
|
+
BorderColour: '#8B3F0AFF',
|
|
116
|
+
FontColour: '#FFFFFFFF',
|
|
117
|
+
FontName: 'Arial',
|
|
118
|
+
FontSize: '16',
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Ensure a color has an alpha channel (Grid3 format requires 8-digit ARGB)
|
|
123
|
+
* @param color - Color string (hex format)
|
|
124
|
+
* @returns Color with alpha channel in format #AARRGGBBFF
|
|
125
|
+
*/
|
|
126
|
+
function ensureAlphaChannel(color) {
|
|
127
|
+
if (!color)
|
|
128
|
+
return '#FFFFFFFF';
|
|
129
|
+
// If already 8 digits (with alpha), return as is
|
|
130
|
+
if (color.match(/^#[0-9A-Fa-f]{8}$/))
|
|
131
|
+
return color;
|
|
132
|
+
// If 6 digits (no alpha), add FF for fully opaque
|
|
133
|
+
if (color.match(/^#[0-9A-Fa-f]{6}$/))
|
|
134
|
+
return color + 'FF';
|
|
135
|
+
// If 3 digits (shorthand), expand to 8
|
|
136
|
+
if (color.match(/^#[0-9A-Fa-f]{3}$/)) {
|
|
137
|
+
const r = color[1];
|
|
138
|
+
const g = color[2];
|
|
139
|
+
const b = color[3];
|
|
140
|
+
return `#${r}${r}${g}${g}${b}${b}FF`;
|
|
141
|
+
}
|
|
142
|
+
// Invalid or unknown format, return white
|
|
143
|
+
return '#FFFFFFFF';
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Create a Grid3 style XML string with default and category styles
|
|
147
|
+
* @param includeCategories - Whether to include category-specific styles (default: true)
|
|
148
|
+
* @returns XML string for Settings0/styles.xml
|
|
149
|
+
*/
|
|
150
|
+
function createDefaultStylesXml(includeCategories = true) {
|
|
151
|
+
const builder = new fast_xml_parser_1.XMLBuilder({
|
|
152
|
+
ignoreAttributes: false,
|
|
153
|
+
format: true,
|
|
154
|
+
indentBy: ' ',
|
|
155
|
+
});
|
|
156
|
+
const styles = { ...exports.DEFAULT_GRID3_STYLES };
|
|
157
|
+
if (includeCategories) {
|
|
158
|
+
Object.assign(styles, exports.CATEGORY_STYLES);
|
|
159
|
+
}
|
|
160
|
+
const styleArray = Object.entries(styles).map(([key, style]) => ({
|
|
161
|
+
'@_Key': key,
|
|
162
|
+
BackColour: style.BackColour,
|
|
163
|
+
TileColour: style.TileColour,
|
|
164
|
+
BorderColour: style.BorderColour,
|
|
165
|
+
FontColour: style.FontColour,
|
|
166
|
+
FontName: style.FontName,
|
|
167
|
+
FontSize: style.FontSize?.toString(),
|
|
168
|
+
}));
|
|
169
|
+
const stylesData = {
|
|
170
|
+
StyleData: {
|
|
171
|
+
'@_xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
|
172
|
+
Styles: {
|
|
173
|
+
Style: styleArray,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
return builder.build(stylesData);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Create a custom category style
|
|
181
|
+
* @param categoryName - Name of the category
|
|
182
|
+
* @param backgroundColor - Background color in hex format
|
|
183
|
+
* @param fontColor - Font color in hex format (default: white)
|
|
184
|
+
* @returns Grid3Style object
|
|
185
|
+
*/
|
|
186
|
+
function createCategoryStyle(categoryName, backgroundColor, fontColor = '#FFFFFFFF') {
|
|
187
|
+
return {
|
|
188
|
+
BackColour: ensureAlphaChannel(backgroundColor),
|
|
189
|
+
TileColour: ensureAlphaChannel(backgroundColor),
|
|
190
|
+
BorderColour: ensureAlphaChannel(darkenColor(backgroundColor, 30)),
|
|
191
|
+
FontColour: ensureAlphaChannel(fontColor),
|
|
192
|
+
FontName: 'Arial',
|
|
193
|
+
FontSize: '16',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Darken a hex color by a given amount
|
|
198
|
+
* @param hexColor - Hex color string
|
|
199
|
+
* @param amount - Amount to darken (0-255)
|
|
200
|
+
* @returns Darkened hex color
|
|
201
|
+
*/
|
|
202
|
+
function darkenColor(hexColor, amount) {
|
|
203
|
+
const normalized = ensureAlphaChannel(hexColor);
|
|
204
|
+
const hex = normalized.slice(1, 7); // Extract RGB part (skip # and alpha)
|
|
205
|
+
const num = parseInt(hex, 16);
|
|
206
|
+
const clamp = (value) => Math.max(0, Math.min(255, value));
|
|
207
|
+
const r = clamp(((num >> 16) & 0xff) - amount);
|
|
208
|
+
const g = clamp(((num >> 8) & 0xff) - amount);
|
|
209
|
+
const b = clamp((num & 0xff) - amount);
|
|
210
|
+
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
|
|
211
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grid3 Wordlist Helpers
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for creating and extracting wordlists
|
|
5
|
+
* from Grid3 gridsets. Wordlists are Grid3-specific data structures
|
|
6
|
+
* used for dynamic vocabulary content.
|
|
7
|
+
*
|
|
8
|
+
* Note: Wordlists are only supported in Grid3 format. Other AAC formats
|
|
9
|
+
* do not have equivalent wordlist functionality.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Represents a single item in a wordlist
|
|
13
|
+
*/
|
|
14
|
+
export interface WordListItem {
|
|
15
|
+
/** The text/word/phrase */
|
|
16
|
+
text: string;
|
|
17
|
+
/** Optional image reference (e.g., "[WIDGIT]path/to/symbol.emf") */
|
|
18
|
+
image?: string;
|
|
19
|
+
/** Part of speech category (e.g., "Noun", "Verb", "Unknown") */
|
|
20
|
+
partOfSpeech?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Represents a complete wordlist
|
|
24
|
+
*/
|
|
25
|
+
export interface WordList {
|
|
26
|
+
/** Array of wordlist items */
|
|
27
|
+
items: WordListItem[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a WordList object from an array of words/phrases or a dictionary
|
|
31
|
+
*
|
|
32
|
+
* @param input - Either an array of strings or an object with text/image/partOfSpeech properties
|
|
33
|
+
* @returns A WordList object ready to be used in Grid3
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // From simple array
|
|
37
|
+
* const wordlist = createWordlist(['hello', 'goodbye', 'thank you']);
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // From array of objects
|
|
41
|
+
* const wordlist = createWordlist([
|
|
42
|
+
* { text: 'hello', image: '[WIDGIT]greetings/hello.emf', partOfSpeech: 'Interjection' },
|
|
43
|
+
* { text: 'goodbye', image: '[WIDGIT]greetings/goodbye.emf', partOfSpeech: 'Interjection' }
|
|
44
|
+
* ]);
|
|
45
|
+
*/
|
|
46
|
+
export declare function createWordlist(input: string[] | WordListItem[] | Record<string, string | WordListItem>): WordList;
|
|
47
|
+
/**
|
|
48
|
+
* Converts a WordList object to Grid3 XML format
|
|
49
|
+
*
|
|
50
|
+
* @param wordlist - The wordlist to convert
|
|
51
|
+
* @returns XML string representation
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export declare function wordlistToXml(wordlist: WordList): string;
|
|
55
|
+
/**
|
|
56
|
+
* Extracts all wordlists from a gridset buffer
|
|
57
|
+
*
|
|
58
|
+
* @param gridsetBuffer - The gridset file as a Buffer
|
|
59
|
+
* @returns Map of grid names to their wordlists (if they have any)
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* const wordlists = extractWordlists(gridsetBuffer);
|
|
63
|
+
* wordlists.forEach((wordlist, gridName) => {
|
|
64
|
+
* console.log(`Grid "${gridName}" has ${wordlist.items.length} items`);
|
|
65
|
+
* });
|
|
66
|
+
*/
|
|
67
|
+
export declare function extractWordlists(gridsetBuffer: Buffer): Map<string, WordList>;
|
|
68
|
+
/**
|
|
69
|
+
* Updates or adds a wordlist to a specific grid in a gridset
|
|
70
|
+
*
|
|
71
|
+
* @param gridsetBuffer - The gridset file as a Buffer
|
|
72
|
+
* @param gridName - The name of the grid to update (e.g., "Greetings")
|
|
73
|
+
* @param wordlist - The wordlist to add/update
|
|
74
|
+
* @returns Updated gridset as a Buffer
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* const gridsetBuffer = fs.readFileSync('my-gridset.gridset');
|
|
78
|
+
* const newWordlist = createWordlist(['hello', 'hi', 'hey']);
|
|
79
|
+
* const updatedGridset = updateWordlist(gridsetBuffer, 'Greetings', newWordlist);
|
|
80
|
+
* fs.writeFileSync('updated-gridset.gridset', updatedGridset);
|
|
81
|
+
*/
|
|
82
|
+
export declare function updateWordlist(gridsetBuffer: Buffer, gridName: string, wordlist: WordList): Buffer;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Grid3 Wordlist Helpers
|
|
4
|
+
*
|
|
5
|
+
* This module provides utilities for creating and extracting wordlists
|
|
6
|
+
* from Grid3 gridsets. Wordlists are Grid3-specific data structures
|
|
7
|
+
* used for dynamic vocabulary content.
|
|
8
|
+
*
|
|
9
|
+
* Note: Wordlists are only supported in Grid3 format. Other AAC formats
|
|
10
|
+
* do not have equivalent wordlist functionality.
|
|
11
|
+
*/
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.createWordlist = createWordlist;
|
|
17
|
+
exports.wordlistToXml = wordlistToXml;
|
|
18
|
+
exports.extractWordlists = extractWordlists;
|
|
19
|
+
exports.updateWordlist = updateWordlist;
|
|
20
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
21
|
+
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
22
|
+
/**
|
|
23
|
+
* Creates a WordList object from an array of words/phrases or a dictionary
|
|
24
|
+
*
|
|
25
|
+
* @param input - Either an array of strings or an object with text/image/partOfSpeech properties
|
|
26
|
+
* @returns A WordList object ready to be used in Grid3
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // From simple array
|
|
30
|
+
* const wordlist = createWordlist(['hello', 'goodbye', 'thank you']);
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // From array of objects
|
|
34
|
+
* const wordlist = createWordlist([
|
|
35
|
+
* { text: 'hello', image: '[WIDGIT]greetings/hello.emf', partOfSpeech: 'Interjection' },
|
|
36
|
+
* { text: 'goodbye', image: '[WIDGIT]greetings/goodbye.emf', partOfSpeech: 'Interjection' }
|
|
37
|
+
* ]);
|
|
38
|
+
*/
|
|
39
|
+
function createWordlist(input) {
|
|
40
|
+
let items = [];
|
|
41
|
+
if (Array.isArray(input)) {
|
|
42
|
+
// Handle array input
|
|
43
|
+
items = input.map((item) => {
|
|
44
|
+
if (typeof item === 'string') {
|
|
45
|
+
return { text: item };
|
|
46
|
+
}
|
|
47
|
+
return item;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
else if (typeof input === 'object') {
|
|
51
|
+
// Handle dictionary/object input
|
|
52
|
+
items = Object.entries(input).map(([key, value]) => {
|
|
53
|
+
if (typeof value === 'string') {
|
|
54
|
+
return { text: value };
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return { items };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Converts a WordList object to Grid3 XML format
|
|
63
|
+
*
|
|
64
|
+
* @param wordlist - The wordlist to convert
|
|
65
|
+
* @returns XML string representation
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
function wordlistToXml(wordlist) {
|
|
69
|
+
const items = wordlist.items.map((item) => ({
|
|
70
|
+
WordListItem: {
|
|
71
|
+
Text: {
|
|
72
|
+
s: {
|
|
73
|
+
'@_Image': item.image || '',
|
|
74
|
+
r: item.text,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
Image: item.image || '',
|
|
78
|
+
PartOfSpeech: item.partOfSpeech || 'Unknown',
|
|
79
|
+
},
|
|
80
|
+
}));
|
|
81
|
+
const wordlistData = {
|
|
82
|
+
WordList: {
|
|
83
|
+
Items: {
|
|
84
|
+
WordListItem: items.length === 1 ? items[0].WordListItem : items.map((i) => i.WordListItem),
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
const builder = new fast_xml_parser_1.XMLBuilder({
|
|
89
|
+
ignoreAttributes: false,
|
|
90
|
+
format: false,
|
|
91
|
+
suppressEmptyNode: false,
|
|
92
|
+
});
|
|
93
|
+
return builder.build(wordlistData);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Extracts all wordlists from a gridset buffer
|
|
97
|
+
*
|
|
98
|
+
* @param gridsetBuffer - The gridset file as a Buffer
|
|
99
|
+
* @returns Map of grid names to their wordlists (if they have any)
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* const wordlists = extractWordlists(gridsetBuffer);
|
|
103
|
+
* wordlists.forEach((wordlist, gridName) => {
|
|
104
|
+
* console.log(`Grid "${gridName}" has ${wordlist.items.length} items`);
|
|
105
|
+
* });
|
|
106
|
+
*/
|
|
107
|
+
function extractWordlists(gridsetBuffer) {
|
|
108
|
+
const wordlists = new Map();
|
|
109
|
+
const parser = new fast_xml_parser_1.XMLParser();
|
|
110
|
+
let zip;
|
|
111
|
+
try {
|
|
112
|
+
zip = new adm_zip_1.default(gridsetBuffer);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
throw new Error(`Invalid gridset buffer: ${error.message}`);
|
|
116
|
+
}
|
|
117
|
+
// Process each grid file
|
|
118
|
+
zip.getEntries().forEach((entry) => {
|
|
119
|
+
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
120
|
+
try {
|
|
121
|
+
const xmlContent = entry.getData().toString('utf8');
|
|
122
|
+
const data = parser.parse(xmlContent);
|
|
123
|
+
const grid = data.Grid || data.grid;
|
|
124
|
+
if (!grid || !grid.WordList) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Extract grid name from path (e.g., "Grids/MyGrid/grid.xml" -> "MyGrid")
|
|
128
|
+
const match = entry.entryName.match(/^Grids\/([^/]+)\//);
|
|
129
|
+
const gridName = match ? match[1] : entry.entryName;
|
|
130
|
+
// Parse wordlist items
|
|
131
|
+
const wordlistData = grid.WordList;
|
|
132
|
+
const itemsContainer = wordlistData.Items || wordlistData.items;
|
|
133
|
+
if (!itemsContainer) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const itemArray = Array.isArray(itemsContainer.WordListItem)
|
|
137
|
+
? itemsContainer.WordListItem
|
|
138
|
+
: itemsContainer.WordListItem
|
|
139
|
+
? [itemsContainer.WordListItem]
|
|
140
|
+
: [];
|
|
141
|
+
const items = itemArray.map((item) => ({
|
|
142
|
+
text: item.Text?.s?.r || item.text?.s?.r || '',
|
|
143
|
+
image: item.Image || item.image || undefined,
|
|
144
|
+
partOfSpeech: item.PartOfSpeech || item.partOfSpeech || 'Unknown',
|
|
145
|
+
}));
|
|
146
|
+
if (items.length > 0) {
|
|
147
|
+
wordlists.set(gridName, { items });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
// Skip grids with parsing errors
|
|
152
|
+
console.warn(`Failed to extract wordlist from ${entry.entryName}:`, error);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return wordlists;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Updates or adds a wordlist to a specific grid in a gridset
|
|
160
|
+
*
|
|
161
|
+
* @param gridsetBuffer - The gridset file as a Buffer
|
|
162
|
+
* @param gridName - The name of the grid to update (e.g., "Greetings")
|
|
163
|
+
* @param wordlist - The wordlist to add/update
|
|
164
|
+
* @returns Updated gridset as a Buffer
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* const gridsetBuffer = fs.readFileSync('my-gridset.gridset');
|
|
168
|
+
* const newWordlist = createWordlist(['hello', 'hi', 'hey']);
|
|
169
|
+
* const updatedGridset = updateWordlist(gridsetBuffer, 'Greetings', newWordlist);
|
|
170
|
+
* fs.writeFileSync('updated-gridset.gridset', updatedGridset);
|
|
171
|
+
*/
|
|
172
|
+
function updateWordlist(gridsetBuffer, gridName, wordlist) {
|
|
173
|
+
const parser = new fast_xml_parser_1.XMLParser();
|
|
174
|
+
const builder = new fast_xml_parser_1.XMLBuilder({
|
|
175
|
+
ignoreAttributes: false,
|
|
176
|
+
format: true,
|
|
177
|
+
indentBy: ' ',
|
|
178
|
+
suppressEmptyNode: false,
|
|
179
|
+
});
|
|
180
|
+
let zip;
|
|
181
|
+
try {
|
|
182
|
+
zip = new adm_zip_1.default(gridsetBuffer);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
throw new Error(`Invalid gridset buffer: ${error.message}`);
|
|
186
|
+
}
|
|
187
|
+
let found = false;
|
|
188
|
+
// Find and update the grid
|
|
189
|
+
zip.getEntries().forEach((entry) => {
|
|
190
|
+
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
191
|
+
const match = entry.entryName.match(/^Grids\/([^/]+)\//);
|
|
192
|
+
const currentGridName = match ? match[1] : null;
|
|
193
|
+
if (currentGridName === gridName) {
|
|
194
|
+
try {
|
|
195
|
+
const xmlContent = entry.getData().toString('utf8');
|
|
196
|
+
const data = parser.parse(xmlContent);
|
|
197
|
+
const grid = data.Grid || data.grid;
|
|
198
|
+
if (!grid) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Build the new wordlist XML structure
|
|
202
|
+
const items = wordlist.items.map((item) => ({
|
|
203
|
+
WordListItem: {
|
|
204
|
+
Text: {
|
|
205
|
+
s: {
|
|
206
|
+
'@_Image': item.image || '',
|
|
207
|
+
r: item.text,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
Image: item.image || '',
|
|
211
|
+
PartOfSpeech: item.partOfSpeech || 'Unknown',
|
|
212
|
+
},
|
|
213
|
+
}));
|
|
214
|
+
grid.WordList = {
|
|
215
|
+
Items: {
|
|
216
|
+
WordListItem: items.length === 1 ? items[0].WordListItem : items.map((i) => i.WordListItem),
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
// Rebuild the XML
|
|
220
|
+
const updatedXml = builder.build(data);
|
|
221
|
+
zip.updateFile(entry, Buffer.from(updatedXml, 'utf8'));
|
|
222
|
+
found = true;
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
throw new Error(`Failed to update wordlist in grid "${gridName}": ${error}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
if (!found) {
|
|
231
|
+
throw new Error(`Grid "${gridName}" not found in gridset`);
|
|
232
|
+
}
|
|
233
|
+
return zip.toBuffer();
|
|
234
|
+
}
|
|
@@ -10,5 +10,7 @@ export { AstericsGridProcessor } from './astericsGridProcessor';
|
|
|
10
10
|
export { getPageTokenImageMap, getAllowedImageEntries, openImage } from './gridset/helpers';
|
|
11
11
|
export { getPageTokenImageMap as getGridsetPageTokenImageMap, getAllowedImageEntries as getGridsetAllowedImageEntries, openImage as openGridsetImage, } from './gridset/helpers';
|
|
12
12
|
export { resolveGrid3CellImage } from './gridset/resolver';
|
|
13
|
+
export { createWordlist, extractWordlists, updateWordlist, wordlistToXml, type WordList, type WordListItem, } from './gridset/wordlistHelpers';
|
|
14
|
+
export { DEFAULT_GRID3_STYLES, CATEGORY_STYLES, ensureAlphaChannel, createDefaultStylesXml, createCategoryStyle, type Grid3Style, } from './gridset/styleHelpers';
|
|
13
15
|
export { getPageTokenImageMap as getSnapPageTokenImageMap, getAllowedImageEntries as getSnapAllowedImageEntries, openImage as openSnapImage, } from './snap/helpers';
|
|
14
16
|
export { getPageTokenImageMap as getTouchChatPageTokenImageMap, getAllowedImageEntries as getTouchChatAllowedImageEntries, openImage as openTouchChatImage, } from './touchchat/helpers';
|
package/dist/processors/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.openTouchChatImage = exports.getTouchChatAllowedImageEntries = exports.getTouchChatPageTokenImageMap = exports.openSnapImage = exports.getSnapAllowedImageEntries = exports.getSnapPageTokenImageMap = exports.resolveGrid3CellImage = exports.openGridsetImage = exports.getGridsetAllowedImageEntries = exports.getGridsetPageTokenImageMap = exports.openImage = exports.getAllowedImageEntries = exports.getPageTokenImageMap = exports.AstericsGridProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.OpmlProcessor = exports.ObfProcessor = exports.GridsetProcessor = exports.ExcelProcessor = exports.DotProcessor = exports.ApplePanelsProcessor = void 0;
|
|
3
|
+
exports.openTouchChatImage = exports.getTouchChatAllowedImageEntries = exports.getTouchChatPageTokenImageMap = exports.openSnapImage = exports.getSnapAllowedImageEntries = exports.getSnapPageTokenImageMap = exports.createCategoryStyle = exports.createDefaultStylesXml = exports.ensureAlphaChannel = exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = exports.wordlistToXml = exports.updateWordlist = exports.extractWordlists = exports.createWordlist = exports.resolveGrid3CellImage = exports.openGridsetImage = exports.getGridsetAllowedImageEntries = exports.getGridsetPageTokenImageMap = exports.openImage = exports.getAllowedImageEntries = exports.getPageTokenImageMap = exports.AstericsGridProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.OpmlProcessor = exports.ObfProcessor = exports.GridsetProcessor = exports.ExcelProcessor = exports.DotProcessor = exports.ApplePanelsProcessor = void 0;
|
|
4
4
|
var applePanelsProcessor_1 = require("./applePanelsProcessor");
|
|
5
5
|
Object.defineProperty(exports, "ApplePanelsProcessor", { enumerable: true, get: function () { return applePanelsProcessor_1.ApplePanelsProcessor; } });
|
|
6
6
|
var dotProcessor_1 = require("./dotProcessor");
|
|
@@ -30,6 +30,19 @@ Object.defineProperty(exports, "getGridsetAllowedImageEntries", { enumerable: tr
|
|
|
30
30
|
Object.defineProperty(exports, "openGridsetImage", { enumerable: true, get: function () { return helpers_2.openImage; } });
|
|
31
31
|
var resolver_1 = require("./gridset/resolver");
|
|
32
32
|
Object.defineProperty(exports, "resolveGrid3CellImage", { enumerable: true, get: function () { return resolver_1.resolveGrid3CellImage; } });
|
|
33
|
+
// Gridset (Grid 3) wordlist helpers
|
|
34
|
+
var wordlistHelpers_1 = require("./gridset/wordlistHelpers");
|
|
35
|
+
Object.defineProperty(exports, "createWordlist", { enumerable: true, get: function () { return wordlistHelpers_1.createWordlist; } });
|
|
36
|
+
Object.defineProperty(exports, "extractWordlists", { enumerable: true, get: function () { return wordlistHelpers_1.extractWordlists; } });
|
|
37
|
+
Object.defineProperty(exports, "updateWordlist", { enumerable: true, get: function () { return wordlistHelpers_1.updateWordlist; } });
|
|
38
|
+
Object.defineProperty(exports, "wordlistToXml", { enumerable: true, get: function () { return wordlistHelpers_1.wordlistToXml; } });
|
|
39
|
+
// Gridset (Grid 3) style helpers
|
|
40
|
+
var styleHelpers_1 = require("./gridset/styleHelpers");
|
|
41
|
+
Object.defineProperty(exports, "DEFAULT_GRID3_STYLES", { enumerable: true, get: function () { return styleHelpers_1.DEFAULT_GRID3_STYLES; } });
|
|
42
|
+
Object.defineProperty(exports, "CATEGORY_STYLES", { enumerable: true, get: function () { return styleHelpers_1.CATEGORY_STYLES; } });
|
|
43
|
+
Object.defineProperty(exports, "ensureAlphaChannel", { enumerable: true, get: function () { return styleHelpers_1.ensureAlphaChannel; } });
|
|
44
|
+
Object.defineProperty(exports, "createDefaultStylesXml", { enumerable: true, get: function () { return styleHelpers_1.createDefaultStylesXml; } });
|
|
45
|
+
Object.defineProperty(exports, "createCategoryStyle", { enumerable: true, get: function () { return styleHelpers_1.createCategoryStyle; } });
|
|
33
46
|
// Snap helpers (stubs)
|
|
34
47
|
var helpers_3 = require("./snap/helpers");
|
|
35
48
|
Object.defineProperty(exports, "getSnapPageTokenImageMap", { enumerable: true, get: function () { return helpers_3.getPageTokenImageMap; } });
|