Skip to content

Commit 0aa0d1e

Browse files
committed
seperate metadata out and better management of metadata
1 parent bbe429b commit 0aa0d1e

18 files changed

Lines changed: 555 additions & 41 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
.DS_Store
2+
aac-metrics-node/
23
obla-improvements/
34
tmp/
45
# Logs

src/core/baseProcessor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export interface VocabPlacementMetadata {
8484

8585
export interface VocabLocation {
8686
table: string;
87-
id: number;
87+
id: string | number;
8888
column: string;
8989
casing: StringCasing;
9090
}
@@ -263,7 +263,7 @@ abstract class BaseProcessor {
263263
const key = page.name.trim().toLowerCase();
264264
const vocabLocation: VocabLocation = {
265265
table: 'pages',
266-
id: parseInt(page.id) || 0,
266+
id: page.id,
267267
column: 'NAME',
268268
casing: detectCasing(page.name),
269269
};
@@ -277,7 +277,7 @@ abstract class BaseProcessor {
277277
const key = button.label.trim().toLowerCase();
278278
const vocabLocation: VocabLocation = {
279279
table: 'buttons',
280-
id: parseInt(button.id) || 0,
280+
id: button.id,
281281
column: 'LABEL',
282282
casing: detectCasing(button.label),
283283
};
@@ -295,7 +295,7 @@ abstract class BaseProcessor {
295295
const key = button.message.trim().toLowerCase();
296296
const vocabLocation: VocabLocation = {
297297
table: 'buttons',
298-
id: parseInt(button.id) || 0,
298+
id: button.id,
299299
column: 'MESSAGE',
300300
casing: detectCasing(button.message),
301301
};

src/core/treeStructure.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ import {
22
AACButton as IAACButton,
33
AACPage as IAACPage,
44
AACTree as IAACTree,
5+
AACTreeMetadata,
6+
SnapMetadata,
7+
GridSetMetadata,
8+
AstericsGridMetadata,
9+
TouchChatMetadata,
510
AACStyle,
611
} from '../types/aac';
712

13+
export { AACTreeMetadata, SnapMetadata, GridSetMetadata, AstericsGridMetadata, TouchChatMetadata };
14+
815
// Semantic action categories for cross-platform compatibility
916
export enum AACSemanticCategory {
1017
COMMUNICATION = 'communication', // Speech, text output
@@ -437,23 +444,37 @@ export class AACPage implements IAACPage {
437444

438445
export class AACTree implements IAACTree {
439446
pages: { [key: string]: AACPage };
440-
private _rootId: string | null;
447+
metadata: AACTreeMetadata;
441448

442449
public get rootId(): string | null {
443-
return this._rootId;
450+
return this.metadata.defaultHomePageId || null;
444451
}
445452
public set rootId(id: string | null) {
446-
this._rootId = id;
453+
this.metadata.defaultHomePageId = id || undefined;
454+
}
455+
456+
public get toolbarId(): string | null {
457+
return this.metadata.toolbarId || null;
458+
}
459+
public set toolbarId(id: string | null) {
460+
this.metadata.toolbarId = id || undefined;
461+
}
462+
463+
public get dashboardId(): string | null {
464+
return this.metadata.dashboardId || null;
465+
}
466+
public set dashboardId(id: string | null) {
467+
this.metadata.dashboardId = id || undefined;
447468
}
448469

449470
constructor() {
450471
this.pages = {};
451-
this._rootId = null;
472+
this.metadata = {};
452473
}
453474

454475
addPage(page: AACPage): void {
455476
this.pages[page.id] = page;
456-
if (!this._rootId) this._rootId = page.id;
477+
if (!this.rootId) this.rootId = page.id;
457478
}
458479

459480
getPage(id: string): AACPage | undefined {

src/processors/applePanelsProcessor.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ class ApplePanelsProcessor extends BaseProcessor {
262262

263263
const data: ApplePanelsDocument = { panels: panelsData };
264264
const tree = new AACTree();
265+
tree.metadata.format = 'applepanels';
265266

266267
data.panels.forEach((panel) => {
267268
const page = new AACPage({
@@ -451,16 +452,18 @@ class ApplePanelsProcessor extends BaseProcessor {
451452

452453
// Create Info.plist (bundle mode only)
453454
const infoPlist = {
454-
ASCConfigurationDisplayName: 'AAC Processors Export',
455+
ASCConfigurationDisplayName: tree.metadata?.name || 'AAC Processors Export',
455456
ASCConfigurationIdentifier: `com.aacprocessors.${Date.now()}`,
456457
ASCConfigurationProductSupportType: 'VirtualKeyboard',
457-
ASCConfigurationVersion: '7.1',
458-
CFBundleDevelopmentRegion: 'en',
458+
ASCConfigurationVersion: tree.metadata?.version || '7.1',
459+
CFBundleDevelopmentRegion: tree.metadata?.locale || 'en',
459460
CFBundleIdentifier: 'com.aacprocessors.panel.export',
460-
CFBundleName: 'AAC Processors Panels',
461-
CFBundleShortVersionString: '1.0',
461+
CFBundleName: tree.metadata?.name || 'AAC Processors Panels',
462+
CFBundleShortVersionString: tree.metadata?.version || '1.0',
462463
CFBundleVersion: '1',
463-
NSHumanReadableCopyright: 'Generated by AAC Processors',
464+
NSHumanReadableCopyright:
465+
tree.metadata?.copyright ||
466+
`Generated by AAC Processors${tree.metadata?.author ? ` - Author: ${tree.metadata.author}` : ''}`,
464467
};
465468
const infoPlistContent = plist.build(infoPlist);
466469
fs.writeFileSync(path.join(contentsPath, 'Info.plist'), infoPlistContent);

src/processors/astericsGridProcessor.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
AACSemanticAction,
1313
AACSemanticCategory,
1414
AACSemanticIntent,
15+
AstericsGridMetadata,
1516
} from '../core/treeStructure';
1617
import fs from 'fs';
1718

@@ -932,6 +933,45 @@ class AstericsGridProcessor extends BaseProcessor {
932933
page.grid = gridLayout;
933934
});
934935

936+
// Set metadata for Asterics Grid files
937+
const astericsMetadata: AstericsGridMetadata = {
938+
format: 'asterics',
939+
hasGlobalGrid: false, // Can be extended in the future
940+
};
941+
942+
if (grdFile.grids && grdFile.grids.length > 0) {
943+
astericsMetadata.name = this.getLocalizedLabel(grdFile.grids[0].label);
944+
945+
// Extract all unique languages from all grids and elements
946+
const languages = new Set<string>();
947+
grdFile.grids.forEach((grid) => {
948+
if (grid.label) {
949+
Object.keys(grid.label).forEach((lang) => languages.add(lang));
950+
}
951+
grid.gridElements?.forEach((element) => {
952+
if (element.label) {
953+
Object.keys(element.label).forEach((lang) => languages.add(lang));
954+
}
955+
// Also check word forms for languages
956+
element.wordForms?.forEach((wf) => {
957+
if (wf.lang) languages.add(wf.lang);
958+
});
959+
});
960+
});
961+
962+
if (languages.size > 0) {
963+
astericsMetadata.languages = Array.from(languages).sort();
964+
// Set primary locale to English if available, otherwise the first language found
965+
astericsMetadata.locale = languages.has('en')
966+
? 'en'
967+
: languages.has('de')
968+
? 'de'
969+
: astericsMetadata.languages[0];
970+
}
971+
}
972+
973+
tree.metadata = astericsMetadata;
974+
935975
// Set the home page from metadata.homeGridId
936976
if (grdFile.metadata && grdFile.metadata.homeGridId) {
937977
tree.rootId = grdFile.metadata.homeGridId;
@@ -1523,6 +1563,8 @@ class AstericsGridProcessor extends BaseProcessor {
15231563
});
15241564
}
15251565

1566+
const locale = tree.metadata?.locale || 'en';
1567+
15261568
return {
15271569
id: button.id,
15281570
modelName: 'GridElement',
@@ -1531,7 +1573,7 @@ class AstericsGridProcessor extends BaseProcessor {
15311573
height: 1,
15321574
x: calculatedX,
15331575
y: calculatedY,
1534-
label: { en: button.label },
1576+
label: { [locale]: button.label },
15351577
wordForms: [],
15361578
image: {
15371579
data: null,
@@ -1558,7 +1600,7 @@ class AstericsGridProcessor extends BaseProcessor {
15581600
id: page.id,
15591601
modelName: 'GridData',
15601602
modelVersion: '{"major": 5, "minor": 0, "patch": 0}',
1561-
label: { en: page.name },
1603+
label: { [tree.metadata?.locale || 'en']: page.name },
15621604
rowCount: calculatedRows,
15631605
minColumnCount: calculatedCols,
15641606
gridElements: gridElements,

src/processors/dotProcessor.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class DotProcessor extends BaseProcessor {
141141

142142
const { nodes, edges } = this.parseDotFile(content);
143143
const tree = new AACTree();
144+
tree.metadata.format = 'dot';
144145

145146
// Create pages for each node and add a self button representing the node label
146147
for (const node of nodes) {
@@ -220,13 +221,17 @@ class DotProcessor extends BaseProcessor {
220221
}
221222

222223
saveFromTree(tree: AACTree, _outputPath: string): void {
223-
let dotContent = 'digraph AACBoard {\n';
224+
let dotContent = `digraph "${tree.metadata?.name || 'AACBoard'}" {\n`;
224225

225226
// Helper to escape DOT string
226227
const escapeDotString = (str: string): string => {
227228
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
228229
};
229230

231+
if (tree.metadata?.name) {
232+
dotContent += ` label="${escapeDotString(tree.metadata.name)}";\n`;
233+
}
234+
230235
// Add nodes
231236
for (const pageId in tree.pages) {
232237
const page = tree.pages[pageId];

src/processors/excelProcessor.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ export class ExcelProcessor extends BaseProcessor {
3535
*/
3636
loadIntoTree(_filePathOrBuffer: string | Buffer): AACTree {
3737
console.warn('ExcelProcessor.loadIntoTree is not implemented yet.');
38-
return new AACTree();
38+
const tree = new AACTree();
39+
tree.metadata.format = 'excel';
40+
return tree;
3941
}
4042

4143
/**
@@ -556,12 +558,15 @@ export class ExcelProcessor extends BaseProcessor {
556558
*/
557559
private async saveFromTreeAsync(tree: AACTree, outputPath: string): Promise<void> {
558560
const workbook = new ExcelJS.Workbook();
561+
const metadata = tree.metadata;
559562

560-
// Set workbook properties
561-
workbook.creator = 'AACProcessors';
563+
// Set workbook properties from tree metadata
564+
workbook.creator = metadata?.author || 'AACProcessors';
562565
workbook.lastModifiedBy = 'AACProcessors';
563566
workbook.created = new Date();
564567
workbook.modified = new Date();
568+
workbook.title = metadata?.name || '';
569+
workbook.subject = metadata?.description || '';
565570

566571
// If no pages, create a default empty worksheet
567572
if (Object.keys(tree.pages).length === 0) {

0 commit comments

Comments
 (0)