hybridtm 0.1.0

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 (87) hide show
  1. package/LICENSE +233 -0
  2. package/README.md +116 -0
  3. package/dist/batchimporter.d.ts +22 -0
  4. package/dist/batchimporter.js +203 -0
  5. package/dist/batchimporter.js.map +1 -0
  6. package/dist/constants.d.ts +15 -0
  7. package/dist/constants.js +16 -0
  8. package/dist/constants.js.map +1 -0
  9. package/dist/debug-progress.d.ts +12 -0
  10. package/dist/debug-progress.js +49 -0
  11. package/dist/debug-progress.js.map +1 -0
  12. package/dist/hybridtm.d.ts +66 -0
  13. package/dist/hybridtm.js +912 -0
  14. package/dist/hybridtm.js.map +1 -0
  15. package/dist/hybridtmFactory.d.ts +43 -0
  16. package/dist/hybridtmFactory.js +165 -0
  17. package/dist/hybridtmFactory.js.map +1 -0
  18. package/dist/importOptions.d.ts +21 -0
  19. package/dist/importOptions.js +24 -0
  20. package/dist/importOptions.js.map +1 -0
  21. package/dist/index.d.ts +25 -0
  22. package/dist/index.js +22 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/langEntry.d.ts +64 -0
  25. package/dist/langEntry.js +13 -0
  26. package/dist/langEntry.js.map +1 -0
  27. package/dist/match.d.ts +22 -0
  28. package/dist/match.js +38 -0
  29. package/dist/match.js.map +1 -0
  30. package/dist/matchQuality.d.ts +16 -0
  31. package/dist/matchQuality.js +83 -0
  32. package/dist/matchQuality.js.map +1 -0
  33. package/dist/ngramIndex.d.ts +31 -0
  34. package/dist/ngramIndex.js +132 -0
  35. package/dist/ngramIndex.js.map +1 -0
  36. package/dist/ngrams.d.ts +21 -0
  37. package/dist/ngrams.js +73 -0
  38. package/dist/ngrams.js.map +1 -0
  39. package/dist/pendingEntry.d.ts +24 -0
  40. package/dist/pendingEntry.js +13 -0
  41. package/dist/pendingEntry.js.map +1 -0
  42. package/dist/progressProvider.d.ts +17 -0
  43. package/dist/progressProvider.js +14 -0
  44. package/dist/progressProvider.js.map +1 -0
  45. package/dist/searchFilters.d.ts +24 -0
  46. package/dist/searchFilters.js +13 -0
  47. package/dist/searchFilters.js.map +1 -0
  48. package/dist/simplexlifftest.d.ts +1 -0
  49. package/dist/simplexlifftest.js +23 -0
  50. package/dist/simplexlifftest.js.map +1 -0
  51. package/dist/test-import.d.ts +12 -0
  52. package/dist/test-import.js +101 -0
  53. package/dist/test-import.js.map +1 -0
  54. package/dist/test-progress-fix.d.ts +1 -0
  55. package/dist/test-progress-fix.js +32 -0
  56. package/dist/test-progress-fix.js.map +1 -0
  57. package/dist/test-progress.d.ts +12 -0
  58. package/dist/test-progress.js +32 -0
  59. package/dist/test-progress.js.map +1 -0
  60. package/dist/tests/vectorSimilarityComparison.d.ts +12 -0
  61. package/dist/tests/vectorSimilarityComparison.js +153 -0
  62. package/dist/tests/vectorSimilarityComparison.js.map +1 -0
  63. package/dist/tmxhandler.d.ts +61 -0
  64. package/dist/tmxhandler.js +347 -0
  65. package/dist/tmxhandler.js.map +1 -0
  66. package/dist/tmxreader.d.ts +25 -0
  67. package/dist/tmxreader.js +51 -0
  68. package/dist/tmxreader.js.map +1 -0
  69. package/dist/tmxtest.d.ts +16 -0
  70. package/dist/tmxtest.js +316 -0
  71. package/dist/tmxtest.js.map +1 -0
  72. package/dist/utils.d.ts +17 -0
  73. package/dist/utils.js +49 -0
  74. package/dist/utils.js.map +1 -0
  75. package/dist/vectorSimilarityTester.d.ts +56 -0
  76. package/dist/vectorSimilarityTester.js +164 -0
  77. package/dist/vectorSimilarityTester.js.map +1 -0
  78. package/dist/xliffhandler.d.ts +67 -0
  79. package/dist/xliffhandler.js +522 -0
  80. package/dist/xliffhandler.js.map +1 -0
  81. package/dist/xliffreader.d.ts +25 -0
  82. package/dist/xliffreader.js +50 -0
  83. package/dist/xliffreader.js.map +1 -0
  84. package/dist/xlifftest.d.ts +54 -0
  85. package/dist/xlifftest.js +245 -0
  86. package/dist/xlifftest.js.map +1 -0
  87. package/package.json +33 -0
@@ -0,0 +1,51 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse License 1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { tmpdir } from "node:os";
13
+ import { basename, join } from 'node:path';
14
+ import { SAXParser } from "typesxml";
15
+ import { DEFAULT_IMPORT_OPTIONS, resolveImportOptions } from './importOptions.js';
16
+ import { TMXHandler } from './tmxHandler.js';
17
+ export class TMXReader {
18
+ parser;
19
+ filePath;
20
+ handler;
21
+ jsonlTempPath;
22
+ options;
23
+ constructor(filePath, options = DEFAULT_IMPORT_OPTIONS) {
24
+ this.filePath = filePath;
25
+ this.options = resolveImportOptions(options);
26
+ const filename = basename(filePath);
27
+ // Generate temp file path for the JSONL output
28
+ const tempDir = tmpdir();
29
+ const tempFileName = 'tmx_' + Date.now() + '_' + Math.random().toString(36).substring(7) + '.jsonl';
30
+ this.jsonlTempPath = join(tempDir, tempFileName);
31
+ this.parser = new SAXParser();
32
+ this.handler = new TMXHandler(this.jsonlTempPath, filename, this.options);
33
+ this.parser.setContentHandler(this.handler);
34
+ }
35
+ async parse() {
36
+ try {
37
+ this.parser.parseFile(this.filePath);
38
+ await this.handler.waitForCompletion();
39
+ }
40
+ catch (error) {
41
+ throw error instanceof Error ? error : new Error(String(error));
42
+ }
43
+ }
44
+ getTempFilePath() {
45
+ return this.jsonlTempPath;
46
+ }
47
+ getEntryCount() {
48
+ return this.handler.getEntryCount();
49
+ }
50
+ }
51
+ //# sourceMappingURL=tmxReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmxReader.js","sourceRoot":"","sources":["../ts/tmxReader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;iFAUiF;AAEjF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAwC,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACxH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,OAAO,SAAS;IAElB,MAAM,CAAY;IAClB,QAAQ,CAAS;IACjB,OAAO,CAAa;IACpB,aAAa,CAAS;IACL,OAAO,CAAwB;IAEhD,YAAY,QAAgB,EAAE,UAAyB,sBAAsB;QACzE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEpC,+CAA+C;QAC/C,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;QACzB,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;QACpG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,KAAK;QACP,IAAI,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,CAAC;IACL,CAAC;IAED,eAAe;QACX,OAAO,IAAI,CAAC,aAAa,CAAC;IAC9B,CAAC;IAED,aAAa;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC;CACJ"}
@@ -0,0 +1,16 @@
1
+ export declare class TMXTest {
2
+ private static readonly NAME;
3
+ private static readonly DB_PATH;
4
+ private static readonly SAMPLE_TMX;
5
+ private static readonly SWORD_FISH_TMX;
6
+ runTest(): Promise<void>;
7
+ private resetEnvironment;
8
+ private verifyEntry;
9
+ private verifySegmentMetadata;
10
+ private expectTranslationMatch;
11
+ private expectConcordanceMatch;
12
+ private logConcordanceExample;
13
+ private verifyMetadataRoundtrip;
14
+ private verifyBatchImporterRoundtrip;
15
+ private assertMetadataEquals;
16
+ }
@@ -0,0 +1,316 @@
1
+ import { rmSync, writeFileSync } from 'node:fs';
2
+ import { BatchImporter } from './batchImporter.js';
3
+ import { HybridTM } from './hybridtm.js';
4
+ import { HybridTMFactory } from './hybridtmFactory.js';
5
+ import { Utils } from './utils.js';
6
+ export class TMXTest {
7
+ static NAME = 'TMX Test';
8
+ static DB_PATH = 'my-tmx.lancedb';
9
+ static SAMPLE_TMX = './samples/fluenta_sample.tmx';
10
+ static SWORD_FISH_TMX = './samples/terms.xlf.tmx';
11
+ async runTest() {
12
+ try {
13
+ this.resetEnvironment();
14
+ const tm = HybridTMFactory.createInstance(TMXTest.NAME, TMXTest.DB_PATH, HybridTM.SPEED_MODEL);
15
+ console.log('Created new HybridTM instance with name: ' + TMXTest.NAME);
16
+ await tm.importTMX(TMXTest.SAMPLE_TMX)
17
+ .then(() => {
18
+ console.log('TMX file imported successfully.');
19
+ })
20
+ .catch(err => {
21
+ console.error('Failed to import TMX file:', err);
22
+ });
23
+ await this.verifyEntry(tm, 'fluenta_sample.tmx', 'TMX-001', 'en', 0, 1);
24
+ await this.verifyEntry(tm, 'fluenta_sample.tmx', 'TMX-001', 'es', 0, 1);
25
+ await this.expectTranslationMatch(tm, 'Fluenta recovers exact matches from translations stored in the previous cycle.', 'en', 'es', 90, 'Fluenta recovers exact matches from translations stored in the previous cycle.', 'Fluenta recupera coincidencias exactas de las traducciones almacenadas en el ciclo anterior.', 'TMX exact match');
26
+ await this.expectTranslationMatch(tm, 'Fluenta automatically recovers exact matches from the previous translation cycle.', 'en', 'es', 75, 'Fluenta recovers exact matches from translations stored in the previous cycle.', 'Fluenta recupera coincidencias exactas de las traducciones almacenadas en el ciclo anterior.', 'TMX fuzzy paraphrase');
27
+ await this.expectTranslationMatch(tm, 'You do not need to pay again for content that stayed the same.', 'en', 'es', 65, 'You don\'t need to pay again for translation of content that didn\'t change.', 'No necesita pagar de nuevo por la traducción del contenido que no cambió.', 'TMX semantic reuse reminder');
28
+ await this.expectConcordanceMatch(tm, 'translation memory for reuse', 'en', 'es', 'Archive the translation memory for reuse.', 'Archive la memoria de traducción para su reutilización.', 'TMX concordance reuse unit');
29
+ await this.logConcordanceExample(tm, 'translation memory', 'en');
30
+ await tm.importTMX(TMXTest.SWORD_FISH_TMX);
31
+ await this.verifySegmentMetadata(tm, 'terms.xlf.tmx', '228667853-1-11-11', 'en', {
32
+ fileHash: '228667853',
33
+ fileId: '1',
34
+ unitId: '11',
35
+ segmentId: '11'
36
+ });
37
+ await this.verifyMetadataRoundtrip(tm);
38
+ await this.verifyBatchImporterRoundtrip(tm);
39
+ await tm.close();
40
+ console.log('Test completed successfully');
41
+ }
42
+ catch (err) {
43
+ console.error('Test failed:', err);
44
+ throw err;
45
+ }
46
+ }
47
+ resetEnvironment() {
48
+ try {
49
+ HybridTMFactory.removeInstance(TMXTest.NAME);
50
+ }
51
+ catch (err) {
52
+ // ignore missing instance
53
+ }
54
+ try {
55
+ rmSync(TMXTest.DB_PATH, { recursive: true, force: true });
56
+ }
57
+ catch (err) {
58
+ // ignore cleanup issues
59
+ }
60
+ }
61
+ async verifyEntry(tm, fileId, unitId, lang, segmentIndex, segmentCount) {
62
+ const entry = await tm.getLangEntry(fileId, unitId, lang, segmentIndex);
63
+ if (!entry) {
64
+ throw new Error('Entry not found for ' + fileId + ':' + unitId + ':' + segmentIndex + ':' + lang);
65
+ }
66
+ if (entry.id !== fileId + ':' + unitId + ':' + segmentIndex + ':' + lang) {
67
+ throw new Error('Unexpected entry id ' + entry.id);
68
+ }
69
+ if (entry.segmentIndex !== segmentIndex) {
70
+ throw new Error('Segment index mismatch for ' + entry.id);
71
+ }
72
+ if (entry.segmentCount !== segmentCount) {
73
+ throw new Error('Segment count mismatch for ' + entry.id);
74
+ }
75
+ if (!entry.metadata) {
76
+ throw new Error('Metadata missing for ' + entry.id);
77
+ }
78
+ if (!entry.vector || entry.vector.length === 0) {
79
+ throw new Error('Vector missing for ' + entry.id);
80
+ }
81
+ console.log('Verified entry ' + entry.id + ' with vector size ' + entry.vector.length);
82
+ }
83
+ async verifySegmentMetadata(tm, fileId, unitId, lang, expected) {
84
+ const entry = await tm.getLangEntry(fileId, unitId, lang, 0);
85
+ if (!entry || !entry.metadata || !entry.metadata.segment) {
86
+ throw new Error('Missing segment metadata for ' + unitId);
87
+ }
88
+ const segmentMeta = entry.metadata.segment;
89
+ if (segmentMeta.provider !== 'xliff-segment') {
90
+ throw new Error('Unexpected metadata provider for ' + unitId);
91
+ }
92
+ if (segmentMeta.fileHash !== expected.fileHash ||
93
+ segmentMeta.fileId !== expected.fileId ||
94
+ segmentMeta.unitId !== expected.unitId ||
95
+ segmentMeta.segmentId !== expected.segmentId) {
96
+ throw new Error('Segment metadata mismatch for ' + unitId);
97
+ }
98
+ if (!segmentMeta.segmentKey || segmentMeta.segmentKey !== unitId) {
99
+ throw new Error('Segment key missing on metadata for ' + unitId);
100
+ }
101
+ if (!entry.metadata.context || entry.metadata.context.indexOf('unit 10, segment 10') === -1) {
102
+ throw new Error('Directional context not decoded for ' + unitId);
103
+ }
104
+ console.log('Verified segment metadata for ' + unitId + ' (' + segmentMeta.segmentKey + ')');
105
+ }
106
+ async expectTranslationMatch(tm, query, srcLang, tgtLang, similarity, expectedSourceSnippet, expectedTargetSnippet, label) {
107
+ const matches = await tm.semanticTranslationSearch(query, srcLang, tgtLang, similarity);
108
+ if (matches.length === 0) {
109
+ throw new Error('No matches found for "' + label + '" query.');
110
+ }
111
+ const best = matches[0];
112
+ const sourceXml = best.source.toString();
113
+ const targetXml = best.target.toString();
114
+ if (!sourceXml.includes(expectedSourceSnippet)) {
115
+ throw new Error('Unexpected source match for "' + label + '": ' + sourceXml);
116
+ }
117
+ if (!targetXml.includes(expectedTargetSnippet)) {
118
+ throw new Error('Unexpected target match for "' + label + '": ' + targetXml);
119
+ }
120
+ console.log('[' + label + '] matches=' + matches.length + ' semantic=' + best.semantic + ' fuzzy=' + best.fuzzy + ' hybrid=' + best.hybridScore());
121
+ }
122
+ async expectConcordanceMatch(tm, fragment, srcLang, tgtLang, expectedSourceSnippet, expectedTargetSnippet, label) {
123
+ const results = await tm.concordanceSearch(fragment, srcLang, 5);
124
+ if (results.length === 0) {
125
+ throw new Error('No concordance matches found for "' + label + '" fragment.');
126
+ }
127
+ const best = results[0];
128
+ const sourceElement = best.get(srcLang);
129
+ const targetElement = best.get(tgtLang);
130
+ if (!sourceElement || !sourceElement.toString().includes(expectedSourceSnippet)) {
131
+ throw new Error('Unexpected concordance source for "' + label + '".');
132
+ }
133
+ if (!targetElement || !targetElement.toString().includes(expectedTargetSnippet)) {
134
+ throw new Error('Unexpected concordance target for "' + label + '".');
135
+ }
136
+ console.log('[' + label + '] concordance languages=' + Array.from(best.keys()).join(', '));
137
+ }
138
+ async logConcordanceExample(tm, fragment, language) {
139
+ const rows = await tm.concordanceSearch(fragment, language, 1);
140
+ if (rows.length === 0) {
141
+ console.log('No concordance example available for "' + fragment + '".');
142
+ return;
143
+ }
144
+ console.log('Concordance example for "' + fragment + '":');
145
+ const sample = rows[0];
146
+ sample.forEach((element, langKey) => {
147
+ const pureText = Utils.getPureText(element).trim().replace(/\s+/g, ' ');
148
+ const flattened = pureText.length > 0
149
+ ? pureText
150
+ : element.toString().replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
151
+ console.log(' [' + langKey + '] ' + flattened);
152
+ });
153
+ }
154
+ async verifyMetadataRoundtrip(tm) {
155
+ const fileId = 'metadata-roundtrip.tmx';
156
+ const unitId = 'ROUNDTRIP-UNIT-1';
157
+ const lang = 'en';
158
+ const segmentIndex = 0;
159
+ const sourceElement = Utils.buildXMLElement('<seg>Metadata roundtrip source</seg>');
160
+ const metadata = {
161
+ state: 'final',
162
+ subState: 'approved',
163
+ quality: 97,
164
+ creationDate: '2024-12-01T10:00:00Z',
165
+ creationId: 'author@example.com',
166
+ changeDate: '2024-12-15T12:34:56Z',
167
+ changeId: 'reviewer@example.com',
168
+ creationTool: 'HybridTM Test Harness',
169
+ creationToolVersion: '1.0.0',
170
+ context: 'Roundtrip metadata context',
171
+ notes: ['roundtrip-note-a', 'roundtrip-note-b'],
172
+ usageCount: 7,
173
+ lastUsageDate: '2025-01-01T08:30:00Z',
174
+ properties: {
175
+ product: 'HybridTM',
176
+ channel: 'support'
177
+ },
178
+ segment: {
179
+ provider: 'unit-test',
180
+ fileHash: 'hash-rt-001',
181
+ fileId: 'roundtrip-file',
182
+ unitId,
183
+ segmentId: 'seg-0',
184
+ segmentIndex,
185
+ segmentCount: 1,
186
+ segmentKey: unitId + '-0'
187
+ }
188
+ };
189
+ await tm.storeLangEntry(fileId, sourceElement.toString(), unitId, lang, 'Metadata roundtrip source', sourceElement, undefined, segmentIndex, 1, metadata);
190
+ const fetched = await tm.getLangEntry(fileId, unitId, lang, segmentIndex);
191
+ if (!fetched) {
192
+ throw new Error('Metadata roundtrip entry missing for ' + unitId);
193
+ }
194
+ this.assertMetadataEquals(fetched.metadata, metadata);
195
+ console.log('[Metadata roundtrip] state=' + fetched.metadata.state + ' quality=' + fetched.metadata.quality + ' properties=' + JSON.stringify(fetched.metadata.properties));
196
+ }
197
+ async verifyBatchImporterRoundtrip(tm) {
198
+ const tempPath = './temp-jsonl-roundtrip.jsonl';
199
+ const fileId = 'jsonl-batch-roundtrip.tmx';
200
+ const enrichedMetadata = {
201
+ state: 'reviewed',
202
+ context: 'JSONL batch importer context',
203
+ notes: ['jsonl-note-a', 'jsonl-note-b'],
204
+ properties: {
205
+ channel: 'jsonl-test',
206
+ domain: 'batch-importer'
207
+ }
208
+ };
209
+ const entries = [
210
+ {
211
+ language: 'en',
212
+ fileId,
213
+ original: fileId,
214
+ unitId: 'JSONL-UNIT-1',
215
+ pureText: 'JSONL batch importer roundtrip source',
216
+ element: '<seg>JSONL batch importer roundtrip source</seg>',
217
+ segmentIndex: 0,
218
+ segmentCount: 1,
219
+ metadata: enrichedMetadata
220
+ },
221
+ {
222
+ language: 'es',
223
+ fileId,
224
+ original: fileId,
225
+ unitId: 'JSONL-UNIT-2',
226
+ pureText: 'JSONL batch importer roundtrip target',
227
+ element: '<seg>JSONL batch importer roundtrip target</seg>',
228
+ segmentIndex: 0,
229
+ segmentCount: 1
230
+ }
231
+ ];
232
+ const payload = entries
233
+ .map((entry) => JSON.stringify(entry))
234
+ .join('\n') + '\n';
235
+ writeFileSync(tempPath, payload, { encoding: 'utf8' });
236
+ const importer = new BatchImporter(tm, tempPath, entries.length);
237
+ await importer.import();
238
+ const enriched = await tm.getLangEntry(fileId, 'JSONL-UNIT-1', 'en', 0);
239
+ if (!enriched) {
240
+ throw new Error('BatchImporter JSONL entry with metadata missing');
241
+ }
242
+ this.assertMetadataEquals(enriched.metadata, enrichedMetadata);
243
+ const minimal = await tm.getLangEntry(fileId, 'JSONL-UNIT-2', 'es', 0);
244
+ if (!minimal) {
245
+ throw new Error('BatchImporter JSONL entry without metadata missing');
246
+ }
247
+ if (Object.keys(minimal.metadata).length !== 0) {
248
+ throw new Error('Expected empty metadata object for JSONL-UNIT-2 entry');
249
+ }
250
+ console.log('[BatchImporter JSONL roundtrip] enrichedKeys=' + Object.keys(enriched.metadata).length + ' minimalKeys=' + Object.keys(minimal.metadata).length);
251
+ }
252
+ assertMetadataEquals(actual, expected) {
253
+ const fail = (field, actualValue, expectedValue) => {
254
+ throw new Error('Metadata roundtrip mismatch for ' + field + ': expected ' + JSON.stringify(expectedValue) + ' but received ' + JSON.stringify(actualValue));
255
+ };
256
+ const scalarFields = [
257
+ 'state',
258
+ 'subState',
259
+ 'quality',
260
+ 'creationDate',
261
+ 'creationId',
262
+ 'changeDate',
263
+ 'changeId',
264
+ 'creationTool',
265
+ 'creationToolVersion',
266
+ 'context',
267
+ 'usageCount',
268
+ 'lastUsageDate'
269
+ ];
270
+ scalarFields.forEach((field) => {
271
+ if ((actual[field] ?? null) !== (expected[field] ?? null)) {
272
+ fail(field, actual[field], expected[field]);
273
+ }
274
+ });
275
+ const expectedNotes = expected.notes ?? [];
276
+ const actualNotes = actual.notes ?? [];
277
+ if (actualNotes.length !== expectedNotes.length || !actualNotes.every((value, index) => value === expectedNotes[index])) {
278
+ fail('notes', actualNotes, expectedNotes);
279
+ }
280
+ const normalizeObject = (value) => {
281
+ if (!value) {
282
+ return {};
283
+ }
284
+ const sortedKeys = Object.keys(value).sort();
285
+ return sortedKeys.reduce((acc, key) => {
286
+ acc[key] = value[key];
287
+ return acc;
288
+ }, {});
289
+ };
290
+ const actualProperties = normalizeObject(actual.properties);
291
+ const expectedProperties = normalizeObject(expected.properties);
292
+ if (JSON.stringify(actualProperties) !== JSON.stringify(expectedProperties)) {
293
+ fail('properties', actualProperties, expectedProperties);
294
+ }
295
+ const actualSegment = normalizeObject(actual.segment);
296
+ const expectedSegment = normalizeObject(expected.segment);
297
+ if (JSON.stringify(actualSegment) !== JSON.stringify(expectedSegment)) {
298
+ fail('segment', actualSegment, expectedSegment);
299
+ }
300
+ }
301
+ }
302
+ // Instantiate and run the test
303
+ async function main() {
304
+ const test = new TMXTest();
305
+ try {
306
+ await test.runTest();
307
+ console.log('All done!');
308
+ process.exit(0);
309
+ }
310
+ catch (error) {
311
+ console.error('Test execution failed:', error);
312
+ process.exit(1);
313
+ }
314
+ }
315
+ main();
316
+ //# sourceMappingURL=tmxtest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmxtest.js","sourceRoot":"","sources":["../ts/tmxtest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse License 1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { XMLElement } from "typesxml";
13
+ export declare class Utils {
14
+ static replaceQuotes(value: string): string;
15
+ static getPureText(element: XMLElement): string;
16
+ static buildXMLElement(str: string): XMLElement;
17
+ }
package/dist/utils.js ADDED
@@ -0,0 +1,49 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025-2026 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse License 1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ import { DOMBuilder, SAXParser, TextNode, XMLElement } from "typesxml";
13
+ export class Utils {
14
+ static replaceQuotes(value) {
15
+ return value.replaceAll("'", "''");
16
+ }
17
+ static getPureText(element) {
18
+ let text = '';
19
+ let content = element.getContent();
20
+ content.forEach((node) => {
21
+ if (node instanceof TextNode) {
22
+ text += node.getValue();
23
+ }
24
+ if (node instanceof XMLElement) {
25
+ const child = node;
26
+ if ("pc" === child.getName() || "mrk" === child.getName() || "hi" === child.getName()) {
27
+ text += this.getPureText(child);
28
+ }
29
+ // purposedly ignore "cp" for now
30
+ }
31
+ });
32
+ return text;
33
+ }
34
+ static buildXMLElement(str) {
35
+ const contentHandler = new DOMBuilder();
36
+ const xmlParser = new SAXParser();
37
+ xmlParser.setContentHandler(contentHandler);
38
+ xmlParser.parseString(str);
39
+ const newDoc = contentHandler.getDocument();
40
+ if (newDoc) {
41
+ const root = newDoc.getRoot();
42
+ if (root) {
43
+ return root;
44
+ }
45
+ }
46
+ throw new Error('Error building XMLElement from string');
47
+ }
48
+ }
49
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../ts/utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;iFAUiF;AAEjF,OAAO,EAAkB,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAe,UAAU,EAAW,MAAM,UAAU,CAAC;AAE7G,MAAM,OAAO,KAAK;IAEd,MAAM,CAAC,aAAa,CAAC,KAAa;QAC9B,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,OAAmB;QAClC,IAAI,IAAI,GAAW,EAAE,CAAC;QACtB,IAAI,OAAO,GAAc,OAAO,CAAC,UAAU,EAAE,CAAC;QAC9C,OAAO,CAAC,OAAO,CAAC,CAAC,IAAa,EAAE,EAAE;YAC9B,IAAI,IAAI,YAAY,QAAQ,EAAE,CAAC;gBAC3B,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC5B,CAAC;YACD,IAAI,IAAI,YAAY,UAAU,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAe,IAAI,CAAC;gBAC/B,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,IAAI,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,IAAI,IAAI,KAAK,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;oBACpF,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACpC,CAAC;gBACD,iCAAiC;YACrC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,eAAe,CAAC,GAAW;QAC9B,MAAM,cAAc,GAAmB,IAAI,UAAU,EAAE,CAAC;QACxD,MAAM,SAAS,GAAc,IAAI,SAAS,EAAE,CAAC;QAC7C,SAAS,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAC5C,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC3B,MAAM,MAAM,GAA6B,cAA6B,CAAC,WAAW,EAAE,CAAC;QACrF,IAAI,MAAM,EAAE,CAAC;YACT,MAAM,IAAI,GAA2B,MAAM,CAAC,OAAO,EAAE,CAAC;YACtD,IAAI,IAAI,EAAE,CAAC;gBACP,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC7D,CAAC;CACJ"}
@@ -0,0 +1,56 @@
1
+ /*******************************************************************************
2
+ * Copyright (c) 2025 Maxprograms.
3
+ *
4
+ * This program and the accompanying materials
5
+ * are made available under the terms of the Eclipse Public License 1.0
6
+ * which accompanies this distribution, and is available at
7
+ * https://www.eclipse.org/org/documents/epl-v10.html
8
+ *
9
+ * Contributors:
10
+ * Maxprograms - initial API and implementation
11
+ *******************************************************************************/
12
+ export interface VectorComparisonInput {
13
+ label?: string;
14
+ sourceVector: number[];
15
+ targetVector: number[];
16
+ }
17
+ export interface TextComparisonInput {
18
+ label?: string;
19
+ sourceText: string;
20
+ targetText: string;
21
+ }
22
+ export interface VectorComparisonResult {
23
+ label?: string;
24
+ manhattanScore: number;
25
+ cosineScore: number;
26
+ cosineMinusManhattan: number;
27
+ absoluteDifference: number;
28
+ manhattanPercent: number;
29
+ cosinePercent: number;
30
+ }
31
+ export interface TextComparisonResult extends VectorComparisonResult {
32
+ sourceText: string;
33
+ targetText: string;
34
+ }
35
+ export interface ComparisonSummary {
36
+ averageManhattan: number;
37
+ averageCosine: number;
38
+ averageAbsoluteDifference: number;
39
+ maxAbsoluteDifference: number;
40
+ minAbsoluteDifference: number;
41
+ }
42
+ export declare class VectorSimilarityTester {
43
+ static readonly DEFAULT_MODEL: string;
44
+ private embedder;
45
+ private readonly modelName;
46
+ constructor(modelName?: string);
47
+ private static manhattanSimilarity;
48
+ private static cosineSimilarity;
49
+ private static buildResult;
50
+ private ensureEmbedder;
51
+ private embed;
52
+ static compareVectors(input: VectorComparisonInput): VectorComparisonResult;
53
+ compareTexts(inputs: TextComparisonInput[]): Promise<TextComparisonResult[]>;
54
+ static summarize(results: VectorComparisonResult[]): ComparisonSummary;
55
+ static formatResults(results: VectorComparisonResult[]): string;
56
+ }