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