@willwade/aac-processors 0.0.8 → 0.0.10

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.
Files changed (58) hide show
  1. package/README.md +116 -11
  2. package/dist/cli/index.js +87 -0
  3. package/dist/core/analyze.js +1 -0
  4. package/dist/core/baseProcessor.d.ts +3 -0
  5. package/dist/core/fileProcessor.js +1 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +3 -0
  8. package/dist/optional/symbolTools.js +4 -2
  9. package/dist/processors/gridset/helpers.d.ts +3 -1
  10. package/dist/processors/gridset/helpers.js +24 -5
  11. package/dist/processors/gridset/password.d.ts +11 -0
  12. package/dist/processors/gridset/password.js +37 -0
  13. package/dist/processors/gridset/resolver.d.ts +1 -1
  14. package/dist/processors/gridset/resolver.js +8 -4
  15. package/dist/processors/gridset/wordlistHelpers.d.ts +2 -2
  16. package/dist/processors/gridset/wordlistHelpers.js +7 -4
  17. package/dist/processors/gridsetProcessor.d.ts +15 -1
  18. package/dist/processors/gridsetProcessor.js +64 -22
  19. package/dist/processors/index.d.ts +1 -0
  20. package/dist/processors/index.js +5 -2
  21. package/dist/processors/obfProcessor.d.ts +7 -0
  22. package/dist/processors/obfProcessor.js +9 -0
  23. package/dist/processors/snap/helpers.d.ts +2 -0
  24. package/dist/processors/snap/helpers.js +2 -0
  25. package/dist/processors/snapProcessor.d.ts +7 -0
  26. package/dist/processors/snapProcessor.js +9 -0
  27. package/dist/processors/touchchatProcessor.d.ts +7 -0
  28. package/dist/processors/touchchatProcessor.js +9 -0
  29. package/dist/utilities/screenshotConverter.d.ts +69 -0
  30. package/dist/utilities/screenshotConverter.js +453 -0
  31. package/dist/validation/baseValidator.d.ts +80 -0
  32. package/dist/validation/baseValidator.js +160 -0
  33. package/dist/validation/gridsetValidator.d.ts +36 -0
  34. package/dist/validation/gridsetValidator.js +288 -0
  35. package/dist/validation/index.d.ts +13 -0
  36. package/dist/validation/index.js +69 -0
  37. package/dist/validation/obfValidator.d.ts +44 -0
  38. package/dist/validation/obfValidator.js +530 -0
  39. package/dist/validation/snapValidator.d.ts +33 -0
  40. package/dist/validation/snapValidator.js +237 -0
  41. package/dist/validation/touchChatValidator.d.ts +33 -0
  42. package/dist/validation/touchChatValidator.js +229 -0
  43. package/dist/validation/validationTypes.d.ts +64 -0
  44. package/dist/validation/validationTypes.js +15 -0
  45. package/examples/README.md +7 -0
  46. package/examples/demo.js +143 -0
  47. package/examples/obf/aboutme.json +376 -0
  48. package/examples/obf/array.json +6 -0
  49. package/examples/obf/hash.json +4 -0
  50. package/examples/obf/links.obz +0 -0
  51. package/examples/obf/simple.obf +53 -0
  52. package/examples/package-lock.json +1326 -0
  53. package/examples/package.json +10 -0
  54. package/examples/styling-example.ts +316 -0
  55. package/examples/translate.js +39 -0
  56. package/examples/translate_demo.js +254 -0
  57. package/examples/typescript-demo.ts +251 -0
  58. package/package.json +3 -1
@@ -0,0 +1,36 @@
1
+ import { BaseValidator } from './baseValidator';
2
+ import { ValidationResult } from './validationTypes';
3
+ /**
4
+ * Validator for Grid3/Smartbox Gridset files (.gridset, .gridsetx)
5
+ */
6
+ export declare class GridsetValidator extends BaseValidator {
7
+ constructor();
8
+ /**
9
+ * Validate a Gridset file from disk
10
+ */
11
+ static validateFile(filePath: string): Promise<ValidationResult>;
12
+ /**
13
+ * Check if content is Gridset format
14
+ */
15
+ static identifyFormat(content: any, filename: string): Promise<boolean>;
16
+ /**
17
+ * Main validation method
18
+ */
19
+ validate(content: Buffer | Uint8Array, filename: string, filesize: number): Promise<ValidationResult>;
20
+ /**
21
+ * Validate Gridset structure
22
+ */
23
+ private validateGridsetStructure;
24
+ /**
25
+ * Validate a single page
26
+ */
27
+ private validatePage;
28
+ /**
29
+ * Validate a single cell
30
+ */
31
+ private validateCell;
32
+ /**
33
+ * Validate color format (Grid3 uses ARGB format)
34
+ */
35
+ private isValidGrid3Color;
36
+ }
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.GridsetValidator = void 0;
27
+ /* eslint-disable @typescript-eslint/require-await */
28
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
29
+ /* eslint-disable @typescript-eslint/no-unsafe-return */
30
+ const fs = __importStar(require("fs"));
31
+ const path = __importStar(require("path"));
32
+ const xml2js = __importStar(require("xml2js"));
33
+ const baseValidator_1 = require("./baseValidator");
34
+ /**
35
+ * Validator for Grid3/Smartbox Gridset files (.gridset, .gridsetx)
36
+ */
37
+ class GridsetValidator extends baseValidator_1.BaseValidator {
38
+ constructor() {
39
+ super();
40
+ }
41
+ /**
42
+ * Validate a Gridset file from disk
43
+ */
44
+ static async validateFile(filePath) {
45
+ const validator = new GridsetValidator();
46
+ const content = fs.readFileSync(filePath);
47
+ const stats = fs.statSync(filePath);
48
+ return validator.validate(content, path.basename(filePath), stats.size);
49
+ }
50
+ /**
51
+ * Check if content is Gridset format
52
+ */
53
+ static async identifyFormat(content, filename) {
54
+ const name = filename.toLowerCase();
55
+ if (name.endsWith('.gridset') || name.endsWith('.gridsetx')) {
56
+ return true;
57
+ }
58
+ // Try to parse as XML and check for gridset structure
59
+ try {
60
+ const contentStr = Buffer.isBuffer(content) ? content.toString('utf-8') : content;
61
+ const parser = new xml2js.Parser();
62
+ const result = await parser.parseStringPromise(contentStr);
63
+ return result && (result.gridset || result.Gridset);
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ }
69
+ /**
70
+ * Main validation method
71
+ */
72
+ async validate(content, filename, filesize) {
73
+ this.reset();
74
+ const isEncrypted = filename.toLowerCase().endsWith('.gridsetx');
75
+ // eslint-disable-next-line @typescript-eslint/require-await
76
+ await this.add_check('filename', 'file extension', async () => {
77
+ if (!filename.match(/\.gridsetx?$/)) {
78
+ this.warn('filename should end with .gridset or .gridsetx');
79
+ }
80
+ });
81
+ // For encrypted .gridsetx files, we can't validate the content
82
+ if (isEncrypted) {
83
+ // eslint-disable-next-line @typescript-eslint/require-await
84
+ await this.add_check('encrypted_format', 'encrypted gridsetx file', async () => {
85
+ this.warn('gridsetx files are encrypted and cannot be fully validated');
86
+ });
87
+ return this.buildResult(filename, filesize, 'gridset');
88
+ }
89
+ let xmlObj = null;
90
+ await this.add_check('xml_parse', 'valid XML', async () => {
91
+ try {
92
+ const parser = new xml2js.Parser();
93
+ const contentStr = content.toString('utf-8');
94
+ xmlObj = await parser.parseStringPromise(contentStr);
95
+ }
96
+ catch (e) {
97
+ this.err(`Failed to parse XML: ${e.message}`, true);
98
+ }
99
+ });
100
+ if (!xmlObj) {
101
+ return this.buildResult(filename, filesize, 'gridset');
102
+ }
103
+ // eslint-disable-next-line @typescript-eslint/require-await
104
+ await this.add_check('xml_structure', 'gridset root element', async () => {
105
+ if (!xmlObj.gridset && !xmlObj.Gridset) {
106
+ this.err('missing root gridset element', true);
107
+ }
108
+ });
109
+ const gridset = xmlObj.gridset || xmlObj.Gridset;
110
+ if (gridset) {
111
+ await this.validateGridsetStructure(gridset, filename, content);
112
+ }
113
+ return this.buildResult(filename, filesize, 'gridset');
114
+ }
115
+ /**
116
+ * Validate Gridset structure
117
+ */
118
+ async validateGridsetStructure(gridset, _filename, _content) {
119
+ // Check for required elements
120
+ await this.add_check('gridset_id', 'gridset id', async () => {
121
+ const id = gridset.$.id || gridset.$.Id;
122
+ if (!id) {
123
+ this.warn('gridset should have an id attribute');
124
+ }
125
+ });
126
+ await this.add_check('gridset_name', 'gridset name', async () => {
127
+ const name = gridset.$.name || gridset.$.Name || gridset.name?.[0];
128
+ if (!name) {
129
+ this.warn('gridset should have a name attribute or element');
130
+ }
131
+ });
132
+ // Check for pages
133
+ await this.add_check('pages', 'pages element', async () => {
134
+ if (!gridset.pages && !gridset.Pages) {
135
+ this.err('gridset must have a pages element');
136
+ }
137
+ else {
138
+ const pages = gridset.pages || gridset.Pages;
139
+ if (!pages[0] || !Array.isArray(pages[0].page)) {
140
+ this.warn('pages should contain at least one page element');
141
+ }
142
+ }
143
+ });
144
+ // Validate individual pages
145
+ const pages = gridset.pages?.[0] || gridset.Pages?.[0];
146
+ if (pages && Array.isArray(pages.page)) {
147
+ await this.add_check('page_count', 'page count', async () => {
148
+ if (pages.page.length === 0) {
149
+ this.err('gridset must contain at least one page');
150
+ }
151
+ });
152
+ for (let i = 0; i < Math.min(pages.page.length, 10); i++) {
153
+ // Limit to first 10 pages to avoid excessive validation
154
+ const page = pages.page[i];
155
+ await this.validatePage(page, i);
156
+ }
157
+ }
158
+ // Check for fixedCellSize
159
+ await this.add_check('fixed_cell_size', 'fixedCellSize element', async () => {
160
+ const fixedSize = gridset.fixedCellSize || gridset.FixedCellSize;
161
+ if (!fixedSize) {
162
+ this.warn('gridset should have a fixedCellSize element for consistency');
163
+ }
164
+ else {
165
+ // Validate fixedCellSize structure
166
+ const size = fixedSize[0];
167
+ if (size) {
168
+ const width = size.$.width || size.$.Width;
169
+ const height = size.$.height || size.$.Height;
170
+ if (!width || !height) {
171
+ this.warn('fixedCellSize should have both width and height attributes');
172
+ }
173
+ else if (isNaN(parseInt(width)) || isNaN(parseInt(height))) {
174
+ this.err('fixedCellSize width and height must be valid numbers');
175
+ }
176
+ }
177
+ }
178
+ });
179
+ // Check for styles
180
+ await this.add_check('styles', 'styles element', async () => {
181
+ const styles = gridset.styles || gridset.Styles;
182
+ if (!styles) {
183
+ this.warn('gridset should have a styles element for consistent formatting');
184
+ }
185
+ });
186
+ }
187
+ /**
188
+ * Validate a single page
189
+ */
190
+ async validatePage(page, index) {
191
+ await this.add_check(`page[${index}]_id`, `page ${index} id`, async () => {
192
+ const id = page.$.id || page.$.Id;
193
+ if (!id) {
194
+ this.err(`page at index ${index} is missing id attribute`);
195
+ }
196
+ });
197
+ await this.add_check(`page[${index}]_name`, `page ${index} name`, async () => {
198
+ const name = page.$.name || page.$.Name || page.name?.[0];
199
+ if (!name) {
200
+ this.warn(`page ${index} should have a name`);
201
+ }
202
+ });
203
+ // Check for cells
204
+ await this.add_check(`page[${index}]_cells`, `page ${index} cells`, async () => {
205
+ const cells = page.cells || page.Cells;
206
+ if (!cells) {
207
+ this.warn(`page ${index} should have a cells element`);
208
+ }
209
+ else {
210
+ const cellArray = cells[0]?.cell || cells[0]?.Cell;
211
+ if (!cellArray || !Array.isArray(cellArray) || cellArray.length === 0) {
212
+ this.warn(`page ${index} should contain at least one cell`);
213
+ }
214
+ }
215
+ });
216
+ // Validate cells if present
217
+ const cells = page.cells?.[0] || page.Cells?.[0];
218
+ if (cells) {
219
+ const cellArray = cells.cell || cells.Cell;
220
+ if (Array.isArray(cellArray) && cellArray.length > 0) {
221
+ // Sample a few cells to validate
222
+ const sampleSize = Math.min(cellArray.length, 5);
223
+ for (let i = 0; i < sampleSize; i++) {
224
+ await this.validateCell(cellArray[i], index, i);
225
+ }
226
+ }
227
+ }
228
+ }
229
+ /**
230
+ * Validate a single cell
231
+ */
232
+ async validateCell(cell, pageIdx, cellIdx) {
233
+ await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_id`, `cell id`, async () => {
234
+ const id = cell.$.id || cell.$.Id;
235
+ if (!id) {
236
+ this.warn(`cell ${cellIdx} on page ${pageIdx} is missing id attribute`);
237
+ }
238
+ });
239
+ await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_content`, `cell content`, async () => {
240
+ const label = cell.$.label || cell.$.Label;
241
+ const image = cell.$.image || cell.$.Image;
242
+ if (!label && !image) {
243
+ this.warn(`cell ${cellIdx} on page ${pageIdx} should have a label or image`);
244
+ }
245
+ });
246
+ // Check for color attributes
247
+ const backgroundColor = cell.$.backgroundColor || cell.$.BackgroundColor;
248
+ const _color = cell.$.color || cell.$.Color;
249
+ if (backgroundColor) {
250
+ await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_bg_color`, `cell background color`, async () => {
251
+ // Grid3 colors can be in various formats: named colors, hex, ARGB
252
+ // We just check it's not empty
253
+ if (backgroundColor.length === 0) {
254
+ this.warn(`cell ${cellIdx} has empty background color`);
255
+ }
256
+ });
257
+ }
258
+ // Check for valid jump references
259
+ const jump = cell.$.jump || cell.$.Jump;
260
+ if (jump) {
261
+ await this.add_check(`page[${pageIdx}]_cell[${cellIdx}]_jump`, `cell jump reference`, async () => {
262
+ if (typeof jump !== 'string' || jump.length === 0) {
263
+ this.warn(`cell ${cellIdx} has invalid jump reference`);
264
+ }
265
+ });
266
+ }
267
+ }
268
+ /**
269
+ * Validate color format (Grid3 uses ARGB format)
270
+ */
271
+ isValidGrid3Color(color) {
272
+ if (!color || color.length === 0)
273
+ return false;
274
+ // Named colors are valid
275
+ if (/^[a-zA-Z]+$/.test(color))
276
+ return true;
277
+ // ARGB format: #AARRGGBB or #RRGGBB
278
+ if (color.startsWith('#')) {
279
+ return color.length === 7 || color.length === 9;
280
+ }
281
+ // RGB format: rgb(r,g,b) or rgba(r,g,b,a)
282
+ if (color.startsWith('rgb')) {
283
+ return true; // Simplified check
284
+ }
285
+ return false;
286
+ }
287
+ }
288
+ exports.GridsetValidator = GridsetValidator;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Validation system for AAC processors
3
+ * Provides consistent validation across all supported formats
4
+ */
5
+ export { ValidationError, ValidationCheck, ValidationResult, ValidationOptions, ValidationRule, } from './validationTypes';
6
+ export { BaseValidator } from './baseValidator';
7
+ export { ObfValidator } from './obfValidator';
8
+ export { GridsetValidator } from './gridsetValidator';
9
+ export { SnapValidator } from './snapValidator';
10
+ export { TouchChatValidator } from './touchChatValidator';
11
+ import { BaseValidator } from './baseValidator';
12
+ export declare function getValidatorForFormat(format: string): BaseValidator | null;
13
+ export declare function getValidatorForFile(filename: string): BaseValidator | null;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Validation system for AAC processors
4
+ * Provides consistent validation across all supported formats
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.TouchChatValidator = exports.SnapValidator = exports.GridsetValidator = exports.ObfValidator = exports.BaseValidator = exports.ValidationError = void 0;
8
+ exports.getValidatorForFormat = getValidatorForFormat;
9
+ exports.getValidatorForFile = getValidatorForFile;
10
+ var validationTypes_1 = require("./validationTypes");
11
+ Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return validationTypes_1.ValidationError; } });
12
+ var baseValidator_1 = require("./baseValidator");
13
+ Object.defineProperty(exports, "BaseValidator", { enumerable: true, get: function () { return baseValidator_1.BaseValidator; } });
14
+ // Individual format validators
15
+ var obfValidator_1 = require("./obfValidator");
16
+ Object.defineProperty(exports, "ObfValidator", { enumerable: true, get: function () { return obfValidator_1.ObfValidator; } });
17
+ var gridsetValidator_1 = require("./gridsetValidator");
18
+ Object.defineProperty(exports, "GridsetValidator", { enumerable: true, get: function () { return gridsetValidator_1.GridsetValidator; } });
19
+ var snapValidator_1 = require("./snapValidator");
20
+ Object.defineProperty(exports, "SnapValidator", { enumerable: true, get: function () { return snapValidator_1.SnapValidator; } });
21
+ var touchChatValidator_1 = require("./touchChatValidator");
22
+ Object.defineProperty(exports, "TouchChatValidator", { enumerable: true, get: function () { return touchChatValidator_1.TouchChatValidator; } });
23
+ /**
24
+ * Main validator factory
25
+ * Returns the appropriate validator for a given format
26
+ */
27
+ const obfValidator_2 = require("./obfValidator");
28
+ const gridsetValidator_2 = require("./gridsetValidator");
29
+ const snapValidator_2 = require("./snapValidator");
30
+ const touchChatValidator_2 = require("./touchChatValidator");
31
+ function getValidatorForFormat(format) {
32
+ switch (format.toLowerCase()) {
33
+ case 'obf':
34
+ case 'obz':
35
+ return new obfValidator_2.ObfValidator();
36
+ case 'gridset':
37
+ case 'gridsetx':
38
+ return new gridsetValidator_2.GridsetValidator();
39
+ case 'snap':
40
+ case 'spb':
41
+ case 'sps':
42
+ return new snapValidator_2.SnapValidator();
43
+ case 'touchchat':
44
+ case 'ce':
45
+ return new touchChatValidator_2.TouchChatValidator();
46
+ default:
47
+ return null;
48
+ }
49
+ }
50
+ function getValidatorForFile(filename) {
51
+ const ext = filename.toLowerCase().split('.').pop();
52
+ if (!ext)
53
+ return null;
54
+ switch (ext) {
55
+ case 'obf':
56
+ case 'obz':
57
+ return new obfValidator_2.ObfValidator();
58
+ case 'gridset':
59
+ case 'gridsetx':
60
+ return new gridsetValidator_2.GridsetValidator();
61
+ case 'spb':
62
+ case 'sps':
63
+ return new snapValidator_2.SnapValidator();
64
+ case 'ce':
65
+ return new touchChatValidator_2.TouchChatValidator();
66
+ default:
67
+ return null;
68
+ }
69
+ }
@@ -0,0 +1,44 @@
1
+ import { BaseValidator } from './baseValidator';
2
+ import { ValidationResult } from './validationTypes';
3
+ /**
4
+ * Validator for Open Board Format (OBF/OBZ) files
5
+ */
6
+ export declare class ObfValidator extends BaseValidator {
7
+ constructor();
8
+ /**
9
+ * Validate an OBF file from disk
10
+ */
11
+ static validateFile(filePath: string): Promise<ValidationResult>;
12
+ /**
13
+ * Check if content is OBF format
14
+ */
15
+ static identifyFormat(content: any, filename: string): Promise<boolean>;
16
+ /**
17
+ * Main validation method
18
+ */
19
+ validate(content: Buffer | Uint8Array, filename: string, filesize: number): Promise<ValidationResult>;
20
+ /**
21
+ * Validate OBF content
22
+ */
23
+ private validateObf;
24
+ /**
25
+ * Validate OBZ (zip) content
26
+ */
27
+ private validateObz;
28
+ /**
29
+ * Validate OBF board structure
30
+ */
31
+ private validateBoardStructure;
32
+ /**
33
+ * Validate a single button
34
+ */
35
+ private validateButton;
36
+ /**
37
+ * Validate OBZ structure
38
+ */
39
+ private validateObzStructure;
40
+ /**
41
+ * Validate manifest structure
42
+ */
43
+ private validateManifest;
44
+ }