@willwade/aac-processors 0.1.5 → 0.1.6
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 +14 -0
- package/dist/browser/index.browser.js +15 -1
- package/dist/browser/processors/gridset/password.js +11 -0
- package/dist/browser/processors/gridsetProcessor.js +42 -46
- package/dist/browser/processors/obfProcessor.js +47 -63
- package/dist/browser/processors/snapProcessor.js +1031 -0
- package/dist/browser/processors/touchchatProcessor.js +1004 -0
- package/dist/browser/utils/io.js +20 -0
- package/dist/browser/utils/sqlite.js +109 -0
- package/dist/browser/utils/zip.js +54 -0
- package/dist/browser/validation/snapValidator.js +200 -0
- package/dist/browser/validation/touchChatValidator.js +202 -0
- package/dist/index.browser.d.ts +7 -0
- package/dist/index.browser.js +19 -2
- package/dist/processors/gridset/helpers.js +3 -4
- package/dist/processors/gridset/index.d.ts +1 -1
- package/dist/processors/gridset/index.js +3 -2
- package/dist/processors/gridset/password.d.ts +3 -2
- package/dist/processors/gridset/password.js +12 -0
- package/dist/processors/gridset/wordlistHelpers.js +107 -51
- package/dist/processors/gridsetProcessor.js +40 -44
- package/dist/processors/obfProcessor.js +46 -62
- package/dist/processors/snapProcessor.js +60 -54
- package/dist/processors/touchchatProcessor.js +38 -36
- package/dist/utils/io.d.ts +2 -0
- package/dist/utils/io.js +22 -0
- package/dist/utils/sqlite.d.ts +21 -0
- package/dist/utils/sqlite.js +137 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.js +80 -0
- package/docs/BROWSER_USAGE.md +2 -10
- package/examples/README.md +3 -75
- package/examples/vitedemo/README.md +13 -7
- package/examples/vitedemo/index.html +2 -2
- package/examples/vitedemo/package-lock.json +9 -0
- package/examples/vitedemo/package.json +1 -0
- package/examples/vitedemo/src/main.ts +48 -2
- package/examples/vitedemo/src/vite-env.d.ts +1 -0
- package/package.json +3 -1
- package/examples/browser-test-server.js +0 -81
package/dist/index.browser.js
CHANGED
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* **NOTE: Gridset .gridsetx files**
|
|
8
8
|
* GridsetProcessor supports regular `.gridset` files in browser.
|
|
9
9
|
* Encrypted `.gridsetx` files require Node.js for crypto operations and are not supported in browser.
|
|
10
|
+
*
|
|
11
|
+
* **NOTE: SQLite-backed formats**
|
|
12
|
+
* Snap (.sps/.spb) and TouchChat (.ce) require a WASM-backed SQLite engine.
|
|
13
|
+
* Configure `sql.js` in browser builds via `configureSqlJs()` before loading these formats.
|
|
10
14
|
*/
|
|
11
15
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
16
|
if (k2 === undefined) k2 = k;
|
|
@@ -23,7 +27,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
23
27
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
24
28
|
};
|
|
25
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.AstericsGridProcessor = exports.ApplePanelsProcessor = exports.GridsetProcessor = exports.ObfProcessor = exports.OpmlProcessor = exports.DotProcessor = void 0;
|
|
30
|
+
exports.configureSqlJs = exports.AstericsGridProcessor = exports.ApplePanelsProcessor = exports.TouchChatProcessor = exports.SnapProcessor = exports.GridsetProcessor = exports.ObfProcessor = exports.OpmlProcessor = exports.DotProcessor = void 0;
|
|
27
31
|
exports.getProcessor = getProcessor;
|
|
28
32
|
exports.getSupportedExtensions = getSupportedExtensions;
|
|
29
33
|
exports.isExtensionSupported = isExtensionSupported;
|
|
@@ -44,6 +48,10 @@ var obfProcessor_1 = require("./processors/obfProcessor");
|
|
|
44
48
|
Object.defineProperty(exports, "ObfProcessor", { enumerable: true, get: function () { return obfProcessor_1.ObfProcessor; } });
|
|
45
49
|
var gridsetProcessor_1 = require("./processors/gridsetProcessor");
|
|
46
50
|
Object.defineProperty(exports, "GridsetProcessor", { enumerable: true, get: function () { return gridsetProcessor_1.GridsetProcessor; } });
|
|
51
|
+
var snapProcessor_1 = require("./processors/snapProcessor");
|
|
52
|
+
Object.defineProperty(exports, "SnapProcessor", { enumerable: true, get: function () { return snapProcessor_1.SnapProcessor; } });
|
|
53
|
+
var touchchatProcessor_1 = require("./processors/touchchatProcessor");
|
|
54
|
+
Object.defineProperty(exports, "TouchChatProcessor", { enumerable: true, get: function () { return touchchatProcessor_1.TouchChatProcessor; } });
|
|
47
55
|
var applePanelsProcessor_1 = require("./processors/applePanelsProcessor");
|
|
48
56
|
Object.defineProperty(exports, "ApplePanelsProcessor", { enumerable: true, get: function () { return applePanelsProcessor_1.ApplePanelsProcessor; } });
|
|
49
57
|
var astericsGridProcessor_1 = require("./processors/astericsGridProcessor");
|
|
@@ -52,8 +60,12 @@ const dotProcessor_2 = require("./processors/dotProcessor");
|
|
|
52
60
|
const opmlProcessor_2 = require("./processors/opmlProcessor");
|
|
53
61
|
const obfProcessor_2 = require("./processors/obfProcessor");
|
|
54
62
|
const gridsetProcessor_2 = require("./processors/gridsetProcessor");
|
|
63
|
+
const snapProcessor_2 = require("./processors/snapProcessor");
|
|
64
|
+
const touchchatProcessor_2 = require("./processors/touchchatProcessor");
|
|
55
65
|
const applePanelsProcessor_2 = require("./processors/applePanelsProcessor");
|
|
56
66
|
const astericsGridProcessor_2 = require("./processors/astericsGridProcessor");
|
|
67
|
+
var sqlite_1 = require("./utils/sqlite");
|
|
68
|
+
Object.defineProperty(exports, "configureSqlJs", { enumerable: true, get: function () { return sqlite_1.configureSqlJs; } });
|
|
57
69
|
/**
|
|
58
70
|
* Factory function to get the appropriate processor for a file extension
|
|
59
71
|
* @param filePathOrExtension - File path or extension (e.g., '.dot', '/path/to/file.obf')
|
|
@@ -74,6 +86,11 @@ function getProcessor(filePathOrExtension) {
|
|
|
74
86
|
return new obfProcessor_2.ObfProcessor();
|
|
75
87
|
case '.gridset':
|
|
76
88
|
return new gridsetProcessor_2.GridsetProcessor();
|
|
89
|
+
case '.spb':
|
|
90
|
+
case '.sps':
|
|
91
|
+
return new snapProcessor_2.SnapProcessor();
|
|
92
|
+
case '.ce':
|
|
93
|
+
return new touchchatProcessor_2.TouchChatProcessor();
|
|
77
94
|
case '.plist':
|
|
78
95
|
return new applePanelsProcessor_2.ApplePanelsProcessor();
|
|
79
96
|
case '.grd':
|
|
@@ -87,7 +104,7 @@ function getProcessor(filePathOrExtension) {
|
|
|
87
104
|
* @returns Array of supported file extensions
|
|
88
105
|
*/
|
|
89
106
|
function getSupportedExtensions() {
|
|
90
|
-
return ['.dot', '.opml', '.obf', '.obz', '.gridset', '.plist', '.grd'];
|
|
107
|
+
return ['.dot', '.opml', '.obf', '.obz', '.gridset', '.spb', '.sps', '.ce', '.plist', '.grd'];
|
|
91
108
|
}
|
|
92
109
|
/**
|
|
93
110
|
* Check if a file extension is supported
|
|
@@ -50,6 +50,7 @@ const child_process_1 = require("child_process");
|
|
|
50
50
|
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
51
51
|
const dotnetTicks_1 = require("../../utils/dotnetTicks");
|
|
52
52
|
const password_1 = require("./password");
|
|
53
|
+
const zip_1 = require("../../utils/zip");
|
|
53
54
|
function normalizeZipPath(p) {
|
|
54
55
|
const unified = p.replace(/\\/g, '/');
|
|
55
56
|
try {
|
|
@@ -97,10 +98,8 @@ function getAllowedImageEntries(tree) {
|
|
|
97
98
|
*/
|
|
98
99
|
async function openImage(gridsetBuffer, entryPath, password = (0, password_1.resolveGridsetPasswordFromEnv)()) {
|
|
99
100
|
try {
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
const zip = await JSZip.loadAsync(gridsetBuffer);
|
|
103
|
-
const entries = (0, password_1.getZipEntriesWithPassword)(zip, password);
|
|
101
|
+
const { zip } = await (0, zip_1.openZipFromInput)(gridsetBuffer);
|
|
102
|
+
const entries = (0, password_1.getZipEntriesFromAdapter)(zip, password);
|
|
104
103
|
const want = normalizeZipPath(entryPath);
|
|
105
104
|
const entry = entries.find((e) => normalizeZipPath(e.entryName) === want);
|
|
106
105
|
if (!entry)
|
|
@@ -15,7 +15,7 @@ import { CellBackgroundShape } from './styleHelpers';
|
|
|
15
15
|
import { Grid3CellType } from './pluginTypes';
|
|
16
16
|
import { Grid3CommandCategory } from './commands';
|
|
17
17
|
export { ensureAlphaChannel, darkenColor, lightenColor, hexToRgba, rgbaToHex } from './colorUtils';
|
|
18
|
-
export { resolveGridsetPassword, getZipEntriesWithPassword, resolveGridsetPasswordFromEnv, } from './password';
|
|
18
|
+
export { resolveGridsetPassword, getZipEntriesWithPassword, getZipEntriesFromAdapter, resolveGridsetPasswordFromEnv, } from './password';
|
|
19
19
|
export { getPageTokenImageMap, getAllowedImageEntries, openImage, generateGrid3Guid, createSettingsXml, createFileMapXml, getCommonDocumentsPath, findGrid3UserPaths, findGrid3HistoryDatabases, findGrid3Vocabularies, findGrid3UserHistory, findGrid3Users, isGrid3Installed, readGrid3History, readGrid3HistoryForUser, readAllGrid3History, type Grid3UserPath, type Grid3VocabularyPath, type Grid3HistoryEntry, } from './helpers';
|
|
20
20
|
export { parseSymbolReference, isSymbolReference, resolveSymbolReference, getAvailableSymbolLibraries, getSymbolLibraryInfo, extractSymbolReferences, analyzeSymbolUsage, createSymbolReference, getSymbolLibraryName, getSymbolPath, isKnownSymbolLibrary, getSymbolLibraryDisplayName, getDefaultGrid3Path, getSymbolLibrariesDir, getSymbolSearchIndexesDir, symbolReferenceToFilename, SYMBOL_LIBRARIES, type SymbolReference, type SymbolLibraryInfo, type SymbolResolutionOptions, type SymbolResolutionResult, type SymbolUsageStats, type SymbolLibraryName, } from './symbols';
|
|
21
21
|
export { getSymbolsDir, getSymbolSearchDir } from './symbols';
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* - Image resolution helpers
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.
|
|
14
|
-
exports.GRID3_COMMAND_CATEGORIES = exports.GRID3_CELL_TYPES = exports.GRID3_CELL_SHAPES = exports.GRID3_PLUGIN_IDS = exports.GRID3_COMMAND_IDS = exports.getSymbolSearchStats = exports.countLibrarySymbols = exports.getSearchSuggestions = exports.getAllSearchTerms = exports.getSymbolDisplayName = exports.getSymbolFilename = exports.searchSymbolsWithReferences = exports.searchSymbols = exports.loadSearchIndexes = exports.parsePixFile = exports.createSymbolManifest = exports.exportSymbolReferencesToCsv = exports.suggestExtractionStrategy = exports.analyzeSymbolExtraction = exports.convertToAstericsImage = exports.extractSymbolLibraryImage = exports.extractButtonImage = exports.parseImageSymbolReference = exports.isSymbolLibraryReference = exports.resolveGrid3CellImage = exports.getSymbolSearchDir = exports.getSymbolsDir = exports.SYMBOL_LIBRARIES = exports.symbolReferenceToFilename = exports.getSymbolSearchIndexesDir = exports.getSymbolLibrariesDir = exports.getDefaultGrid3Path = exports.getSymbolLibraryDisplayName = exports.isKnownSymbolLibrary = exports.getSymbolPath = exports.getSymbolLibraryName = exports.createSymbolReference = exports.analyzeSymbolUsage = exports.extractSymbolReferences = exports.getSymbolLibraryInfo = exports.getAvailableSymbolLibraries = exports.resolveSymbolReference = exports.isSymbolReference = void 0;
|
|
13
|
+
exports.readAllGrid3History = exports.readGrid3HistoryForUser = exports.readGrid3History = exports.isGrid3Installed = exports.findGrid3Users = exports.findGrid3UserHistory = exports.findGrid3Vocabularies = exports.findGrid3HistoryDatabases = exports.findGrid3UserPaths = exports.getCommonDocumentsPath = exports.createFileMapXml = exports.createSettingsXml = exports.generateGrid3Guid = exports.openImage = exports.getAllowedImageEntries = exports.getPageTokenImageMap = exports.resolveGridsetPasswordFromEnv = exports.getZipEntriesFromAdapter = exports.getZipEntriesWithPassword = exports.resolveGridsetPassword = exports.rgbaToHex = exports.hexToRgba = exports.lightenColor = exports.darkenColor = exports.ensureAlphaChannel = exports.Grid3CommandCategory = exports.GRID3_COMMANDS = exports.extractCommandParameters = exports.getAllPluginIds = exports.getAllCommandIds = exports.getCommandsByCategory = exports.getCommandsByPlugin = exports.getCommandDefinition = exports.detectCommand = exports.isRegularCell = exports.isAutoContentCell = exports.isLiveCell = exports.isWorkspaceCell = exports.getCellTypeDisplayName = exports.AUTOCONTENT_TYPES = exports.LIVECELL_TYPES = exports.WORKSPACE_TYPES = exports.Grid3CellType = exports.detectPluginCellType = exports.createCategoryStyle = exports.createDefaultStylesXml = exports.CATEGORY_STYLES = exports.DEFAULT_GRID3_STYLES = exports.SHAPE_NAMES = exports.CellBackgroundShape = void 0;
|
|
14
|
+
exports.GRID3_COMMAND_CATEGORIES = exports.GRID3_CELL_TYPES = exports.GRID3_CELL_SHAPES = exports.GRID3_PLUGIN_IDS = exports.GRID3_COMMAND_IDS = exports.getSymbolSearchStats = exports.countLibrarySymbols = exports.getSearchSuggestions = exports.getAllSearchTerms = exports.getSymbolDisplayName = exports.getSymbolFilename = exports.searchSymbolsWithReferences = exports.searchSymbols = exports.loadSearchIndexes = exports.parsePixFile = exports.createSymbolManifest = exports.exportSymbolReferencesToCsv = exports.suggestExtractionStrategy = exports.analyzeSymbolExtraction = exports.convertToAstericsImage = exports.extractSymbolLibraryImage = exports.extractButtonImage = exports.parseImageSymbolReference = exports.isSymbolLibraryReference = exports.resolveGrid3CellImage = exports.getSymbolSearchDir = exports.getSymbolsDir = exports.SYMBOL_LIBRARIES = exports.symbolReferenceToFilename = exports.getSymbolSearchIndexesDir = exports.getSymbolLibrariesDir = exports.getDefaultGrid3Path = exports.getSymbolLibraryDisplayName = exports.isKnownSymbolLibrary = exports.getSymbolPath = exports.getSymbolLibraryName = exports.createSymbolReference = exports.analyzeSymbolUsage = exports.extractSymbolReferences = exports.getSymbolLibraryInfo = exports.getAvailableSymbolLibraries = exports.resolveSymbolReference = exports.isSymbolReference = exports.parseSymbolReference = void 0;
|
|
15
15
|
// Style helpers
|
|
16
16
|
var styleHelpers_1 = require("./styleHelpers");
|
|
17
17
|
Object.defineProperty(exports, "CellBackgroundShape", { enumerable: true, get: function () { return styleHelpers_1.CellBackgroundShape; } });
|
|
@@ -59,6 +59,7 @@ Object.defineProperty(exports, "rgbaToHex", { enumerable: true, get: function ()
|
|
|
59
59
|
var password_1 = require("./password");
|
|
60
60
|
Object.defineProperty(exports, "resolveGridsetPassword", { enumerable: true, get: function () { return password_1.resolveGridsetPassword; } });
|
|
61
61
|
Object.defineProperty(exports, "getZipEntriesWithPassword", { enumerable: true, get: function () { return password_1.getZipEntriesWithPassword; } });
|
|
62
|
+
Object.defineProperty(exports, "getZipEntriesFromAdapter", { enumerable: true, get: function () { return password_1.getZipEntriesFromAdapter; } });
|
|
62
63
|
Object.defineProperty(exports, "resolveGridsetPasswordFromEnv", { enumerable: true, get: function () { return password_1.resolveGridsetPasswordFromEnv; } });
|
|
63
64
|
// Helper functions
|
|
64
65
|
var helpers_1 = require("./helpers");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type JSZip from 'jszip';
|
|
2
2
|
import { ProcessorOptions } from '../../core/baseProcessor';
|
|
3
3
|
import { ProcessorInput } from '../../utils/io';
|
|
4
|
+
import { type ZipAdapter } from '../../utils/zip';
|
|
4
5
|
/**
|
|
5
6
|
* Resolve the password to use for Grid3 archives.
|
|
6
7
|
* Preference order:
|
|
@@ -18,11 +19,11 @@ export declare function resolveGridsetPasswordFromEnv(): string | undefined;
|
|
|
18
19
|
* @param password - Optional password (kept for API compatibility, not used with JSZip)
|
|
19
20
|
* @returns Array of entry objects with name and data
|
|
20
21
|
*/
|
|
21
|
-
type ZipEntry = {
|
|
22
|
+
export type ZipEntry = {
|
|
22
23
|
name: string;
|
|
23
24
|
entryName: string;
|
|
24
25
|
dir: boolean;
|
|
25
26
|
getData: () => Promise<Uint8Array>;
|
|
26
27
|
};
|
|
27
28
|
export declare function getZipEntriesWithPassword(zip: JSZip, password?: string): ZipEntry[];
|
|
28
|
-
export
|
|
29
|
+
export declare function getZipEntriesFromAdapter(zip: ZipAdapter, password?: string): ZipEntry[];
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.resolveGridsetPassword = resolveGridsetPassword;
|
|
4
4
|
exports.resolveGridsetPasswordFromEnv = resolveGridsetPasswordFromEnv;
|
|
5
5
|
exports.getZipEntriesWithPassword = getZipEntriesWithPassword;
|
|
6
|
+
exports.getZipEntriesFromAdapter = getZipEntriesFromAdapter;
|
|
6
7
|
function getExtension(source) {
|
|
7
8
|
const index = source.lastIndexOf('.');
|
|
8
9
|
if (index === -1)
|
|
@@ -52,3 +53,14 @@ function getZipEntriesWithPassword(zip, password) {
|
|
|
52
53
|
});
|
|
53
54
|
return entries;
|
|
54
55
|
}
|
|
56
|
+
function getZipEntriesFromAdapter(zip, password) {
|
|
57
|
+
if (password) {
|
|
58
|
+
console.warn('Zip password support is handled at the archive level for .gridsetx files.');
|
|
59
|
+
}
|
|
60
|
+
return zip.listFiles().map((entryName) => ({
|
|
61
|
+
name: entryName,
|
|
62
|
+
entryName,
|
|
63
|
+
dir: false,
|
|
64
|
+
getData: () => zip.readFile(entryName),
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
@@ -9,6 +9,29 @@
|
|
|
9
9
|
* Note: Wordlists are only supported in Grid3 format. Other AAC formats
|
|
10
10
|
* do not have equivalent wordlist functionality.
|
|
11
11
|
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
12
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
36
|
exports.createWordlist = createWordlist;
|
|
14
37
|
exports.wordlistToXml = wordlistToXml;
|
|
@@ -16,7 +39,9 @@ exports.extractWordlists = extractWordlists;
|
|
|
16
39
|
exports.updateWordlist = updateWordlist;
|
|
17
40
|
const fast_xml_parser_1 = require("fast-xml-parser");
|
|
18
41
|
const password_1 = require("./password");
|
|
42
|
+
const zip_1 = require("../../utils/zip");
|
|
19
43
|
const io_1 = require("../../utils/io");
|
|
44
|
+
const io_2 = require("../../utils/io");
|
|
20
45
|
/**
|
|
21
46
|
* Creates a WordList object from an array of words/phrases or a dictionary
|
|
22
47
|
*
|
|
@@ -105,55 +130,52 @@ function wordlistToXml(wordlist) {
|
|
|
105
130
|
async function extractWordlists(gridsetBuffer, password = (0, password_1.resolveGridsetPasswordFromEnv)()) {
|
|
106
131
|
const wordlists = new Map();
|
|
107
132
|
const parser = new fast_xml_parser_1.XMLParser();
|
|
108
|
-
let zip;
|
|
109
133
|
try {
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
const { zip } = await (0, zip_1.openZipFromInput)(gridsetBuffer);
|
|
135
|
+
const entries = (0, password_1.getZipEntriesFromAdapter)(zip, password);
|
|
136
|
+
// Process each grid file
|
|
137
|
+
for (const entry of entries) {
|
|
138
|
+
if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
|
|
139
|
+
try {
|
|
140
|
+
const xmlContent = (0, io_2.decodeText)(await entry.getData());
|
|
141
|
+
const data = parser.parse(xmlContent);
|
|
142
|
+
const grid = data.Grid || data.grid;
|
|
143
|
+
if (!grid || !grid.WordList) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
// Extract grid name from path (e.g., "Grids/MyGrid/grid.xml" -> "MyGrid")
|
|
147
|
+
const match = entry.entryName.match(/^Grids\/([^/]+)\//);
|
|
148
|
+
const gridName = match ? match[1] : entry.entryName;
|
|
149
|
+
// Parse wordlist items
|
|
150
|
+
const wordlistData = grid.WordList;
|
|
151
|
+
const itemsContainer = wordlistData.Items || wordlistData.items;
|
|
152
|
+
if (!itemsContainer) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const itemArray = Array.isArray(itemsContainer.WordListItem)
|
|
156
|
+
? itemsContainer.WordListItem
|
|
157
|
+
: itemsContainer.WordListItem
|
|
158
|
+
? [itemsContainer.WordListItem]
|
|
159
|
+
: [];
|
|
160
|
+
const items = itemArray.map((item) => ({
|
|
161
|
+
text: item.Text?.s?.r || item.text?.s?.r || '',
|
|
162
|
+
image: item.Image || item.image || undefined,
|
|
163
|
+
partOfSpeech: item.PartOfSpeech || item.partOfSpeech || 'Unknown',
|
|
164
|
+
}));
|
|
165
|
+
if (items.length > 0) {
|
|
166
|
+
wordlists.set(gridName, { items });
|
|
167
|
+
}
|
|
136
168
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
? [itemsContainer.WordListItem]
|
|
141
|
-
: [];
|
|
142
|
-
const items = itemArray.map((item) => ({
|
|
143
|
-
text: item.Text?.s?.r || item.text?.s?.r || '',
|
|
144
|
-
image: item.Image || item.image || undefined,
|
|
145
|
-
partOfSpeech: item.PartOfSpeech || item.partOfSpeech || 'Unknown',
|
|
146
|
-
}));
|
|
147
|
-
if (items.length > 0) {
|
|
148
|
-
wordlists.set(gridName, { items });
|
|
169
|
+
catch (error) {
|
|
170
|
+
// Skip grids with parsing errors
|
|
171
|
+
console.warn(`Failed to extract wordlist from ${entry.entryName}:`, error);
|
|
149
172
|
}
|
|
150
173
|
}
|
|
151
|
-
catch (error) {
|
|
152
|
-
// Skip grids with parsing errors
|
|
153
|
-
console.warn(`Failed to extract wordlist from ${entry.entryName}:`, error);
|
|
154
|
-
}
|
|
155
174
|
}
|
|
156
175
|
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw new Error(`Invalid gridset buffer: ${error.message}`);
|
|
178
|
+
}
|
|
157
179
|
return wordlists;
|
|
158
180
|
}
|
|
159
181
|
/**
|
|
@@ -178,16 +200,45 @@ async function updateWordlist(gridsetBuffer, gridName, wordlist, password = (0,
|
|
|
178
200
|
indentBy: ' ',
|
|
179
201
|
suppressEmptyNode: false,
|
|
180
202
|
});
|
|
181
|
-
let
|
|
203
|
+
let entries;
|
|
204
|
+
let saveZip = null;
|
|
205
|
+
let updateEntry = null;
|
|
182
206
|
try {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
207
|
+
if ((0, io_1.isNodeRuntime)()) {
|
|
208
|
+
const AdmZip = (0, io_1.getNodeRequire)()('adm-zip');
|
|
209
|
+
const zip = new AdmZip(Buffer.from(gridsetBuffer));
|
|
210
|
+
entries = zip.getEntries().map((entry) => ({
|
|
211
|
+
entryName: entry.entryName,
|
|
212
|
+
getData: () => Promise.resolve(entry.getData()),
|
|
213
|
+
}));
|
|
214
|
+
updateEntry = (entryName, xml) => {
|
|
215
|
+
zip.addFile(entryName, Buffer.from(xml, 'utf8'));
|
|
216
|
+
};
|
|
217
|
+
saveZip = () => Promise.resolve(zip.toBuffer());
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const module = await Promise.resolve().then(() => __importStar(require('jszip')));
|
|
221
|
+
const JSZip = module.default || module;
|
|
222
|
+
const zip = await JSZip.loadAsync(gridsetBuffer);
|
|
223
|
+
entries = (0, password_1.getZipEntriesFromAdapter)({
|
|
224
|
+
listFiles: () => Object.keys(zip.files),
|
|
225
|
+
readFile: async (name) => {
|
|
226
|
+
const file = zip.file(name);
|
|
227
|
+
if (!file) {
|
|
228
|
+
throw new Error(`Zip entry not found: ${name}`);
|
|
229
|
+
}
|
|
230
|
+
return file.async('uint8array');
|
|
231
|
+
},
|
|
232
|
+
}, password);
|
|
233
|
+
updateEntry = (entryName, xml) => {
|
|
234
|
+
zip.file(entryName, xml, { binary: false });
|
|
235
|
+
};
|
|
236
|
+
saveZip = async () => zip.generateAsync({ type: 'uint8array' });
|
|
237
|
+
}
|
|
186
238
|
}
|
|
187
239
|
catch (error) {
|
|
188
240
|
throw new Error(`Invalid gridset buffer: ${error.message}`);
|
|
189
241
|
}
|
|
190
|
-
const entries = (0, password_1.getZipEntriesWithPassword)(zip, password);
|
|
191
242
|
let found = false;
|
|
192
243
|
// Find and update the grid
|
|
193
244
|
for (const entry of entries) {
|
|
@@ -196,7 +247,7 @@ async function updateWordlist(gridsetBuffer, gridName, wordlist, password = (0,
|
|
|
196
247
|
const currentGridName = match ? match[1] : null;
|
|
197
248
|
if (currentGridName === gridName) {
|
|
198
249
|
try {
|
|
199
|
-
const xmlContent = (0,
|
|
250
|
+
const xmlContent = (0, io_2.decodeText)(await entry.getData());
|
|
200
251
|
const data = parser.parse(xmlContent);
|
|
201
252
|
const grid = data.Grid || data.grid;
|
|
202
253
|
if (!grid) {
|
|
@@ -222,7 +273,9 @@ async function updateWordlist(gridsetBuffer, gridName, wordlist, password = (0,
|
|
|
222
273
|
};
|
|
223
274
|
// Rebuild the XML
|
|
224
275
|
const updatedXml = builder.build(data);
|
|
225
|
-
|
|
276
|
+
if (updateEntry) {
|
|
277
|
+
updateEntry(entry.entryName, updatedXml);
|
|
278
|
+
}
|
|
226
279
|
found = true;
|
|
227
280
|
}
|
|
228
281
|
catch (error) {
|
|
@@ -235,5 +288,8 @@ async function updateWordlist(gridsetBuffer, gridName, wordlist, password = (0,
|
|
|
235
288
|
if (!found) {
|
|
236
289
|
throw new Error(`Grid "${gridName}" not found in gridset`);
|
|
237
290
|
}
|
|
238
|
-
|
|
291
|
+
if (!saveZip) {
|
|
292
|
+
throw new Error('Failed to serialize updated gridset.');
|
|
293
|
+
}
|
|
294
|
+
return await saveZip();
|
|
239
295
|
}
|
|
@@ -40,31 +40,7 @@ const resolver_2 = require("./gridset/resolver");
|
|
|
40
40
|
const idGenerator_1 = require("../utilities/analytics/utils/idGenerator");
|
|
41
41
|
const symbolAlignment_1 = require("./gridset/symbolAlignment");
|
|
42
42
|
const io_1 = require("../utils/io");
|
|
43
|
-
|
|
44
|
-
async function getJSZip() {
|
|
45
|
-
if (!JSZipModule) {
|
|
46
|
-
try {
|
|
47
|
-
// Try ES module import first (browser/Vite)
|
|
48
|
-
const module = await Promise.resolve().then(() => __importStar(require('jszip')));
|
|
49
|
-
JSZipModule = module.default || module;
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
// Fall back to CommonJS require (Node.js)
|
|
53
|
-
try {
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
55
|
-
const module = require('jszip');
|
|
56
|
-
JSZipModule = module.default || module;
|
|
57
|
-
}
|
|
58
|
-
catch (err2) {
|
|
59
|
-
throw new Error('Zip handling requires JSZip in this environment.');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (!JSZipModule) {
|
|
64
|
-
throw new Error('Zip handling requires JSZip in this environment.');
|
|
65
|
-
}
|
|
66
|
-
return JSZipModule;
|
|
67
|
-
}
|
|
43
|
+
const zip_1 = require("../utils/zip");
|
|
68
44
|
class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
69
45
|
constructor(options) {
|
|
70
46
|
super(options);
|
|
@@ -437,17 +413,15 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
437
413
|
}
|
|
438
414
|
async loadIntoTree(filePathOrBuffer) {
|
|
439
415
|
const tree = new treeStructure_1.AACTree();
|
|
440
|
-
let
|
|
416
|
+
let zipResult;
|
|
441
417
|
try {
|
|
442
|
-
|
|
443
|
-
const zipInput = (0, io_1.readBinaryFromInput)(filePathOrBuffer);
|
|
444
|
-
zip = await JSZip.loadAsync(zipInput);
|
|
418
|
+
zipResult = await (0, zip_1.openZipFromInput)((0, io_1.readBinaryFromInput)(filePathOrBuffer));
|
|
445
419
|
}
|
|
446
420
|
catch (error) {
|
|
447
421
|
throw new Error(`Invalid ZIP file format: ${error.message}`);
|
|
448
422
|
}
|
|
449
423
|
const password = this.getGridsetPassword(filePathOrBuffer);
|
|
450
|
-
const entries = (0, password_1.
|
|
424
|
+
const entries = (0, password_1.getZipEntriesFromAdapter)(zipResult.zip, password);
|
|
451
425
|
const parser = new fast_xml_parser_1.XMLParser({ ignoreAttributes: false });
|
|
452
426
|
const isEncryptedArchive = typeof filePathOrBuffer === 'string' && filePathOrBuffer.toLowerCase().endsWith('.gridsetx');
|
|
453
427
|
const encryptedContentPassword = this.getGridsetPassword(filePathOrBuffer);
|
|
@@ -458,14 +432,11 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
458
432
|
passwordProtected: !!password,
|
|
459
433
|
};
|
|
460
434
|
const readEntryBuffer = async (entry) => {
|
|
461
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-argument
|
|
462
435
|
const raw = await entry.getData();
|
|
463
436
|
if (!isEncryptedArchive) {
|
|
464
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
465
437
|
return raw;
|
|
466
438
|
}
|
|
467
|
-
|
|
468
|
-
return (0, crypto_1.decryptGridsetEntry)(raw, encryptedContentPassword);
|
|
439
|
+
return (0, crypto_1.decryptGridsetEntry)(Buffer.from(raw), encryptedContentPassword);
|
|
469
440
|
};
|
|
470
441
|
// Parse FileMap.xml if present to index dynamic files per grid
|
|
471
442
|
const fileMapIndex = new Map();
|
|
@@ -785,7 +756,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
785
756
|
const gridEntryPath = entry.entryName.replace(/\\/g, '/');
|
|
786
757
|
const baseDir = gridEntryPath.replace(/\/grid\.xml$/, '/');
|
|
787
758
|
const dynamicFiles = fileMapIndex.get(gridEntryPath) || [];
|
|
788
|
-
const resolvedImageEntry = (0, resolver_1.resolveGrid3CellImage)(
|
|
759
|
+
const resolvedImageEntry = (0, resolver_1.resolveGrid3CellImage)(null, {
|
|
789
760
|
baseDir,
|
|
790
761
|
imageName: declaredImageName,
|
|
791
762
|
x: cellX + 1,
|
|
@@ -1636,11 +1607,36 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1636
1607
|
return (0, io_1.readBinaryFromInput)(outputPath);
|
|
1637
1608
|
}
|
|
1638
1609
|
async saveFromTree(tree, outputPath) {
|
|
1639
|
-
const
|
|
1640
|
-
|
|
1610
|
+
const useNodeZip = (0, io_1.isNodeRuntime)();
|
|
1611
|
+
let addText;
|
|
1612
|
+
let addBinary;
|
|
1613
|
+
let finalizeZip;
|
|
1614
|
+
if (useNodeZip) {
|
|
1615
|
+
const AdmZip = (0, io_1.getNodeRequire)()('adm-zip');
|
|
1616
|
+
const zip = new AdmZip();
|
|
1617
|
+
addText = (entryPath, content) => {
|
|
1618
|
+
zip.addFile(entryPath, Buffer.from(content, 'utf8'));
|
|
1619
|
+
};
|
|
1620
|
+
addBinary = (entryPath, content) => {
|
|
1621
|
+
zip.addFile(entryPath, Buffer.from(content));
|
|
1622
|
+
};
|
|
1623
|
+
finalizeZip = () => Promise.resolve(zip.toBuffer());
|
|
1624
|
+
}
|
|
1625
|
+
else {
|
|
1626
|
+
const module = await Promise.resolve().then(() => __importStar(require('jszip')));
|
|
1627
|
+
const JSZip = module.default || module;
|
|
1628
|
+
const zip = new JSZip();
|
|
1629
|
+
addText = (entryPath, content) => {
|
|
1630
|
+
zip.file(entryPath, content, { binary: false });
|
|
1631
|
+
};
|
|
1632
|
+
addBinary = (entryPath, content) => {
|
|
1633
|
+
zip.file(entryPath, content);
|
|
1634
|
+
};
|
|
1635
|
+
finalizeZip = async () => zip.generateAsync({ type: 'uint8array' });
|
|
1636
|
+
}
|
|
1641
1637
|
if (Object.keys(tree.pages).length === 0) {
|
|
1642
1638
|
// Create empty zip for empty tree
|
|
1643
|
-
const zipBuffer = await
|
|
1639
|
+
const zipBuffer = await finalizeZip();
|
|
1644
1640
|
(0, io_1.writeBinaryToPath)(outputPath, zipBuffer);
|
|
1645
1641
|
return;
|
|
1646
1642
|
}
|
|
@@ -1713,7 +1709,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1713
1709
|
suppressEmptyNode: true,
|
|
1714
1710
|
});
|
|
1715
1711
|
const settingsXmlContent = settingsBuilder.build(settingsData);
|
|
1716
|
-
|
|
1712
|
+
addText('Settings0/settings.xml', settingsXmlContent);
|
|
1717
1713
|
// Create Settings0/Styles/style.xml if there are styles
|
|
1718
1714
|
if (uniqueStyles.size > 0) {
|
|
1719
1715
|
const stylesArray = Array.from(uniqueStyles.values()).map(({ id, style }) => {
|
|
@@ -1746,7 +1742,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1746
1742
|
indentBy: ' ',
|
|
1747
1743
|
});
|
|
1748
1744
|
const styleXmlContent = styleBuilder.build(styleData);
|
|
1749
|
-
|
|
1745
|
+
addText('Settings0/Styles/styles.xml', styleXmlContent);
|
|
1750
1746
|
}
|
|
1751
1747
|
// Collect grid file paths for FileMap.xml
|
|
1752
1748
|
const gridFilePaths = [];
|
|
@@ -1887,14 +1883,14 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1887
1883
|
// Add to zip in Grids folder with proper Grid3 naming
|
|
1888
1884
|
const gridPath = `Grids/${page.name || page.id}/grid.xml`;
|
|
1889
1885
|
gridFilePaths.push(gridPath);
|
|
1890
|
-
|
|
1886
|
+
addText(gridPath, xmlContent);
|
|
1891
1887
|
});
|
|
1892
1888
|
// Write image files to ZIP
|
|
1893
1889
|
buttonImages.forEach((imgData) => {
|
|
1894
1890
|
if (imgData.imageData && imgData.imageData.length > 0) {
|
|
1895
1891
|
// Create image path in the grid's directory
|
|
1896
1892
|
const imagePath = `Grids/${imgData.pageName}/${imgData.x}-${imgData.y}-0-text-0.${imgData.ext}`;
|
|
1897
|
-
|
|
1893
|
+
addBinary(imagePath, imgData.imageData);
|
|
1898
1894
|
}
|
|
1899
1895
|
});
|
|
1900
1896
|
// Create FileMap.xml to map all grid files with their dynamic image files
|
|
@@ -1933,9 +1929,9 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
|
|
|
1933
1929
|
indentBy: ' ',
|
|
1934
1930
|
});
|
|
1935
1931
|
const fileMapXmlContent = fileMapBuilder.build(fileMapData);
|
|
1936
|
-
|
|
1932
|
+
addText('FileMap.xml', fileMapXmlContent);
|
|
1937
1933
|
// Write the zip file
|
|
1938
|
-
const zipBuffer = await
|
|
1934
|
+
const zipBuffer = await finalizeZip();
|
|
1939
1935
|
(0, io_1.writeBinaryToPath)(outputPath, zipBuffer);
|
|
1940
1936
|
}
|
|
1941
1937
|
// Helper method to calculate column definitions based on page layout
|