@willwade/aac-processors 0.2.17 → 0.2.18
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/dist/browser/processors/snapProcessor.js +42 -4
- package/dist/browser/utilities/analytics/metrics/core.js +182 -33
- package/dist/browser/utilities/analytics/metrics/effort.js +1 -0
- package/dist/browser/utilities/analytics/morphology/engine.js +24 -2
- package/dist/browser/utilities/analytics/morphology/index.js +1 -0
- package/dist/browser/utilities/analytics/morphology/tdsnapLexiconParser.js +182 -0
- package/dist/core/treeStructure.d.ts +2 -2
- package/dist/index.node.d.ts +1 -0
- package/dist/index.node.js +4 -2
- package/dist/processors/snapProcessor.js +42 -4
- package/dist/types/aac.d.ts +1 -1
- package/dist/utilities/analytics/metrics/core.d.ts +33 -0
- package/dist/utilities/analytics/metrics/core.js +182 -33
- package/dist/utilities/analytics/metrics/effort.d.ts +1 -0
- package/dist/utilities/analytics/metrics/effort.js +1 -0
- package/dist/utilities/analytics/metrics/types.d.ts +26 -0
- package/dist/utilities/analytics/morphology/engine.d.ts +4 -0
- package/dist/utilities/analytics/morphology/engine.js +24 -2
- package/dist/utilities/analytics/morphology/index.d.ts +2 -0
- package/dist/utilities/analytics/morphology/index.js +3 -1
- package/dist/utilities/analytics/morphology/tdsnapLexiconParser.d.ts +28 -0
- package/dist/utilities/analytics/morphology/tdsnapLexiconParser.js +186 -0
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TDSnapLexiconParser = void 0;
|
|
4
|
+
class TDSnapLexiconParser {
|
|
5
|
+
parseDb(dbPath, locale) {
|
|
6
|
+
const detectedLocale = locale || this.inferLocale(dbPath);
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
8
|
+
const Database = require('better-sqlite3');
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
10
|
+
const db = new Database(dbPath, { readonly: true });
|
|
11
|
+
try {
|
|
12
|
+
return this.extractAll(db, detectedLocale);
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
db.close();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
inferLocale(dbPath) {
|
|
19
|
+
const match = dbPath.match(/lang_([a-z]{2}_[A-Z]{2})/i);
|
|
20
|
+
return match ? match[1] : 'unknown';
|
|
21
|
+
}
|
|
22
|
+
extractAll(db, locale) {
|
|
23
|
+
const words = new Map();
|
|
24
|
+
const subclassCache = new Map();
|
|
25
|
+
const getSubclass = (id) => {
|
|
26
|
+
let name = subclassCache.get(id);
|
|
27
|
+
if (name !== undefined)
|
|
28
|
+
return name;
|
|
29
|
+
const row = db.prepare('SELECT Name FROM PosSubclass WHERE Id = ?').get(id);
|
|
30
|
+
name = row?.Name;
|
|
31
|
+
if (name) {
|
|
32
|
+
subclassCache.set(id, name);
|
|
33
|
+
return name;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
};
|
|
37
|
+
const allWords = db
|
|
38
|
+
.prepare(`SELECT w.Id as wordId, w.Text as text,
|
|
39
|
+
i.Id as inflectionId, i.LexemeId as lexemeId, i.PosSubclassId as posSubclassId
|
|
40
|
+
FROM Word w
|
|
41
|
+
JOIN Spelling s ON s.WordId = w.Id
|
|
42
|
+
JOIN Inflection i ON i.Id = s.InflectionId
|
|
43
|
+
WHERE i.PosSubclassId != 0
|
|
44
|
+
ORDER BY w.Text`)
|
|
45
|
+
.all();
|
|
46
|
+
const lexemeForms = new Map();
|
|
47
|
+
for (const row of allWords) {
|
|
48
|
+
const tag = getSubclass(row.posSubclassId);
|
|
49
|
+
if (!tag)
|
|
50
|
+
continue;
|
|
51
|
+
let formsByTag = lexemeForms.get(row.lexemeId);
|
|
52
|
+
if (!formsByTag) {
|
|
53
|
+
formsByTag = new Map();
|
|
54
|
+
lexemeForms.set(row.lexemeId, formsByTag);
|
|
55
|
+
}
|
|
56
|
+
const existing = formsByTag.get(tag);
|
|
57
|
+
if (existing) {
|
|
58
|
+
if (!existing.includes(row.text))
|
|
59
|
+
existing.push(row.text);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
formsByTag.set(tag, [row.text]);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const wordToLexeme = new Map();
|
|
66
|
+
for (const row of allWords) {
|
|
67
|
+
if (!wordToLexeme.has(row.text.toLowerCase())) {
|
|
68
|
+
wordToLexeme.set(row.text.toLowerCase(), row.lexemeId);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const [text, lexemeId] of wordToLexeme) {
|
|
72
|
+
const formsByTag = lexemeForms.get(lexemeId);
|
|
73
|
+
if (!formsByTag || formsByTag.size === 0)
|
|
74
|
+
continue;
|
|
75
|
+
const forms = [];
|
|
76
|
+
for (const [tag, formTexts] of formsByTag) {
|
|
77
|
+
for (const formText of formTexts) {
|
|
78
|
+
if (formText.toLowerCase() !== text) {
|
|
79
|
+
forms.push({ tag, form: formText });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (forms.length > 0) {
|
|
84
|
+
words.set(text, { lexemeId, forms });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return { locale, words };
|
|
88
|
+
}
|
|
89
|
+
lookupWord(data, word) {
|
|
90
|
+
const entry = data.words.get(word.toLowerCase());
|
|
91
|
+
if (!entry)
|
|
92
|
+
return [];
|
|
93
|
+
return entry.forms.map((f) => f.form);
|
|
94
|
+
}
|
|
95
|
+
lookupWordByTag(data, word, tag) {
|
|
96
|
+
const entry = data.words.get(word.toLowerCase());
|
|
97
|
+
if (!entry)
|
|
98
|
+
return [];
|
|
99
|
+
return entry.forms.filter((f) => f.tag === tag).map((f) => f.form);
|
|
100
|
+
}
|
|
101
|
+
static parseContentTypeHandler(handler) {
|
|
102
|
+
if (!handler)
|
|
103
|
+
return null;
|
|
104
|
+
const colonIdx = handler.indexOf(':');
|
|
105
|
+
if (colonIdx === -1) {
|
|
106
|
+
const parts = handler.split(',');
|
|
107
|
+
return { category: parts[0], subtype: '', params: parts.slice(1) };
|
|
108
|
+
}
|
|
109
|
+
const category = handler.substring(0, colonIdx);
|
|
110
|
+
const rest = handler.substring(colonIdx + 1);
|
|
111
|
+
const commaIdx = rest.indexOf(',');
|
|
112
|
+
if (commaIdx === -1) {
|
|
113
|
+
return { category, subtype: rest, params: [] };
|
|
114
|
+
}
|
|
115
|
+
const subtype = rest.substring(0, commaIdx);
|
|
116
|
+
const paramsStr = rest.substring(commaIdx + 1);
|
|
117
|
+
const params = paramsStr.split(',').map((p) => p.trim());
|
|
118
|
+
return { category, subtype, params };
|
|
119
|
+
}
|
|
120
|
+
static tagToPos(tag) {
|
|
121
|
+
return TDSnapLexiconParser.TAG_TO_POS[tag] || 'Unknown';
|
|
122
|
+
}
|
|
123
|
+
static handlerToPos(handler) {
|
|
124
|
+
const parsed = TDSnapLexiconParser.parseContentTypeHandler(handler);
|
|
125
|
+
if (!parsed)
|
|
126
|
+
return 'Unknown';
|
|
127
|
+
if (parsed.category === 'RESET' || parsed.category === 'SPECIAL')
|
|
128
|
+
return 'Ignore';
|
|
129
|
+
const key = `${parsed.category}:${parsed.subtype}`;
|
|
130
|
+
const tag = TDSnapLexiconParser.HANDLER_TAG_MAP[key];
|
|
131
|
+
if (tag)
|
|
132
|
+
return TDSnapLexiconParser.TAG_TO_POS[tag] || 'Unknown';
|
|
133
|
+
return TDSnapLexiconParser.TAG_TO_POS[parsed.subtype] || 'Unknown';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.TDSnapLexiconParser = TDSnapLexiconParser;
|
|
137
|
+
TDSnapLexiconParser.TAG_TO_POS = {
|
|
138
|
+
V0: 'Verb',
|
|
139
|
+
VZ: 'Verb',
|
|
140
|
+
VG: 'Verb',
|
|
141
|
+
VD: 'Verb',
|
|
142
|
+
VN: 'Verb',
|
|
143
|
+
SNG: 'Noun',
|
|
144
|
+
PLU: 'Noun',
|
|
145
|
+
ADJ: 'Adjective',
|
|
146
|
+
ADJR: 'Adjective',
|
|
147
|
+
ADJT: 'Adjective',
|
|
148
|
+
ADV: 'Adjective',
|
|
149
|
+
SUB: 'Pronoun',
|
|
150
|
+
OBJ: 'Pronoun',
|
|
151
|
+
POS: 'Pronoun',
|
|
152
|
+
NPOS: 'Pronoun',
|
|
153
|
+
REF: 'Pronoun',
|
|
154
|
+
B0: 'Verb',
|
|
155
|
+
BZ: 'Verb',
|
|
156
|
+
BM: 'Verb',
|
|
157
|
+
BR: 'Verb',
|
|
158
|
+
BDZ: 'Verb',
|
|
159
|
+
BDR: 'Verb',
|
|
160
|
+
BG: 'Verb',
|
|
161
|
+
BN: 'Verb',
|
|
162
|
+
};
|
|
163
|
+
TDSnapLexiconParser.HANDLER_TAG_MAP = {
|
|
164
|
+
'NOUN:PLU': 'PLU',
|
|
165
|
+
'DESCRIBE:ADJR': 'ADJR',
|
|
166
|
+
'DESCRIBE:ADJT': 'ADJT',
|
|
167
|
+
'DESCRIBE:ADV': 'ADV',
|
|
168
|
+
'VERB:V0': 'V0',
|
|
169
|
+
'VERB:VZ': 'VZ',
|
|
170
|
+
'VERB:VG': 'VG',
|
|
171
|
+
'VERB:VD': 'VD',
|
|
172
|
+
'VERB:VN': 'VN',
|
|
173
|
+
'PRONOUN:SUB': 'SUB',
|
|
174
|
+
'PRONOUN:OBJ': 'OBJ',
|
|
175
|
+
'PRONOUN:POS': 'POS',
|
|
176
|
+
'PRONOUN:NPOS': 'NPOS',
|
|
177
|
+
'PRONOUN:REF': 'REF',
|
|
178
|
+
'BE:B0': 'B0',
|
|
179
|
+
'BE:BZ': 'BZ',
|
|
180
|
+
'BE:BM': 'BM',
|
|
181
|
+
'BE:BR': 'BR',
|
|
182
|
+
'BE:BDZ': 'BDZ',
|
|
183
|
+
'BE:BDR': 'BDR',
|
|
184
|
+
'BE:BG': 'BG',
|
|
185
|
+
'BE:BN': 'BN',
|
|
186
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@willwade/aac-processors",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.18",
|
|
4
4
|
"description": "A comprehensive TypeScript library for processing AAC (Augmentative and Alternative Communication) file formats with translation support",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"browser": "dist/browser/index.browser.js",
|