@willwade/aac-processors 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,9 @@
1
- import path from 'path';
1
+ function getExtension(source) {
2
+ const index = source.lastIndexOf('.');
3
+ if (index === -1)
4
+ return '';
5
+ return source.slice(index);
6
+ }
2
7
  /**
3
8
  * Resolve the password to use for Grid3 archives.
4
9
  * Preference order:
@@ -8,17 +13,18 @@ import path from 'path';
8
13
  export function resolveGridsetPassword(options, source) {
9
14
  if (options?.gridsetPassword)
10
15
  return options.gridsetPassword;
11
- if (process.env.GRIDSET_PASSWORD)
12
- return process.env.GRIDSET_PASSWORD;
16
+ const envPassword = typeof process !== 'undefined' ? process.env?.GRIDSET_PASSWORD : undefined;
17
+ if (envPassword)
18
+ return envPassword;
13
19
  if (typeof source === 'string') {
14
- const ext = path.extname(source).toLowerCase();
20
+ const ext = getExtension(source).toLowerCase();
15
21
  if (ext === '.gridsetx')
16
- return process.env.GRIDSET_PASSWORD;
22
+ return envPassword;
17
23
  }
18
24
  return undefined;
19
25
  }
20
26
  export function resolveGridsetPasswordFromEnv() {
21
- return process.env.GRIDSET_PASSWORD;
27
+ return typeof process !== 'undefined' ? process.env?.GRIDSET_PASSWORD : undefined;
22
28
  }
23
29
  export function getZipEntriesWithPassword(zip, password) {
24
30
  const entries = [];
@@ -12,9 +12,7 @@
12
12
  *
13
13
  * This module provides symbol resolution and metadata extraction.
14
14
  */
15
- import * as fs from 'fs';
16
- import * as path from 'path';
17
- import AdmZip from 'adm-zip';
15
+ import { getFs, getPath } from '../../utils/io';
18
16
  /**
19
17
  * Default Grid 3 installation paths by platform
20
18
  */
@@ -57,6 +55,37 @@ export const SYMBOL_LIBRARIES = {
57
55
  * Default locale to use
58
56
  */
59
57
  export const DEFAULT_LOCALE = 'en-GB';
58
+ function getNodeFs() {
59
+ try {
60
+ return getFs();
61
+ }
62
+ catch {
63
+ throw new Error('Symbol library access is not available in this environment.');
64
+ }
65
+ }
66
+ function getNodePath() {
67
+ try {
68
+ return getPath();
69
+ }
70
+ catch {
71
+ throw new Error('Path utilities are not available in this environment.');
72
+ }
73
+ }
74
+ let cachedAdmZip = null;
75
+ function getAdmZip() {
76
+ if (cachedAdmZip)
77
+ return cachedAdmZip;
78
+ try {
79
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
80
+ const module = require('adm-zip');
81
+ const resolved = module.default || module;
82
+ cachedAdmZip = resolved;
83
+ return resolved;
84
+ }
85
+ catch {
86
+ throw new Error('Symbol library access requires AdmZip in this environment.');
87
+ }
88
+ }
60
89
  /**
61
90
  * Parse a symbol reference string
62
91
  * @param reference - Symbol reference like "[widgit]/food/apple.png"
@@ -95,24 +124,30 @@ export function isSymbolReference(reference) {
95
124
  * @returns Default Grid 3 path or empty string if not found
96
125
  */
97
126
  export function getDefaultGrid3Path() {
98
- const platform = process.platform;
127
+ const platform = (typeof process !== 'undefined' && process.platform ? process.platform : 'unknown');
99
128
  const defaultPath = DEFAULT_GRID3_PATHS[platform] || '';
100
- if (defaultPath && fs.existsSync(defaultPath)) {
101
- return defaultPath;
102
- }
103
- // Try to find Grid 3 in common locations
104
- const commonPaths = [
105
- 'C:\\Program Files (x86)\\Smartbox\\Grid 3',
106
- 'C:\\Program Files\\Smartbox\\Grid 3',
107
- 'C:\\Program Files\\Smartbox\\Grid 3',
108
- '/Applications/Grid 3.app',
109
- '/opt/smartbox/grid3',
110
- ];
111
- for (const testPath of commonPaths) {
112
- if (fs.existsSync(testPath)) {
113
- return testPath;
129
+ try {
130
+ const fs = getNodeFs();
131
+ if (defaultPath && fs.existsSync(defaultPath)) {
132
+ return defaultPath;
133
+ }
134
+ // Try to find Grid 3 in common locations
135
+ const commonPaths = [
136
+ 'C:\\Program Files (x86)\\Smartbox\\Grid 3',
137
+ 'C:\\Program Files\\Smartbox\\Grid 3',
138
+ 'C:\\Program Files\\Smartbox\\Grid 3',
139
+ '/Applications/Grid 3.app',
140
+ '/opt/smartbox/grid3',
141
+ ];
142
+ for (const testPath of commonPaths) {
143
+ if (fs.existsSync(testPath)) {
144
+ return testPath;
145
+ }
114
146
  }
115
147
  }
148
+ catch {
149
+ return '';
150
+ }
116
151
  return '';
117
152
  }
118
153
  /**
@@ -122,6 +157,7 @@ export function getDefaultGrid3Path() {
122
157
  * @returns Path to Symbol Libraries directory (e.g., "C:\...\Grid 3\Resources\Symbols")
123
158
  */
124
159
  export function getSymbolLibrariesDir(grid3Path) {
160
+ const path = getNodePath();
125
161
  return path.join(grid3Path, SYMBOLS_SUBDIR);
126
162
  }
127
163
  /**
@@ -132,6 +168,7 @@ export function getSymbolLibrariesDir(grid3Path) {
132
168
  * @returns Path to symbol search indexes directory (e.g., "C:\...\Grid 3\Locale\en-GB\symbolsearch")
133
169
  */
134
170
  export function getSymbolSearchIndexesDir(grid3Path, locale = DEFAULT_LOCALE) {
171
+ const path = getNodePath();
135
172
  return path.join(grid3Path, SYMBOLSEARCH_SUBDIR, locale, 'symbolsearch');
136
173
  }
137
174
  /**
@@ -145,6 +182,7 @@ export function getAvailableSymbolLibraries(options = {}) {
145
182
  return [];
146
183
  }
147
184
  const symbolsDir = getSymbolLibrariesDir(grid3Path);
185
+ const fs = getNodeFs();
148
186
  if (!fs.existsSync(symbolsDir)) {
149
187
  return [];
150
188
  }
@@ -152,6 +190,7 @@ export function getAvailableSymbolLibraries(options = {}) {
152
190
  const files = fs.readdirSync(symbolsDir);
153
191
  for (const file of files) {
154
192
  if (file.endsWith('.symbols')) {
193
+ const path = getNodePath();
155
194
  const fullPath = path.join(symbolsDir, file);
156
195
  const stats = fs.statSync(fullPath);
157
196
  const libraryName = path.basename(file, '.symbols');
@@ -186,7 +225,9 @@ export function getSymbolLibraryInfo(libraryName, options = {}) {
186
225
  libraryName + '.symbols',
187
226
  ];
188
227
  for (const file of variations) {
228
+ const path = getNodePath();
189
229
  const fullPath = path.join(symbolsDir, file);
230
+ const fs = getNodeFs();
190
231
  if (fs.existsSync(fullPath)) {
191
232
  const stats = fs.statSync(fullPath);
192
233
  return {
@@ -233,6 +274,7 @@ export function resolveSymbolReference(reference, options = {}) {
233
274
  }
234
275
  try {
235
276
  // .symbols files are ZIP archives
277
+ const AdmZip = getAdmZip();
236
278
  const zip = new AdmZip(libraryInfo.pixFile);
237
279
  // The path in the symbol reference becomes the path within the symbols/ folder
238
280
  // e.g., [tawasl]/above bw.png becomes symbols/above bw.png
@@ -398,7 +440,8 @@ export function analyzeSymbolUsage(tree) {
398
440
  */
399
441
  export function symbolReferenceToFilename(reference, cellX, cellY) {
400
442
  const parsed = parseSymbolReference(reference);
401
- const ext = path.extname(parsed.path) || '.png';
443
+ const dotIndex = parsed.path.lastIndexOf('.');
444
+ const ext = dotIndex >= 0 ? parsed.path.slice(dotIndex) : '.png';
402
445
  // Grid 3 format: {x}-{y}-0-text-0.{ext}
403
446
  return `${cellX}-${cellY}-0-text-0${ext}`;
404
447
  }
@@ -507,7 +507,14 @@ class GridsetProcessor extends BaseProcessor {
507
507
  }
508
508
  // Debug: log all entry names
509
509
  console.log('[Gridset] Total zip entries:', entries.length);
510
- const gridEntries = entries.filter((e) => e.entryName.startsWith('Grids/') && e.entryName.endsWith('grid.xml'));
510
+ const normalizeEntryName = (entryName) => entryName.replace(/\\/g, '/').toLowerCase();
511
+ const isGridXmlEntry = (entryName) => {
512
+ const normalized = normalizeEntryName(entryName);
513
+ if (!normalized.endsWith('grid.xml'))
514
+ return false;
515
+ return normalized.startsWith('grids/') || normalized.includes('/grids/');
516
+ };
517
+ const gridEntries = entries.filter((e) => isGridXmlEntry(e.entryName));
511
518
  console.log('[Gridset] Grid XML entries found:', gridEntries.length);
512
519
  if (gridEntries.length > 0) {
513
520
  console.log('[Gridset] First few grid entries:', gridEntries.slice(0, 3).map((e) => e.entryName));
@@ -516,7 +523,7 @@ class GridsetProcessor extends BaseProcessor {
516
523
  const gridNameToIdMap = new Map();
517
524
  const gridIdToNameMap = new Map();
518
525
  for (const entry of entries) {
519
- if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
526
+ if (isGridXmlEntry(entry.entryName)) {
520
527
  try {
521
528
  const xmlContent = decodeText(await readEntryBuffer(entry));
522
529
  const data = parser.parse(xmlContent);
@@ -549,7 +556,7 @@ class GridsetProcessor extends BaseProcessor {
549
556
  // Second pass: process each grid file in the gridset
550
557
  for (const entry of entries) {
551
558
  // Only process files named grid.xml under Grids/ (any subdir)
552
- if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
559
+ if (isGridXmlEntry(entry.entryName)) {
553
560
  let xmlContent;
554
561
  try {
555
562
  const buffer = await readEntryBuffer(entry);
@@ -341,7 +341,7 @@ class ObfProcessor extends BaseProcessor {
341
341
  return null;
342
342
  }
343
343
  // If input is a string path and ends with .obf, treat as JSON
344
- if (typeof filePathOrBuffer === 'string' && filePathOrBuffer.endsWith('.obf')) {
344
+ if (typeof filePathOrBuffer === 'string' && filePathOrBuffer.toLowerCase().endsWith('.obf')) {
345
345
  try {
346
346
  const content = readTextFromInput(filePathOrBuffer);
347
347
  const boardData = tryParseObfJson(content);
@@ -393,8 +393,10 @@ class ObfProcessor extends BaseProcessor {
393
393
  }
394
394
  // Otherwise, try as ZIP (.obz). Detect likely zip signature first; throw if neither JSON nor ZIP
395
395
  function isLikelyZip(input) {
396
- if (typeof input === 'string')
397
- return input.endsWith('.zip') || input.endsWith('.obz');
396
+ if (typeof input === 'string') {
397
+ const lowered = input.toLowerCase();
398
+ return lowered.endsWith('.zip') || lowered.endsWith('.obz');
399
+ }
398
400
  const bytes = readBinaryFromInput(input);
399
401
  return bytes.length >= 2 && bytes[0] === 0x50 && bytes[1] === 0x4b;
400
402
  }
@@ -420,7 +422,7 @@ class ObfProcessor extends BaseProcessor {
420
422
  zip.forEach((relativePath, file) => {
421
423
  if (file.dir)
422
424
  return;
423
- if (relativePath.endsWith('.obf')) {
425
+ if (relativePath.toLowerCase().endsWith('.obf')) {
424
426
  obfEntries.push({ name: relativePath, file });
425
427
  }
426
428
  });
@@ -1,11 +1,10 @@
1
1
  /* eslint-disable @typescript-eslint/require-await */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
3
  /* eslint-disable @typescript-eslint/no-unsafe-return */
4
- import * as fs from 'fs';
5
- import * as path from 'path';
6
4
  import * as xml2js from 'xml2js';
7
5
  import JSZip from 'jszip';
8
6
  import { BaseValidator } from './baseValidator';
7
+ import { getFs, getPath } from '../utils/io';
9
8
  /**
10
9
  * Validator for Grid3/Smartbox Gridset files (.gridset, .gridsetx)
11
10
  */
@@ -18,6 +17,8 @@ export class GridsetValidator extends BaseValidator {
18
17
  */
19
18
  static async validateFile(filePath) {
20
19
  const validator = new GridsetValidator();
20
+ const fs = getFs();
21
+ const path = getPath();
21
22
  const content = fs.readFileSync(filePath);
22
23
  const stats = fs.statSync(filePath);
23
24
  return validator.validate(content, path.basename(filePath), stats.size);
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.resolveGridsetPassword = resolveGridsetPassword;
7
4
  exports.resolveGridsetPasswordFromEnv = resolveGridsetPasswordFromEnv;
8
5
  exports.getZipEntriesWithPassword = getZipEntriesWithPassword;
9
- const path_1 = __importDefault(require("path"));
6
+ function getExtension(source) {
7
+ const index = source.lastIndexOf('.');
8
+ if (index === -1)
9
+ return '';
10
+ return source.slice(index);
11
+ }
10
12
  /**
11
13
  * Resolve the password to use for Grid3 archives.
12
14
  * Preference order:
@@ -16,17 +18,18 @@ const path_1 = __importDefault(require("path"));
16
18
  function resolveGridsetPassword(options, source) {
17
19
  if (options?.gridsetPassword)
18
20
  return options.gridsetPassword;
19
- if (process.env.GRIDSET_PASSWORD)
20
- return process.env.GRIDSET_PASSWORD;
21
+ const envPassword = typeof process !== 'undefined' ? process.env?.GRIDSET_PASSWORD : undefined;
22
+ if (envPassword)
23
+ return envPassword;
21
24
  if (typeof source === 'string') {
22
- const ext = path_1.default.extname(source).toLowerCase();
25
+ const ext = getExtension(source).toLowerCase();
23
26
  if (ext === '.gridsetx')
24
- return process.env.GRIDSET_PASSWORD;
27
+ return envPassword;
25
28
  }
26
29
  return undefined;
27
30
  }
28
31
  function resolveGridsetPasswordFromEnv() {
29
- return process.env.GRIDSET_PASSWORD;
32
+ return typeof process !== 'undefined' ? process.env?.GRIDSET_PASSWORD : undefined;
30
33
  }
31
34
  function getZipEntriesWithPassword(zip, password) {
32
35
  const entries = [];
@@ -13,32 +13,6 @@
13
13
  *
14
14
  * This module provides symbol resolution and metadata extraction.
15
15
  */
16
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
- if (k2 === undefined) k2 = k;
18
- var desc = Object.getOwnPropertyDescriptor(m, k);
19
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
- desc = { enumerable: true, get: function() { return m[k]; } };
21
- }
22
- Object.defineProperty(o, k2, desc);
23
- }) : (function(o, m, k, k2) {
24
- if (k2 === undefined) k2 = k;
25
- o[k2] = m[k];
26
- }));
27
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
- Object.defineProperty(o, "default", { enumerable: true, value: v });
29
- }) : function(o, v) {
30
- o["default"] = v;
31
- });
32
- var __importStar = (this && this.__importStar) || function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- var __importDefault = (this && this.__importDefault) || function (mod) {
40
- return (mod && mod.__esModule) ? mod : { "default": mod };
41
- };
42
16
  Object.defineProperty(exports, "__esModule", { value: true });
43
17
  exports.DEFAULT_LOCALE = exports.SYMBOL_LIBRARIES = void 0;
44
18
  exports.parseSymbolReference = parseSymbolReference;
@@ -59,9 +33,7 @@ exports.analyzeSymbolUsage = analyzeSymbolUsage;
59
33
  exports.symbolReferenceToFilename = symbolReferenceToFilename;
60
34
  exports.getSymbolsDir = getSymbolsDir;
61
35
  exports.getSymbolSearchDir = getSymbolSearchDir;
62
- const fs = __importStar(require("fs"));
63
- const path = __importStar(require("path"));
64
- const adm_zip_1 = __importDefault(require("adm-zip"));
36
+ const io_1 = require("../../utils/io");
65
37
  /**
66
38
  * Default Grid 3 installation paths by platform
67
39
  */
@@ -104,6 +76,37 @@ exports.SYMBOL_LIBRARIES = {
104
76
  * Default locale to use
105
77
  */
106
78
  exports.DEFAULT_LOCALE = 'en-GB';
79
+ function getNodeFs() {
80
+ try {
81
+ return (0, io_1.getFs)();
82
+ }
83
+ catch {
84
+ throw new Error('Symbol library access is not available in this environment.');
85
+ }
86
+ }
87
+ function getNodePath() {
88
+ try {
89
+ return (0, io_1.getPath)();
90
+ }
91
+ catch {
92
+ throw new Error('Path utilities are not available in this environment.');
93
+ }
94
+ }
95
+ let cachedAdmZip = null;
96
+ function getAdmZip() {
97
+ if (cachedAdmZip)
98
+ return cachedAdmZip;
99
+ try {
100
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
101
+ const module = require('adm-zip');
102
+ const resolved = module.default || module;
103
+ cachedAdmZip = resolved;
104
+ return resolved;
105
+ }
106
+ catch {
107
+ throw new Error('Symbol library access requires AdmZip in this environment.');
108
+ }
109
+ }
107
110
  /**
108
111
  * Parse a symbol reference string
109
112
  * @param reference - Symbol reference like "[widgit]/food/apple.png"
@@ -142,23 +145,29 @@ function isSymbolReference(reference) {
142
145
  * @returns Default Grid 3 path or empty string if not found
143
146
  */
144
147
  function getDefaultGrid3Path() {
145
- const platform = process.platform;
148
+ const platform = (typeof process !== 'undefined' && process.platform ? process.platform : 'unknown');
146
149
  const defaultPath = DEFAULT_GRID3_PATHS[platform] || '';
147
- if (defaultPath && fs.existsSync(defaultPath)) {
148
- return defaultPath;
149
- }
150
- // Try to find Grid 3 in common locations
151
- const commonPaths = [
152
- 'C:\\Program Files (x86)\\Smartbox\\Grid 3',
153
- 'C:\\Program Files\\Smartbox\\Grid 3',
154
- 'C:\\Program Files\\Smartbox\\Grid 3',
155
- '/Applications/Grid 3.app',
156
- '/opt/smartbox/grid3',
157
- ];
158
- for (const testPath of commonPaths) {
159
- if (fs.existsSync(testPath)) {
160
- return testPath;
150
+ try {
151
+ const fs = getNodeFs();
152
+ if (defaultPath && fs.existsSync(defaultPath)) {
153
+ return defaultPath;
161
154
  }
155
+ // Try to find Grid 3 in common locations
156
+ const commonPaths = [
157
+ 'C:\\Program Files (x86)\\Smartbox\\Grid 3',
158
+ 'C:\\Program Files\\Smartbox\\Grid 3',
159
+ 'C:\\Program Files\\Smartbox\\Grid 3',
160
+ '/Applications/Grid 3.app',
161
+ '/opt/smartbox/grid3',
162
+ ];
163
+ for (const testPath of commonPaths) {
164
+ if (fs.existsSync(testPath)) {
165
+ return testPath;
166
+ }
167
+ }
168
+ }
169
+ catch {
170
+ return '';
162
171
  }
163
172
  return '';
164
173
  }
@@ -169,6 +178,7 @@ function getDefaultGrid3Path() {
169
178
  * @returns Path to Symbol Libraries directory (e.g., "C:\...\Grid 3\Resources\Symbols")
170
179
  */
171
180
  function getSymbolLibrariesDir(grid3Path) {
181
+ const path = getNodePath();
172
182
  return path.join(grid3Path, SYMBOLS_SUBDIR);
173
183
  }
174
184
  /**
@@ -179,6 +189,7 @@ function getSymbolLibrariesDir(grid3Path) {
179
189
  * @returns Path to symbol search indexes directory (e.g., "C:\...\Grid 3\Locale\en-GB\symbolsearch")
180
190
  */
181
191
  function getSymbolSearchIndexesDir(grid3Path, locale = exports.DEFAULT_LOCALE) {
192
+ const path = getNodePath();
182
193
  return path.join(grid3Path, SYMBOLSEARCH_SUBDIR, locale, 'symbolsearch');
183
194
  }
184
195
  /**
@@ -192,6 +203,7 @@ function getAvailableSymbolLibraries(options = {}) {
192
203
  return [];
193
204
  }
194
205
  const symbolsDir = getSymbolLibrariesDir(grid3Path);
206
+ const fs = getNodeFs();
195
207
  if (!fs.existsSync(symbolsDir)) {
196
208
  return [];
197
209
  }
@@ -199,6 +211,7 @@ function getAvailableSymbolLibraries(options = {}) {
199
211
  const files = fs.readdirSync(symbolsDir);
200
212
  for (const file of files) {
201
213
  if (file.endsWith('.symbols')) {
214
+ const path = getNodePath();
202
215
  const fullPath = path.join(symbolsDir, file);
203
216
  const stats = fs.statSync(fullPath);
204
217
  const libraryName = path.basename(file, '.symbols');
@@ -233,7 +246,9 @@ function getSymbolLibraryInfo(libraryName, options = {}) {
233
246
  libraryName + '.symbols',
234
247
  ];
235
248
  for (const file of variations) {
249
+ const path = getNodePath();
236
250
  const fullPath = path.join(symbolsDir, file);
251
+ const fs = getNodeFs();
237
252
  if (fs.existsSync(fullPath)) {
238
253
  const stats = fs.statSync(fullPath);
239
254
  return {
@@ -280,7 +295,8 @@ function resolveSymbolReference(reference, options = {}) {
280
295
  }
281
296
  try {
282
297
  // .symbols files are ZIP archives
283
- const zip = new adm_zip_1.default(libraryInfo.pixFile);
298
+ const AdmZip = getAdmZip();
299
+ const zip = new AdmZip(libraryInfo.pixFile);
284
300
  // The path in the symbol reference becomes the path within the symbols/ folder
285
301
  // e.g., [tawasl]/above bw.png becomes symbols/above bw.png
286
302
  const symbolPath = `symbols/${parsed.path}`;
@@ -445,7 +461,8 @@ function analyzeSymbolUsage(tree) {
445
461
  */
446
462
  function symbolReferenceToFilename(reference, cellX, cellY) {
447
463
  const parsed = parseSymbolReference(reference);
448
- const ext = path.extname(parsed.path) || '.png';
464
+ const dotIndex = parsed.path.lastIndexOf('.');
465
+ const ext = dotIndex >= 0 ? parsed.path.slice(dotIndex) : '.png';
449
466
  // Grid 3 format: {x}-{y}-0-text-0.{ext}
450
467
  return `${cellX}-${cellY}-0-text-0${ext}`;
451
468
  }
@@ -533,7 +533,14 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
533
533
  }
534
534
  // Debug: log all entry names
535
535
  console.log('[Gridset] Total zip entries:', entries.length);
536
- const gridEntries = entries.filter((e) => e.entryName.startsWith('Grids/') && e.entryName.endsWith('grid.xml'));
536
+ const normalizeEntryName = (entryName) => entryName.replace(/\\/g, '/').toLowerCase();
537
+ const isGridXmlEntry = (entryName) => {
538
+ const normalized = normalizeEntryName(entryName);
539
+ if (!normalized.endsWith('grid.xml'))
540
+ return false;
541
+ return normalized.startsWith('grids/') || normalized.includes('/grids/');
542
+ };
543
+ const gridEntries = entries.filter((e) => isGridXmlEntry(e.entryName));
537
544
  console.log('[Gridset] Grid XML entries found:', gridEntries.length);
538
545
  if (gridEntries.length > 0) {
539
546
  console.log('[Gridset] First few grid entries:', gridEntries.slice(0, 3).map((e) => e.entryName));
@@ -542,7 +549,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
542
549
  const gridNameToIdMap = new Map();
543
550
  const gridIdToNameMap = new Map();
544
551
  for (const entry of entries) {
545
- if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
552
+ if (isGridXmlEntry(entry.entryName)) {
546
553
  try {
547
554
  const xmlContent = (0, io_1.decodeText)(await readEntryBuffer(entry));
548
555
  const data = parser.parse(xmlContent);
@@ -575,7 +582,7 @@ class GridsetProcessor extends baseProcessor_1.BaseProcessor {
575
582
  // Second pass: process each grid file in the gridset
576
583
  for (const entry of entries) {
577
584
  // Only process files named grid.xml under Grids/ (any subdir)
578
- if (entry.entryName.startsWith('Grids/') && entry.entryName.endsWith('grid.xml')) {
585
+ if (isGridXmlEntry(entry.entryName)) {
579
586
  let xmlContent;
580
587
  try {
581
588
  const buffer = await readEntryBuffer(entry);
@@ -367,7 +367,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
367
367
  return null;
368
368
  }
369
369
  // If input is a string path and ends with .obf, treat as JSON
370
- if (typeof filePathOrBuffer === 'string' && filePathOrBuffer.endsWith('.obf')) {
370
+ if (typeof filePathOrBuffer === 'string' && filePathOrBuffer.toLowerCase().endsWith('.obf')) {
371
371
  try {
372
372
  const content = (0, io_1.readTextFromInput)(filePathOrBuffer);
373
373
  const boardData = tryParseObfJson(content);
@@ -419,8 +419,10 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
419
419
  }
420
420
  // Otherwise, try as ZIP (.obz). Detect likely zip signature first; throw if neither JSON nor ZIP
421
421
  function isLikelyZip(input) {
422
- if (typeof input === 'string')
423
- return input.endsWith('.zip') || input.endsWith('.obz');
422
+ if (typeof input === 'string') {
423
+ const lowered = input.toLowerCase();
424
+ return lowered.endsWith('.zip') || lowered.endsWith('.obz');
425
+ }
424
426
  const bytes = (0, io_1.readBinaryFromInput)(input);
425
427
  return bytes.length >= 2 && bytes[0] === 0x50 && bytes[1] === 0x4b;
426
428
  }
@@ -446,7 +448,7 @@ class ObfProcessor extends baseProcessor_1.BaseProcessor {
446
448
  zip.forEach((relativePath, file) => {
447
449
  if (file.dir)
448
450
  return;
449
- if (relativePath.endsWith('.obf')) {
451
+ if (relativePath.toLowerCase().endsWith('.obf')) {
450
452
  obfEntries.push({ name: relativePath, file });
451
453
  }
452
454
  });
@@ -30,11 +30,10 @@ exports.GridsetValidator = void 0;
30
30
  /* eslint-disable @typescript-eslint/require-await */
31
31
  /* eslint-disable @typescript-eslint/no-unsafe-argument */
32
32
  /* eslint-disable @typescript-eslint/no-unsafe-return */
33
- const fs = __importStar(require("fs"));
34
- const path = __importStar(require("path"));
35
33
  const xml2js = __importStar(require("xml2js"));
36
34
  const jszip_1 = __importDefault(require("jszip"));
37
35
  const baseValidator_1 = require("./baseValidator");
36
+ const io_1 = require("../utils/io");
38
37
  /**
39
38
  * Validator for Grid3/Smartbox Gridset files (.gridset, .gridsetx)
40
39
  */
@@ -47,6 +46,8 @@ class GridsetValidator extends baseValidator_1.BaseValidator {
47
46
  */
48
47
  static async validateFile(filePath) {
49
48
  const validator = new GridsetValidator();
49
+ const fs = (0, io_1.getFs)();
50
+ const path = (0, io_1.getPath)();
50
51
  const content = fs.readFileSync(filePath);
51
52
  const stats = fs.statSync(filePath);
52
53
  return validator.validate(content, path.basename(filePath), stats.size);