@keymanapp/kmc-ldml 18.0.41-alpha → 18.0.45-alpha

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 (58) hide show
  1. package/build/src/compiler/compiler.d.ts +123 -123
  2. package/build/src/compiler/compiler.js +307 -310
  3. package/build/src/compiler/compiler.js.map +1 -1
  4. package/build/src/compiler/disp.d.ts +11 -11
  5. package/build/src/compiler/disp.js +82 -85
  6. package/build/src/compiler/disp.js.map +1 -1
  7. package/build/src/compiler/empty-compiler.d.ts +37 -37
  8. package/build/src/compiler/empty-compiler.js +114 -117
  9. package/build/src/compiler/empty-compiler.js.map +1 -1
  10. package/build/src/compiler/keymanweb-compiler.d.ts +13 -13
  11. package/build/src/compiler/keymanweb-compiler.js +95 -98
  12. package/build/src/compiler/keymanweb-compiler.js.map +1 -1
  13. package/build/src/compiler/keys.d.ts +53 -53
  14. package/build/src/compiler/keys.js +417 -420
  15. package/build/src/compiler/keys.js.map +1 -1
  16. package/build/src/compiler/layr.d.ts +9 -9
  17. package/build/src/compiler/layr.js +81 -84
  18. package/build/src/compiler/layr.js.map +1 -1
  19. package/build/src/compiler/ldml-compiler-options.d.ts +11 -11
  20. package/build/src/compiler/ldml-compiler-options.js +3 -6
  21. package/build/src/compiler/ldml-compiler-options.js.map +1 -1
  22. package/build/src/compiler/loca.d.ts +15 -15
  23. package/build/src/compiler/loca.js +59 -62
  24. package/build/src/compiler/loca.js.map +1 -1
  25. package/build/src/compiler/messages.d.ts +186 -186
  26. package/build/src/compiler/messages.js +122 -125
  27. package/build/src/compiler/messages.js.map +1 -1
  28. package/build/src/compiler/meta.d.ts +13 -13
  29. package/build/src/compiler/meta.js +55 -58
  30. package/build/src/compiler/meta.js.map +1 -1
  31. package/build/src/compiler/metadata-compiler.d.ts +12 -12
  32. package/build/src/compiler/metadata-compiler.js +47 -50
  33. package/build/src/compiler/metadata-compiler.js.map +1 -1
  34. package/build/src/compiler/section-compiler.d.ts +35 -35
  35. package/build/src/compiler/section-compiler.js +40 -43
  36. package/build/src/compiler/section-compiler.js.map +1 -1
  37. package/build/src/compiler/substitution-tracker.d.ts +47 -47
  38. package/build/src/compiler/substitution-tracker.js +103 -106
  39. package/build/src/compiler/substitution-tracker.js.map +1 -1
  40. package/build/src/compiler/touch-layout-compiler.d.ts +7 -7
  41. package/build/src/compiler/touch-layout-compiler.js +91 -94
  42. package/build/src/compiler/touch-layout-compiler.js.map +1 -1
  43. package/build/src/compiler/tran.d.ts +57 -57
  44. package/build/src/compiler/tran.js +388 -391
  45. package/build/src/compiler/tran.js.map +1 -1
  46. package/build/src/compiler/vars.d.ts +21 -21
  47. package/build/src/compiler/vars.js +234 -237
  48. package/build/src/compiler/vars.js.map +1 -1
  49. package/build/src/compiler/visual-keyboard-compiler.d.ts +8 -8
  50. package/build/src/compiler/visual-keyboard-compiler.js +68 -71
  51. package/build/src/compiler/visual-keyboard-compiler.js.map +1 -1
  52. package/build/src/main.d.ts +3 -3
  53. package/build/src/main.js +3 -6
  54. package/build/src/main.js.map +1 -1
  55. package/build/src/util/util.d.ts +49 -49
  56. package/build/src/util/util.js +183 -186
  57. package/build/src/util/util.js.map +1 -1
  58. package/package.json +6 -6
@@ -1,310 +1,307 @@
1
-
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5183a68a-b994-5081-b881-0db8ef00163d")}catch(e){}}();
3
- import { LDMLKeyboardXMLSourceFileReader, KMXPlus, defaultCompilerOptions, KMXBuilder, KvkFileWriter } from '@keymanapp/common-types';
4
- import { CompilerMessages } from './messages.js';
5
- import { BkspCompiler, TranCompiler } from './tran.js';
6
- import { DispCompiler } from './disp.js';
7
- import { KeysCompiler } from './keys.js';
8
- import { LayrCompiler } from './layr.js';
9
- import { LocaCompiler } from './loca.js';
10
- import { MetaCompiler } from './meta.js';
11
- import { VarsCompiler } from './vars.js';
12
- import { StrsCompiler, ElemCompiler, ListCompiler, UsetCompiler } from './empty-compiler.js';
13
- var KMXPlusFile = KMXPlus.KMXPlusFile;
14
- import { constants } from '@keymanapp/ldml-keyboard-constants';
15
- import { KmnCompiler } from '@keymanapp/kmc-kmn';
16
- import { KMXPlusMetadataCompiler } from './metadata-compiler.js';
17
- import { LdmlKeyboardVisualKeyboardCompiler } from './visual-keyboard-compiler.js';
18
- //KMW17.0: import { LdmlKeyboardKeymanWebCompiler } from './keymanweb-compiler.js';
19
- export const SECTION_COMPILERS = [
20
- // These are in dependency order.
21
- // First the former 'global' sections
22
- StrsCompiler,
23
- // meta depends on strs, but potentially needed by anything else using strs
24
- MetaCompiler,
25
- ListCompiler,
26
- ElemCompiler,
27
- UsetCompiler,
28
- // Next, Vars, which depends on others
29
- VarsCompiler,
30
- // Now all others:
31
- BkspCompiler,
32
- DispCompiler,
33
- KeysCompiler,
34
- LayrCompiler,
35
- LocaCompiler,
36
- TranCompiler,
37
- ];
38
- ;
39
- ;
40
- /**
41
- * @public
42
- * Compiles a LDML keyboard .xml file to a .kmx (KMXPlus), .kvk, and/or .js. The
43
- * compiler does not read or write from filesystem or network directly, but
44
- * relies on callbacks for all external IO.
45
- */
46
- export class LdmlKeyboardCompiler {
47
- callbacks;
48
- options;
49
- // uset parser
50
- usetparser = undefined;
51
- /**
52
- * Initialize the compiler, including loading the WASM host for uset parsing.
53
- * Copies options.
54
- * @param callbacks - Callbacks for external interfaces, including message
55
- * reporting and file io
56
- * @param options - Compiler options
57
- * @returns false if initialization fails
58
- */
59
- async init(callbacks, options) {
60
- this.options = { ...options };
61
- this.callbacks = callbacks;
62
- return true;
63
- }
64
- /**
65
- * Compiles a LDML keyboard .xml file to .kmx, .kvk, and/or .js files. Returns
66
- * an object containing binary artifacts on success. The files are passed in
67
- * by name, and the compiler will use callbacks as passed to the
68
- * {@link LdmlKeyboardCompiler.init} function to read any input files by disk.
69
- * @param infile - Path to source file.
70
- * @param outfile - Path to output file. The file will not be written to, but
71
- * will be included in the result for use by
72
- * {@link LdmlKeyboardCompiler.write}.
73
- * @returns Binary artifacts on success, null on failure.
74
- */
75
- async run(inputFilename, outputFilename) {
76
- let compilerOptions = {
77
- ...defaultCompilerOptions,
78
- ...this.options,
79
- };
80
- let source = this.load(inputFilename);
81
- if (!source) {
82
- return null;
83
- }
84
- let kmx = await this.compile(source);
85
- if (!kmx) {
86
- return null;
87
- }
88
- // In order for the KMX file to be loaded by non-KMXPlus components, it is helpful
89
- // to duplicate some of the metadata
90
- KMXPlusMetadataCompiler.addKmxMetadata(kmx.kmxplus, kmx.keyboard, compilerOptions);
91
- // Use the builder to generate the binary output file
92
- const builder = new KMXBuilder(kmx, compilerOptions.saveDebug);
93
- const kmx_binary = builder.compile();
94
- const vkcompiler = new LdmlKeyboardVisualKeyboardCompiler(this.callbacks);
95
- const vk = vkcompiler.compile(source);
96
- const writer = new KvkFileWriter();
97
- const kvk_binary = writer.write(vk);
98
- // Note: we could have a step of generating source files here
99
- // KvksFileWriter()...
100
- // const tlcompiler = new kmc.TouchLayoutCompiler();
101
- // const tl = tlcompiler.compile(source);
102
- // const tlwriter = new TouchLayoutFileWriter();
103
- //KMW17.0: const kmwcompiler = new LdmlKeyboardKeymanWebCompiler(this.callbacks, compilerOptions);
104
- //KMW17.0: const kmw_string = kmwcompiler.compile(inputFilename, source);
105
- //KMW17.0: const encoder = new TextEncoder();
106
- //KMW17.0: const kmw_binary = encoder.encode(kmw_string);
107
- outputFilename = outputFilename ?? inputFilename.replace(/\.xml$/, '.kmx');
108
- return {
109
- artifacts: {
110
- kmx: { data: kmx_binary, filename: outputFilename },
111
- kvk: { data: kvk_binary, filename: outputFilename.replace(/\.kmx$/, '.kvk') },
112
- //KMW17.0: js: { data: kmw_binary, filename: outputFilename.replace(/\.kmx$/, '.js') },
113
- }
114
- };
115
- }
116
- /**
117
- * Write artifacts from a successful compile to disk, via callbacks methods.
118
- * The artifacts written may include:
119
- *
120
- * - .kmx file - binary keyboard used by Keyman on desktop platforms
121
- * - .kvk file - binary on screen keyboard used by Keyman on desktop platforms
122
- * - .js file - Javascript keyboard for web and touch platforms
123
- *
124
- * @param artifacts - object containing artifact binary data to write out
125
- * @returns true on success
126
- */
127
- async write(artifacts) {
128
- if (artifacts.kmx) {
129
- this.callbacks.fs.writeFileSync(artifacts.kmx.filename, artifacts.kmx.data);
130
- }
131
- if (artifacts.kvk) {
132
- this.callbacks.fs.writeFileSync(artifacts.kvk.filename, artifacts.kvk.data);
133
- }
134
- if (artifacts.js) {
135
- this.callbacks.fs.writeFileSync(artifacts.js.filename, artifacts.js.data);
136
- }
137
- return true;
138
- }
139
- /**
140
- * @internal
141
- * Construct or return a UnicodeSetParser, aka KmnCompiler
142
- * @returns the held UnicodeSetParser
143
- */
144
- async getUsetParser() {
145
- if (this.usetparser === undefined) {
146
- // initialize
147
- const compiler = new KmnCompiler();
148
- const ok = await compiler.init(this.callbacks, null);
149
- if (ok) {
150
- this.usetparser = compiler;
151
- }
152
- else {
153
- /* c8 ignore next 2 */
154
- this.usetparser = null; // Store null on failure
155
- }
156
- }
157
- return this.usetparser;
158
- }
159
- buildSections(source) {
160
- return SECTION_COMPILERS.map(c => new c(source, this.callbacks));
161
- }
162
- /**
163
- * @internal
164
- * Loads a LDML Keyboard xml file and compiles into in-memory xml
165
- * structures.
166
- * @param filename - input filename, will use callback to load from disk
167
- * @returns the source file, or null if invalid
168
- */
169
- load(filename) {
170
- const reader = new LDMLKeyboardXMLSourceFileReader(this.options.readerOptions, this.callbacks);
171
- // load the file from disk into a string
172
- const data = this.callbacks.loadFile(filename);
173
- if (!data) {
174
- this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to read XML file' }));
175
- return null;
176
- }
177
- // parse (load) the string into an object tree
178
- const source = reader.load(data);
179
- if (!source) {
180
- this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to load XML file' }));
181
- return null;
182
- }
183
- try {
184
- // validate the object tree against the .xsd schema
185
- if (!reader.validate(source)) {
186
- return null;
187
- }
188
- }
189
- catch (e) {
190
- this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: e.toString() }));
191
- return null;
192
- }
193
- return source;
194
- }
195
- /**
196
- * @internal
197
- * Loads a LDML Keyboard test data xml file and compiles into in-memory xml
198
- * structures.
199
- * @param filename - input filename, will use callback to load from disk
200
- * @returns the source file, or null if invalid
201
- */
202
- loadTestData(filename) {
203
- const reader = new LDMLKeyboardXMLSourceFileReader(this.options.readerOptions, this.callbacks);
204
- const data = this.callbacks.loadFile(filename);
205
- if (!data) {
206
- this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to read XML file' }));
207
- return null;
208
- }
209
- const source = reader.loadTestData(data);
210
- /* c8 ignore next 4 */
211
- if (!source) {
212
- this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to load XML file' }));
213
- return null;
214
- }
215
- // TODO-LDML: The unboxed data doesn't match the schema anymore. Skipping validation, for now.
216
- // try {
217
- // if (!reader.validate(source)) {
218
- // return null;
219
- // }
220
- // } catch(e) {
221
- // this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({errorText: e.toString()}));
222
- // return null;
223
- // }
224
- return source;
225
- }
226
- /**
227
- * @internal
228
- * Validates that the LDML keyboard source file and lints. Actually just
229
- * compiles the keyboard and returns `true` if everything is good...
230
- * @param source - in-memory representation of LDML keyboard xml file
231
- * @returns true if the file validates
232
- */
233
- async validate(source) {
234
- return !!(await this.compile(source, true));
235
- }
236
- /**
237
- * @internal
238
- * Transforms in-memory LDML keyboard xml file to an intermediate
239
- * representation of a .kmx file.
240
- * @param source - in-memory representation of LDML keyboard xml file
241
- * @returns KMXPlusFile intermediate file
242
- */
243
- async compile(source, postValidate) {
244
- const sections = this.buildSections(source);
245
- let passed = true;
246
- const kmx = new KMXPlusFile();
247
- for (let section of sections) {
248
- if (!section.validate()) {
249
- // TODO-LDML: coverage
250
- passed = false;
251
- // We'll keep validating other sections anyway, so we get a full set of
252
- // errors for the keyboard developer.
253
- continue;
254
- }
255
- // clone
256
- const globalSections = Object.assign({}, kmx.kmxplus);
257
- // pre-initialize the usetparser
258
- globalSections.usetparser = await this.getUsetParser();
259
- const dependencies = section.dependencies;
260
- let dependencyProblem = false;
261
- Object.keys(constants.section).forEach((sectstr) => {
262
- const sectid = constants.section[sectstr];
263
- if (dependencies.has(sectid)) {
264
- /* c8 ignore next 4 */
265
- if (!kmx.kmxplus[sectid]) {
266
- if (passed) {
267
- // Internal error useful during section bring-up
268
- throw new Error(`Internal error: section ${section.id} depends on uninitialized dependency ${sectid}, check ordering`);
269
- }
270
- else {
271
- dependencyProblem = true;
272
- return; // Already failed to validate, so no need for the layering message.
273
- }
274
- }
275
- }
276
- else {
277
- // delete dependencies that aren't referenced
278
- delete globalSections[sectid];
279
- }
280
- });
281
- if (dependencyProblem && !passed) {
282
- // Some layering problem, but we've already noted an error (!passed).
283
- // Just skip this section.
284
- continue;
285
- }
286
- const sect = section.compile(globalSections);
287
- if (!sect) {
288
- passed = false;
289
- continue;
290
- }
291
- /* c8 ignore next 4 */
292
- if (kmx.kmxplus[section.id]) {
293
- // Internal error useful during section bring-up
294
- throw new Error(`Internal error: section ${section.id} would be assigned twice`);
295
- }
296
- kmx.kmxplus[section.id] = sect;
297
- }
298
- // give all sections a chance to postValidate
299
- if (postValidate) {
300
- for (let section of sections) {
301
- if (!section.postValidate(kmx.kmxplus[section.id])) {
302
- passed = false;
303
- }
304
- }
305
- }
306
- return passed ? kmx : null;
307
- }
308
- }
309
- //# sourceMappingURL=compiler.js.map
310
- //# debugId=5183a68a-b994-5081-b881-0db8ef00163d
1
+ import { LDMLKeyboardXMLSourceFileReader, KMXPlus, defaultCompilerOptions, KMXBuilder, KvkFileWriter } from '@keymanapp/common-types';
2
+ import { CompilerMessages } from './messages.js';
3
+ import { BkspCompiler, TranCompiler } from './tran.js';
4
+ import { DispCompiler } from './disp.js';
5
+ import { KeysCompiler } from './keys.js';
6
+ import { LayrCompiler } from './layr.js';
7
+ import { LocaCompiler } from './loca.js';
8
+ import { MetaCompiler } from './meta.js';
9
+ import { VarsCompiler } from './vars.js';
10
+ import { StrsCompiler, ElemCompiler, ListCompiler, UsetCompiler } from './empty-compiler.js';
11
+ var KMXPlusFile = KMXPlus.KMXPlusFile;
12
+ import { constants } from '@keymanapp/ldml-keyboard-constants';
13
+ import { KmnCompiler } from '@keymanapp/kmc-kmn';
14
+ import { KMXPlusMetadataCompiler } from './metadata-compiler.js';
15
+ import { LdmlKeyboardVisualKeyboardCompiler } from './visual-keyboard-compiler.js';
16
+ //KMW17.0: import { LdmlKeyboardKeymanWebCompiler } from './keymanweb-compiler.js';
17
+ export const SECTION_COMPILERS = [
18
+ // These are in dependency order.
19
+ // First the former 'global' sections
20
+ StrsCompiler,
21
+ // meta depends on strs, but potentially needed by anything else using strs
22
+ MetaCompiler,
23
+ ListCompiler,
24
+ ElemCompiler,
25
+ UsetCompiler,
26
+ // Next, Vars, which depends on others
27
+ VarsCompiler,
28
+ // Now all others:
29
+ BkspCompiler,
30
+ DispCompiler,
31
+ KeysCompiler,
32
+ LayrCompiler,
33
+ LocaCompiler,
34
+ TranCompiler,
35
+ ];
36
+ ;
37
+ ;
38
+ /**
39
+ * @public
40
+ * Compiles a LDML keyboard .xml file to a .kmx (KMXPlus), .kvk, and/or .js. The
41
+ * compiler does not read or write from filesystem or network directly, but
42
+ * relies on callbacks for all external IO.
43
+ */
44
+ export class LdmlKeyboardCompiler {
45
+ callbacks;
46
+ options;
47
+ // uset parser
48
+ usetparser = undefined;
49
+ /**
50
+ * Initialize the compiler, including loading the WASM host for uset parsing.
51
+ * Copies options.
52
+ * @param callbacks - Callbacks for external interfaces, including message
53
+ * reporting and file io
54
+ * @param options - Compiler options
55
+ * @returns false if initialization fails
56
+ */
57
+ async init(callbacks, options) {
58
+ this.options = { ...options };
59
+ this.callbacks = callbacks;
60
+ return true;
61
+ }
62
+ /**
63
+ * Compiles a LDML keyboard .xml file to .kmx, .kvk, and/or .js files. Returns
64
+ * an object containing binary artifacts on success. The files are passed in
65
+ * by name, and the compiler will use callbacks as passed to the
66
+ * {@link LdmlKeyboardCompiler.init} function to read any input files by disk.
67
+ * @param infile - Path to source file.
68
+ * @param outfile - Path to output file. The file will not be written to, but
69
+ * will be included in the result for use by
70
+ * {@link LdmlKeyboardCompiler.write}.
71
+ * @returns Binary artifacts on success, null on failure.
72
+ */
73
+ async run(inputFilename, outputFilename) {
74
+ let compilerOptions = {
75
+ ...defaultCompilerOptions,
76
+ ...this.options,
77
+ };
78
+ let source = this.load(inputFilename);
79
+ if (!source) {
80
+ return null;
81
+ }
82
+ let kmx = await this.compile(source);
83
+ if (!kmx) {
84
+ return null;
85
+ }
86
+ // In order for the KMX file to be loaded by non-KMXPlus components, it is helpful
87
+ // to duplicate some of the metadata
88
+ KMXPlusMetadataCompiler.addKmxMetadata(kmx.kmxplus, kmx.keyboard, compilerOptions);
89
+ // Use the builder to generate the binary output file
90
+ const builder = new KMXBuilder(kmx, compilerOptions.saveDebug);
91
+ const kmx_binary = builder.compile();
92
+ const vkcompiler = new LdmlKeyboardVisualKeyboardCompiler(this.callbacks);
93
+ const vk = vkcompiler.compile(source);
94
+ const writer = new KvkFileWriter();
95
+ const kvk_binary = writer.write(vk);
96
+ // Note: we could have a step of generating source files here
97
+ // KvksFileWriter()...
98
+ // const tlcompiler = new kmc.TouchLayoutCompiler();
99
+ // const tl = tlcompiler.compile(source);
100
+ // const tlwriter = new TouchLayoutFileWriter();
101
+ //KMW17.0: const kmwcompiler = new LdmlKeyboardKeymanWebCompiler(this.callbacks, compilerOptions);
102
+ //KMW17.0: const kmw_string = kmwcompiler.compile(inputFilename, source);
103
+ //KMW17.0: const encoder = new TextEncoder();
104
+ //KMW17.0: const kmw_binary = encoder.encode(kmw_string);
105
+ outputFilename = outputFilename ?? inputFilename.replace(/\.xml$/, '.kmx');
106
+ return {
107
+ artifacts: {
108
+ kmx: { data: kmx_binary, filename: outputFilename },
109
+ kvk: { data: kvk_binary, filename: outputFilename.replace(/\.kmx$/, '.kvk') },
110
+ //KMW17.0: js: { data: kmw_binary, filename: outputFilename.replace(/\.kmx$/, '.js') },
111
+ }
112
+ };
113
+ }
114
+ /**
115
+ * Write artifacts from a successful compile to disk, via callbacks methods.
116
+ * The artifacts written may include:
117
+ *
118
+ * - .kmx file - binary keyboard used by Keyman on desktop platforms
119
+ * - .kvk file - binary on screen keyboard used by Keyman on desktop platforms
120
+ * - .js file - Javascript keyboard for web and touch platforms
121
+ *
122
+ * @param artifacts - object containing artifact binary data to write out
123
+ * @returns true on success
124
+ */
125
+ async write(artifacts) {
126
+ if (artifacts.kmx) {
127
+ this.callbacks.fs.writeFileSync(artifacts.kmx.filename, artifacts.kmx.data);
128
+ }
129
+ if (artifacts.kvk) {
130
+ this.callbacks.fs.writeFileSync(artifacts.kvk.filename, artifacts.kvk.data);
131
+ }
132
+ if (artifacts.js) {
133
+ this.callbacks.fs.writeFileSync(artifacts.js.filename, artifacts.js.data);
134
+ }
135
+ return true;
136
+ }
137
+ /**
138
+ * @internal
139
+ * Construct or return a UnicodeSetParser, aka KmnCompiler
140
+ * @returns the held UnicodeSetParser
141
+ */
142
+ async getUsetParser() {
143
+ if (this.usetparser === undefined) {
144
+ // initialize
145
+ const compiler = new KmnCompiler();
146
+ const ok = await compiler.init(this.callbacks, null);
147
+ if (ok) {
148
+ this.usetparser = compiler;
149
+ }
150
+ else {
151
+ /* c8 ignore next 2 */
152
+ this.usetparser = null; // Store null on failure
153
+ }
154
+ }
155
+ return this.usetparser;
156
+ }
157
+ buildSections(source) {
158
+ return SECTION_COMPILERS.map(c => new c(source, this.callbacks));
159
+ }
160
+ /**
161
+ * @internal
162
+ * Loads a LDML Keyboard xml file and compiles into in-memory xml
163
+ * structures.
164
+ * @param filename - input filename, will use callback to load from disk
165
+ * @returns the source file, or null if invalid
166
+ */
167
+ load(filename) {
168
+ const reader = new LDMLKeyboardXMLSourceFileReader(this.options.readerOptions, this.callbacks);
169
+ // load the file from disk into a string
170
+ const data = this.callbacks.loadFile(filename);
171
+ if (!data) {
172
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to read XML file' }));
173
+ return null;
174
+ }
175
+ // parse (load) the string into an object tree
176
+ const source = reader.load(data);
177
+ if (!source) {
178
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to load XML file' }));
179
+ return null;
180
+ }
181
+ try {
182
+ // validate the object tree against the .xsd schema
183
+ if (!reader.validate(source)) {
184
+ return null;
185
+ }
186
+ }
187
+ catch (e) {
188
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: e.toString() }));
189
+ return null;
190
+ }
191
+ return source;
192
+ }
193
+ /**
194
+ * @internal
195
+ * Loads a LDML Keyboard test data xml file and compiles into in-memory xml
196
+ * structures.
197
+ * @param filename - input filename, will use callback to load from disk
198
+ * @returns the source file, or null if invalid
199
+ */
200
+ loadTestData(filename) {
201
+ const reader = new LDMLKeyboardXMLSourceFileReader(this.options.readerOptions, this.callbacks);
202
+ const data = this.callbacks.loadFile(filename);
203
+ if (!data) {
204
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to read XML file' }));
205
+ return null;
206
+ }
207
+ const source = reader.loadTestData(data);
208
+ /* c8 ignore next 4 */
209
+ if (!source) {
210
+ this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({ errorText: 'Unable to load XML file' }));
211
+ return null;
212
+ }
213
+ // TODO-LDML: The unboxed data doesn't match the schema anymore. Skipping validation, for now.
214
+ // try {
215
+ // if (!reader.validate(source)) {
216
+ // return null;
217
+ // }
218
+ // } catch(e) {
219
+ // this.callbacks.reportMessage(CompilerMessages.Error_InvalidFile({errorText: e.toString()}));
220
+ // return null;
221
+ // }
222
+ return source;
223
+ }
224
+ /**
225
+ * @internal
226
+ * Validates that the LDML keyboard source file and lints. Actually just
227
+ * compiles the keyboard and returns `true` if everything is good...
228
+ * @param source - in-memory representation of LDML keyboard xml file
229
+ * @returns true if the file validates
230
+ */
231
+ async validate(source) {
232
+ return !!(await this.compile(source, true));
233
+ }
234
+ /**
235
+ * @internal
236
+ * Transforms in-memory LDML keyboard xml file to an intermediate
237
+ * representation of a .kmx file.
238
+ * @param source - in-memory representation of LDML keyboard xml file
239
+ * @returns KMXPlusFile intermediate file
240
+ */
241
+ async compile(source, postValidate) {
242
+ const sections = this.buildSections(source);
243
+ let passed = true;
244
+ const kmx = new KMXPlusFile();
245
+ for (let section of sections) {
246
+ if (!section.validate()) {
247
+ // TODO-LDML: coverage
248
+ passed = false;
249
+ // We'll keep validating other sections anyway, so we get a full set of
250
+ // errors for the keyboard developer.
251
+ continue;
252
+ }
253
+ // clone
254
+ const globalSections = Object.assign({}, kmx.kmxplus);
255
+ // pre-initialize the usetparser
256
+ globalSections.usetparser = await this.getUsetParser();
257
+ const dependencies = section.dependencies;
258
+ let dependencyProblem = false;
259
+ Object.keys(constants.section).forEach((sectstr) => {
260
+ const sectid = constants.section[sectstr];
261
+ if (dependencies.has(sectid)) {
262
+ /* c8 ignore next 4 */
263
+ if (!kmx.kmxplus[sectid]) {
264
+ if (passed) {
265
+ // Internal error useful during section bring-up
266
+ throw new Error(`Internal error: section ${section.id} depends on uninitialized dependency ${sectid}, check ordering`);
267
+ }
268
+ else {
269
+ dependencyProblem = true;
270
+ return; // Already failed to validate, so no need for the layering message.
271
+ }
272
+ }
273
+ }
274
+ else {
275
+ // delete dependencies that aren't referenced
276
+ delete globalSections[sectid];
277
+ }
278
+ });
279
+ if (dependencyProblem && !passed) {
280
+ // Some layering problem, but we've already noted an error (!passed).
281
+ // Just skip this section.
282
+ continue;
283
+ }
284
+ const sect = section.compile(globalSections);
285
+ if (!sect) {
286
+ passed = false;
287
+ continue;
288
+ }
289
+ /* c8 ignore next 4 */
290
+ if (kmx.kmxplus[section.id]) {
291
+ // Internal error useful during section bring-up
292
+ throw new Error(`Internal error: section ${section.id} would be assigned twice`);
293
+ }
294
+ kmx.kmxplus[section.id] = sect;
295
+ }
296
+ // give all sections a chance to postValidate
297
+ if (postValidate) {
298
+ for (let section of sections) {
299
+ if (!section.postValidate(kmx.kmxplus[section.id])) {
300
+ passed = false;
301
+ }
302
+ }
303
+ }
304
+ return passed ? kmx : null;
305
+ }
306
+ }
307
+ //# sourceMappingURL=compiler.js.map