@keymanapp/kmc-kmn 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 (33) hide show
  1. package/build/src/compiler/compiler.d.ts.map +1 -1
  2. package/build/src/compiler/compiler.js +495 -487
  3. package/build/src/compiler/compiler.js.map +1 -1
  4. package/build/src/compiler/kmn-compiler-messages.d.ts +8 -0
  5. package/build/src/compiler/kmn-compiler-messages.d.ts.map +1 -1
  6. package/build/src/compiler/kmn-compiler-messages.js +497 -488
  7. package/build/src/compiler/kmn-compiler-messages.js.map +1 -1
  8. package/build/src/compiler/osk.js +86 -85
  9. package/build/src/compiler/osk.js.map +1 -1
  10. package/build/src/import/kmcmplib/wasm-host.js +3264 -3263
  11. package/build/src/import/kmcmplib/wasm-host.js.map +1 -1
  12. package/build/src/import/kmcmplib/wasm-host.wasm +0 -0
  13. package/build/src/kmw-compiler/compiler-globals.js +40 -39
  14. package/build/src/kmw-compiler/compiler-globals.js.map +1 -1
  15. package/build/src/kmw-compiler/constants.js +81 -80
  16. package/build/src/kmw-compiler/constants.js.map +1 -1
  17. package/build/src/kmw-compiler/javascript-strings.js +854 -853
  18. package/build/src/kmw-compiler/javascript-strings.js.map +1 -1
  19. package/build/src/kmw-compiler/keymanweb-key-codes.js +821 -820
  20. package/build/src/kmw-compiler/keymanweb-key-codes.js.map +1 -1
  21. package/build/src/kmw-compiler/kmw-compiler-messages.js +42 -41
  22. package/build/src/kmw-compiler/kmw-compiler-messages.js.map +1 -1
  23. package/build/src/kmw-compiler/kmw-compiler.js +549 -548
  24. package/build/src/kmw-compiler/kmw-compiler.js.map +1 -1
  25. package/build/src/kmw-compiler/util.js +249 -248
  26. package/build/src/kmw-compiler/util.js.map +1 -1
  27. package/build/src/kmw-compiler/validate-layout-file.js +278 -277
  28. package/build/src/kmw-compiler/validate-layout-file.js.map +1 -1
  29. package/build/src/kmw-compiler/visual-keyboard-compiler.js +121 -120
  30. package/build/src/kmw-compiler/visual-keyboard-compiler.js.map +1 -1
  31. package/build/src/main.js +12 -11
  32. package/build/src/main.js.map +1 -1
  33. package/package.json +5 -5
@@ -1,549 +1,550 @@
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]="f0c1024b-406f-5f29-aa9d-57d6db7088a4")}catch(e){}}();
2
- import { KMX, KvkFileReader, KmxFileReader } from "@keymanapp/common-types";
3
- import { ExpandSentinel, incxstr, xstrlen } from "./util.js";
4
- import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater, callbacks, FFix183_LadderLength, FCallFunctions, fk, IsKeyboardVersion17OrLater } from "./compiler-globals.js";
5
- import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js';
6
- import { KmwCompilerMessages } from "./kmw-compiler-messages.js";
7
- import { ValidateLayoutFile } from "./validate-layout-file.js";
8
- import { VisualKeyboardFromFile } from "./visual-keyboard-compiler.js";
9
- import { STORETYPE_DEBUG, STORETYPE_OPTION, STORETYPE_RESERVED } from "../compiler/compiler.js";
10
- function requote(s) {
11
- return "'" + s.replaceAll(/(['\\])/g, "\\$1") + "'";
12
- }
13
- export function RequotedString(s, RequoteSingleQuotes = false) {
14
- // TODO: use a JSON encode
15
- let i = 0;
16
- while (i < s.length) {
17
- if (s.charAt(i) == '"' || s.charAt(i) == '\\') {
18
- s = s.substring(0, i) + '\\' + s.substring(i);
19
- i++;
20
- }
21
- else if (s.charAt(i) == '\'' && RequoteSingleQuotes) {
22
- s = s.substring(0, i) + '\\' + s.substring(i);
23
- i++;
24
- }
25
- else if (s.charAt(i) == '\n') {
26
- s = s.substring(0, i) + ' ' + s.substring(i + 1);
27
- }
28
- else if (s.charAt(i) == '\r') {
29
- // Yes, `\r` gets converted to `\n`, per kmcomp pattern
30
- // in the future we may change this
31
- s = s.substring(0, i) + '\\n' + s.substring(i + 1);
32
- }
33
- i++;
34
- }
35
- return s;
36
- }
37
- export function WriteCompiledKeyboard(callbacks, kmnfile, keyboardData, kvkData, kmxResult, FDebug = false) {
38
- let opts = {
39
- shouldAddCompilerVersion: false,
40
- saveDebug: FDebug
41
- };
42
- const reader = new KmxFileReader();
43
- const keyboard = reader.read(keyboardData);
44
- setupGlobals(callbacks, opts, FDebug ? ' ' : '', FDebug ? '\r\n' : '', kmxResult, keyboard, kmnfile);
45
- const isStoreType = (index, type) => !!(kmxResult.extra.stores[index].storeType & type);
46
- const isDebugStore = (index) => isStoreType(index, STORETYPE_DEBUG);
47
- const isReservedStore = (index) => isStoreType(index, STORETYPE_RESERVED);
48
- const isOptionStore = (index) => isStoreType(index, STORETYPE_OPTION);
49
- const getStoreLine = (index) => kmxResult.extra.stores[index].line;
50
- let vMnemonic = 0;
51
- let sRTL = "", sHelp = "''", sHelpFile = "", sEmbedJSFilename = "", sEmbedCSSFilename = "";
52
- let sVisualKeyboardFilename = "", sFullName = "";
53
- let sBegin_NewContext = "", sBegin_PostKeystroke = "";
54
- let sLayoutFilename = "", sVKDictionary = "";
55
- let linecomment; // I3438
56
- let sModifierBitmask;
57
- let FOptionStores;
58
- let FKeyboardVersion = "1.0";
59
- let sHelpFileStoreIndex, sEmbedJSStoreIndex, sEmbedCSSStoreIndex;
60
- let result = "";
61
- // Locate the name of the keyboard
62
- for (let i = 0; i < keyboard.stores.length; i++) {
63
- const fsp = keyboard.stores[i];
64
- if (fsp.dwSystemID == KMX.KMXFile.TSS_NAME) {
65
- sFullName = fsp.dpString;
66
- }
67
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_KEYBOARDVERSION) { // I4155
68
- FKeyboardVersion = fsp.dpString;
69
- }
70
- else if (fsp.dpName == 'HelpFile' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPFILE) {
71
- sHelpFile = fsp.dpString;
72
- sHelpFileStoreIndex = i;
73
- }
74
- else if (fsp.dpName == 'Help' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPTEXT) {
75
- sHelp = '"' + RequotedString(fsp.dpString) + '"';
76
- }
77
- else if (fsp.dpName == 'VisualKeyboard' || fsp.dwSystemID == KMX.KMXFile.TSS_VISUALKEYBOARD) {
78
- sVisualKeyboardFilename = fsp.dpString;
79
- }
80
- else if (fsp.dpName == 'EmbedJS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDJS) {
81
- sEmbedJSFilename = fsp.dpString;
82
- sEmbedJSStoreIndex = i;
83
- }
84
- else if (fsp.dpName == 'EmbedCSS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDCSS) { // I4368
85
- sEmbedCSSFilename = fsp.dpString;
86
- sEmbedCSSStoreIndex = i;
87
- }
88
- else if (fsp.dpName == 'RTL' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_RTL) {
89
- sRTL = fsp.dpString == '1' ? FTabStop + 'this.KRTL=1;' + nl : ''; // I3681
90
- }
91
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_MNEMONIC) {
92
- vMnemonic = fsp.dpString == '1' ? 1 : 0;
93
- }
94
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_VKDICTIONARY) { // I3438
95
- sVKDictionary = fsp.dpString;
96
- }
97
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_LAYOUTFILE) { // I3483
98
- sLayoutFilename = fsp.dpString;
99
- }
100
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_NEWCONTEXT) {
101
- sBegin_NewContext = fsp.dpString;
102
- }
103
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_POSTKEYSTROKE) {
104
- sBegin_PostKeystroke = fsp.dpString;
105
- }
106
- }
107
- const sName = 'Keyboard_' + getKeymanWebCompiledNameFromFileName(kmnfile);
108
- if (sHelpFile != '') {
109
- sHelp = '';
110
- sHelpFile = callbacks.resolveFilename(kmnfile, sHelpFile);
111
- try {
112
- const data = callbacks.loadFile(sHelpFile);
113
- let html = new TextDecoder().decode(data);
114
- if (!html.endsWith('\n'))
115
- html += '\n'; // CompileKeymanWeb.pas adds a new line at EOF
116
- sHelp = html.replace(/\r/g, '').replace(/\n/g, ' ');
117
- sHelp = requote(sHelp);
118
- }
119
- catch (e) {
120
- callbacks.reportMessage(KmwCompilerMessages.Warn_HelpFileMissing({ line: getStoreLine(sHelpFileStoreIndex), helpFilename: sHelpFile, e }));
121
- sHelp = '';
122
- }
123
- }
124
- let sEmbedJS = '';
125
- if (sEmbedJSFilename != '') {
126
- sEmbedJSFilename = callbacks.resolveFilename(kmnfile, sEmbedJSFilename);
127
- try {
128
- const data = callbacks.loadFile(sEmbedJSFilename);
129
- sEmbedJS = new TextDecoder().decode(data);
130
- }
131
- catch (e) {
132
- callbacks.reportMessage(KmwCompilerMessages.Warn_EmbedJsFileMissing({ line: getStoreLine(sEmbedJSStoreIndex), jsFilename: sEmbedJSFilename, e }));
133
- sEmbedJS = '';
134
- }
135
- }
136
- let sEmbedCSS = '';
137
- if (sEmbedCSSFilename != '') { // I4368
138
- sEmbedCSSFilename = callbacks.resolveFilename(kmnfile, sEmbedCSSFilename);
139
- try {
140
- const data = callbacks.loadFile(sEmbedCSSFilename);
141
- sEmbedCSS = new TextDecoder().decode(data);
142
- if (sEmbedCSS != '' && !sEmbedCSS.endsWith('\r\n'))
143
- sEmbedCSS += '\r\n'; // match CompileKeymanWeb.pas
144
- }
145
- catch (e) {
146
- // TODO(lowpri): rename error constant to Warn_EmbedFileMissing
147
- callbacks.reportMessage(KmwCompilerMessages.Warn_EmbedJsFileMissing({ line: getStoreLine(sEmbedCSSStoreIndex), jsFilename: sEmbedCSSFilename, e }));
148
- sEmbedCSS = '';
149
- }
150
- }
151
- let sLayoutFile = '';
152
- if (sLayoutFilename != '') { // I3483
153
- sLayoutFilename = callbacks.resolveFilename(kmnfile, sLayoutFilename);
154
- let result = ValidateLayoutFile(keyboard, options.saveDebug, sLayoutFilename, sVKDictionary, kmxResult.displayMap);
155
- if (!result) {
156
- sLayoutFile = '';
157
- return null;
158
- }
159
- else if (!result.result) {
160
- sLayoutFile = '';
161
- callbacks.reportMessage(KmwCompilerMessages.Error_InvalidTouchLayoutFile({ filename: sLayoutFilename }));
162
- return null;
163
- }
164
- else {
165
- sLayoutFile = result.output;
166
- }
167
- }
168
- // Default to hide underlying layout characters. This is overridden by touch
169
- // layout platform.displayUnderlying property or, if that is not present for
170
- // the given platform, by the OSK property.
171
- let fDisplayUnderlying = false;
172
- let sVisualKeyboard = 'null'; // 'null' as a string is correct
173
- if (sVisualKeyboardFilename != '') {
174
- const reader = new KvkFileReader();
175
- const kvk = reader.read(kvkData);
176
- fDisplayUnderlying = !!(kvk.header.flags & 2 /* KvkFile.BUILDER_KVK_HEADER_FLAGS.kvkhDisplayUnderlying */);
177
- sVisualKeyboard = VisualKeyboardFromFile(kvk, options.saveDebug);
178
- }
179
- const fMnemonic = vMnemonic == 1;
180
- sModifierBitmask = GetKeyboardModifierBitmask(keyboard, fMnemonic);
181
- result +=
182
- `${JavaScript_SetupProlog()}${nl}` +
183
- `KeymanWeb.KR(new ${sName}());${nl}` +
184
- `${JavaScript_SetupEpilog()}${nl}` +
185
- `function ${sName}()${nl}` +
186
- `{${nl}` +
187
- `${FTabStop}${JavaScript_SetupDebug()}${nl}` +
188
- // Following line caches the Keyman major version
189
- `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` +
190
- `${FTabStop}this.KI="${sName}";${nl}` +
191
- `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}` +
192
- `${FTabStop}this.KMINVER="${(keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MAJOR) >> 8}.${keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MINOR}";${nl}` +
193
- `${FTabStop}this.KV=${sVisualKeyboard};${nl}` +
194
- `${FTabStop}this.KDU=${fDisplayUnderlying ? '1' : '0'};${nl}` +
195
- `${FTabStop}this.KH=${sHelp};${nl}` +
196
- `${FTabStop}this.KM=${vMnemonic};${nl}` +
197
- `${FTabStop}this.KBVER="${FKeyboardVersion}";${nl}` + // I4155
198
- `${FTabStop}this.KMBM=${sModifierBitmask};${nl}` +
199
- `${sRTL}`; // I3681
200
- if (HasSupplementaryPlaneChars()) {
201
- result += `${FTabStop}this.KS=1;${nl}`;
202
- }
203
- if (sVKDictionary != '') { // I3438
204
- result += `${FTabStop}this.KVKD="${RequotedString(sVKDictionary)}";${nl}`; // I3681
205
- }
206
- if (sLayoutFile != '') { // I3483
207
- result += `${FTabStop}this.KVKL=${sLayoutFile};${nl}`; // I3681
208
- }
209
- if (sEmbedCSS != '') { // I4368
210
- result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`;
211
- }
212
- // Write the stores out
213
- FOptionStores = '';
214
- for (let i = 0; i < keyboard.stores.length; i++) {
215
- let fsp = keyboard.stores[i];
216
- // I3438 - Save all system stores to the keyboard, for now // I3684
217
- if (!isDebugStore(i)) {
218
- if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPARISON) {
219
- result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)};${nl}`;
220
- }
221
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPILEDVERSION) {
222
- result += `${FTabStop}this.KVER=${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)};${nl}`;
223
- }
224
- else if (isOptionStore(i) && !isReservedStore(i)) {
225
- result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i, fsp.dpName, true)}",` +
226
- `${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)});${nl}`;
227
- if (FOptionStores != '') {
228
- FOptionStores += ',';
229
- }
230
- FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}'`;
231
- }
232
- else if (fsp.dwSystemID == KMX.KMXFile.TSS_NONE /* aka !isReservedStore(i) */) {
233
- result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)};${nl}`; // I3681
234
- }
235
- }
236
- }
237
- result += `${FTabStop}this.KVS=[${FOptionStores}];${nl}`;
238
- // Write the groups out
239
- // I853 - begin unicode missing causes crash
240
- if (keyboard.startGroup.unicode == 0xFFFFFFFF) {
241
- callbacks.reportMessage(KmwCompilerMessages.Error_InvalidBegin());
242
- return null;
243
- }
244
- result += WriteBeginStatement(keyboard, 'gs', keyboard.startGroup.unicode);
245
- let rec = ExpandSentinel(keyboard, sBegin_NewContext, 0);
246
- if (rec.Code == KMX.KMXFile.CODE_USE) {
247
- result += WriteBeginStatement(keyboard, 'gn', rec.Use.GroupIndex);
248
- }
249
- rec = ExpandSentinel(keyboard, sBegin_PostKeystroke, 0);
250
- if (rec.Code == KMX.KMXFile.CODE_USE) {
251
- result += WriteBeginStatement(keyboard, 'gpk', rec.Use.GroupIndex);
252
- }
253
- let fgp = keyboard.groups[keyboard.startGroup.unicode];
254
- result +=
255
- `${FTabStop}this.gs=function(t,e) {${nl}` +
256
- `${FTabStop + FTabStop}return this.g${JavaScript_Name(keyboard.startGroup.unicode, fgp.dpName)}(t,e);${nl}` +
257
- `${FTabStop}};${nl}`; // I3681
258
- for (let i = 0; i < keyboard.groups.length; i++) { // I1964
259
- let fgp = keyboard.groups[i];
260
- /*
261
- Note on `r` and `m` variables in a group function:
262
-
263
- `m` can have one of three values:
264
- 0: no rule from this group was matched
265
- 1: a rule from this group was matched and did not include a `use`
266
- statement
267
- 2: a rule from this group matched and did include a `use` statement
268
- (#5440)
269
-
270
- `m` is only used within a rule group to control the firing of the
271
- `match` and `nomatch` rules.
272
-
273
- `r` can have one of two values:
274
- 0: no rule from the final group matched (even if a rule from an
275
- higher-level group did)
276
- 1: a rule from the final group did match;
277
-
278
- `r` serves as the rule group's return value and is forwarded
279
- recursively, best serving as a flag for whether or not default
280
- output for a key should be emitted (0 means yes, emit the
281
- default character output for that key).
282
- */
283
- result +=
284
- `${FTabStop}this.g${JavaScript_Name(i, fgp.dpName)}=function(t,e) {${nl}` +
285
- `${FTabStop + FTabStop}var k=KeymanWeb,r=${fgp.fUsingKeys ? 0 : 1},m=0;${nl}`; //I1959
286
- // fkp := fgp.dpKeyArray;
287
- let HasRules = false;
288
- if (FFix183_LadderLength != 0) {
289
- result += JavaScript_Rules(keyboard, fMnemonic, fgp);
290
- }
291
- else {
292
- for (let j = 0; j < fgp.keys.length; j++) { // I1964
293
- let fkp = fgp.keys[j];
294
- if (!RuleIsExcludedByPlatform(keyboard, fkp)) {
295
- result += FTabStop + FTabStop; // I3681
296
- if (HasRules) {
297
- result += 'else ';
298
- }
299
- HasRules = true;
300
- if (fgp.fUsingKeys) {
301
- result += `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})`;
302
- }
303
- if (xstrlen(fkp.dpContext) > 0) {
304
- result += fgp.fUsingKeys ? '&&' : 'if(';
305
- result += JavaScript_ContextMatch(keyboard, fkp, fkp.dpContext);
306
- }
307
- else if (!fgp.fUsingKeys) {
308
- result += 'if(1';
309
- }
310
- linecomment = (fkp.Line > 0 && FDebug) ? ` // Line ${fkp.Line}` : '';
311
- result +=
312
- `) {${linecomment}${nl}` +
313
- FTabStop + FTabStop + FTabStop;
314
- if (fgp.fUsingKeys) { // I1959
315
- result += 'r=m=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681
316
- }
317
- else {
318
- result += 'm=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681
319
- }
320
- result += `${nl}${FTabStop}${FTabStop}}${nl}`; // I3681
321
- }
322
- }
323
- }
324
- if (fgp.dpMatch) {
325
- result +=
326
- `${FTabStop + FTabStop}if(m==1) {${nl}` +
327
- `${FTabStop + FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}` +
328
- `${FTabStop + FTabStop}}${nl}`;
329
- }
330
- if (fgp.dpNoMatch) {
331
- if (fgp.fUsingKeys) { // I1382 - fixup m=1 to m=g()
332
- result +=
333
- `${FTabStop + FTabStop}if(!m&&k.KIK(e)) {${nl}` +
334
- `${FTabStop + FTabStop + FTabStop}r=1;${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}` +
335
- `${FTabStop + FTabStop}}${nl}`; // I1959. part 2, I2224 // I3681
336
- }
337
- else {
338
- result +=
339
- `${FTabStop + FTabStop}if(!m) {${nl}` +
340
- `${FTabStop + FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}` +
341
- // TODO: add FTabStop to line above, once we have 100% identical match
342
- // to legacy compiler, but because legacy compiler missed this
343
- // tabstop we'll leave it out here for now
344
- `${FTabStop + FTabStop}}${nl}`;
345
- }
346
- }
347
- result +=
348
- `${FTabStop + FTabStop}return r;${nl}` +
349
- `${FTabStop}};${nl}`;
350
- }
351
- for (let n = 0; n < FCallFunctions.length; n++) {
352
- const s = callbacks.resolveFilename(kmnfile, FCallFunctions[n] + '.call_js');
353
- if (callbacks.fs.existsSync(s)) {
354
- const data = new TextDecoder().decode(callbacks.loadFile(s));
355
- result += `${FTabStop}this.c${n}=function(t,e){${data.trim()}};${nl}`;
356
- }
357
- else {
358
- result += `${FTabStop}this.c${n}=function(t,e){alert("call(${FCallFunctions[n]}) not defined");};${nl}`;
359
- }
360
- }
361
- result += sEmbedJS + '}' + nl; // I3681
362
- return result;
363
- }
364
- ///
365
- /// Determine the modifiers used in the target keyboard and return a bitmask
366
- /// representing them, or an number value when not in debug mode
367
- ///
368
- /// @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 */'
369
- ///
370
- function GetKeyboardModifierBitmask(keyboard, fMnemonic) {
371
- let bitMask = 0;
372
- for (let gp of keyboard.groups) {
373
- if (gp.fUsingKeys) {
374
- for (let kp of gp.keys) {
375
- if (!RuleIsExcludedByPlatform(keyboard, kp)) {
376
- bitMask |= JavaScript_Shift(kp, fMnemonic);
377
- }
378
- }
379
- }
380
- }
381
- if ((bitMask & KMX.KMXFile.MASK_MODIFIER_CHIRAL) && (bitMask & KMX.KMXFile.MASK_MODIFIER_NONCHIRAL)) {
382
- callbacks.reportMessage(KmwCompilerMessages.Warn_DontMixChiralAndNonChiralModifiers());
383
- }
384
- if (options.saveDebug) {
385
- return FormatModifierAsBitflags(bitMask & KMX.KMXFile.MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY
386
- }
387
- return '0x' + (bitMask & KMX.KMXFile.MASK_KEYS).toString(16).toUpperCase();
388
- }
389
- ///
390
- /// If debug mode, then returns Javascript code necessary for
391
- /// accessing constants in the compiled keyboard
392
- ///
393
- /// @return string of JavaScript code
394
- ///
395
- function JavaScript_SetupDebug() {
396
- if (IsKeyboardVersion10OrLater()) {
397
- if (options.saveDebug) {
398
- if (IsKeyboardVersion17OrLater()) {
399
- return 'var modCodes = KeymanWeb.Codes.modifierCodes;' + nl +
400
- FTabStop + 'var keyCodes = KeymanWeb.Codes.keyCodes;' + nl;
401
- }
402
- else {
403
- return 'var modCodes = keyman.osk.modifierCodes;' + nl +
404
- FTabStop + 'var keyCodes = keyman.osk.keyCodes;' + nl;
405
- }
406
- }
407
- }
408
- return '';
409
- }
410
- function JavaScript_SetupProlog() {
411
- if (IsKeyboardVersion10OrLater()) {
412
- return 'if(typeof keyman === \'undefined\') {' + nl +
413
- FTabStop + 'console.log(\'Keyboard requires KeymanWeb 10.0 or later\');' + nl +
414
- FTabStop + 'if(typeof tavultesoft !== \'undefined\') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");' + nl +
415
- '} else {';
416
- }
417
- return '';
418
- }
419
- function JavaScript_SetupEpilog() {
420
- if (IsKeyboardVersion10OrLater()) {
421
- return '}';
422
- }
423
- return '';
424
- }
425
- function HasSupplementaryPlaneChars() {
426
- const suppChar = /[\uD800-\uDBFF][\uDC00-\uDFFF]/;
427
- for (let sp of fk.stores) {
428
- if (suppChar.test(sp.dpString)) {
429
- return true;
430
- }
431
- }
432
- for (let gp of fk.groups) {
433
- for (let kp of gp.keys) {
434
- if (suppChar.test(kp.dpContext) || suppChar.test(kp.dpOutput)) {
435
- return true;
436
- }
437
- }
438
- if (suppChar.test(gp.dpMatch) || suppChar.test(gp.dpNoMatch)) {
439
- return true;
440
- }
441
- }
442
- return false;
443
- }
444
- export function RuleIsExcludedByPlatform(keyboard, fkp) {
445
- if (fkp.dpContext == null || fkp.dpContext == '') {
446
- return false;
447
- }
448
- let x = 0;
449
- while (x < fkp.dpContext.length) {
450
- let rec = ExpandSentinel(keyboard, fkp.dpContext, x);
451
- if (rec.IsSentinel &&
452
- (rec.Code == KMX.KMXFile.CODE_IFSYSTEMSTORE) &&
453
- (rec.IfSystemStore.dwSystemID == KMX.KMXFile.TSS_PLATFORM) &&
454
- rec.IfSystemStore.Store.dpString.includes('native')) {
455
- if (rec.IfSystemStore.Store.dpString.match(/windows|desktop|macosx|linux/)) {
456
- return true;
457
- }
458
- }
459
- x = incxstr(fkp.dpContext, x);
460
- }
461
- return false;
462
- }
463
- function WriteBeginStatement(keyboard, name, groupIndex) {
464
- const fgp = keyboard.groups[groupIndex];
465
- return `${FTabStop}this.${name}=function(t,e) {${nl}` +
466
- `${FTabStop + FTabStop}return this.g${JavaScript_Name(groupIndex, fgp.dpName)}(t,e);${nl}` +
467
- `${FTabStop}};${nl}`;
468
- }
469
- /**
470
- * Converts a modifier bit mask integer into its component bit flags
471
- *
472
- * @param FBitMask A KMX modifier bitmask value
473
- *
474
- * @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 ./'
475
- **/
476
- export function FormatModifierAsBitflags(FBitMask) {
477
- const mask = [
478
- 'LCTRL',
479
- 'RCTRL',
480
- 'LALT',
481
- 'RALT',
482
- 'SHIFT',
483
- 'CTRL',
484
- 'ALT',
485
- '???',
486
- 'CAPS',
487
- 'NO_CAPS',
488
- 'NUM_LOCK',
489
- 'NO_NUM_LOCK',
490
- 'SCROLL_LOCK',
491
- 'NO_SCROLL_LOCK',
492
- 'VIRTUAL_KEY' // 0X4000
493
- ];
494
- let i;
495
- let result = '';
496
- //TODO: We need to think about mnemonic layouts which are incompletely supported at present
497
- //tavultesoft.keymanweb.osk.
498
- if (IsKeyboardVersion10OrLater()) {
499
- // This depends on flags defined in KeymanWeb 10.0
500
- result = '';
501
- for (i = 0; i < mask.length; i++) {
502
- if (FBitMask & (1 << i)) {
503
- if (result != '')
504
- result += ' | ';
505
- result += 'modCodes.' + mask[i];
506
- }
507
- }
508
- if (result == '') {
509
- result = '0';
510
- }
511
- result += ' /* 0x' + zeroPadHex(FBitMask, 4) + ' */';
512
- }
513
- else {
514
- result = '0x' + zeroPadHex(FBitMask, 4);
515
- }
516
- return result;
517
- }
518
- function cleanKeyboardID(name) {
519
- name = name.toLowerCase();
520
- if (name.length == 0) {
521
- return name;
522
- }
523
- if (name[0].match(/\d/)) {
524
- name = '_' + name;
525
- }
526
- let result = '';
527
- for (let i = 0; i < name.length; i++) {
528
- if (!name[i].match(/[a-z0-9_]/)) {
529
- result += '_';
530
- }
531
- else {
532
- result += name[i];
533
- }
534
- }
535
- return result;
536
- }
537
- function getKeymanWebCompiledNameFromFileName(filename) {
538
- let m = /([^/\\]+)$/.exec(filename);
539
- if (!m) {
540
- return null;
541
- }
542
- m = /^(.+?)(\.[^.]+)?$/.exec(m[1]);
543
- if (!m) {
544
- return null;
545
- }
546
- return cleanKeyboardID(m[1]);
547
- }
548
- //# debugId=f0c1024b-406f-5f29-aa9d-57d6db7088a4
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]="bb0f70f6-191e-5f90-80c7-09d068e49b8a")}catch(e){}}();
3
+ import { KMX, KvkFileReader, KmxFileReader } from "@keymanapp/common-types";
4
+ import { ExpandSentinel, incxstr, xstrlen } from "./util.js";
5
+ import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater, callbacks, FFix183_LadderLength, FCallFunctions, fk, IsKeyboardVersion17OrLater } from "./compiler-globals.js";
6
+ import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js';
7
+ import { KmwCompilerMessages } from "./kmw-compiler-messages.js";
8
+ import { ValidateLayoutFile } from "./validate-layout-file.js";
9
+ import { VisualKeyboardFromFile } from "./visual-keyboard-compiler.js";
10
+ import { STORETYPE_DEBUG, STORETYPE_OPTION, STORETYPE_RESERVED } from "../compiler/compiler.js";
11
+ function requote(s) {
12
+ return "'" + s.replaceAll(/(['\\])/g, "\\$1") + "'";
13
+ }
14
+ export function RequotedString(s, RequoteSingleQuotes = false) {
15
+ // TODO: use a JSON encode
16
+ let i = 0;
17
+ while (i < s.length) {
18
+ if (s.charAt(i) == '"' || s.charAt(i) == '\\') {
19
+ s = s.substring(0, i) + '\\' + s.substring(i);
20
+ i++;
21
+ }
22
+ else if (s.charAt(i) == '\'' && RequoteSingleQuotes) {
23
+ s = s.substring(0, i) + '\\' + s.substring(i);
24
+ i++;
25
+ }
26
+ else if (s.charAt(i) == '\n') {
27
+ s = s.substring(0, i) + ' ' + s.substring(i + 1);
28
+ }
29
+ else if (s.charAt(i) == '\r') {
30
+ // Yes, `\r` gets converted to `\n`, per kmcomp pattern
31
+ // in the future we may change this
32
+ s = s.substring(0, i) + '\\n' + s.substring(i + 1);
33
+ }
34
+ i++;
35
+ }
36
+ return s;
37
+ }
38
+ export function WriteCompiledKeyboard(callbacks, kmnfile, keyboardData, kvkData, kmxResult, FDebug = false) {
39
+ let opts = {
40
+ shouldAddCompilerVersion: false,
41
+ saveDebug: FDebug
42
+ };
43
+ const reader = new KmxFileReader();
44
+ const keyboard = reader.read(keyboardData);
45
+ setupGlobals(callbacks, opts, FDebug ? ' ' : '', FDebug ? '\r\n' : '', kmxResult, keyboard, kmnfile);
46
+ const isStoreType = (index, type) => !!(kmxResult.extra.stores[index].storeType & type);
47
+ const isDebugStore = (index) => isStoreType(index, STORETYPE_DEBUG);
48
+ const isReservedStore = (index) => isStoreType(index, STORETYPE_RESERVED);
49
+ const isOptionStore = (index) => isStoreType(index, STORETYPE_OPTION);
50
+ const getStoreLine = (index) => kmxResult.extra.stores[index].line;
51
+ let vMnemonic = 0;
52
+ let sRTL = "", sHelp = "''", sHelpFile = "", sEmbedJSFilename = "", sEmbedCSSFilename = "";
53
+ let sVisualKeyboardFilename = "", sFullName = "";
54
+ let sBegin_NewContext = "", sBegin_PostKeystroke = "";
55
+ let sLayoutFilename = "", sVKDictionary = "";
56
+ let linecomment; // I3438
57
+ let sModifierBitmask;
58
+ let FOptionStores;
59
+ let FKeyboardVersion = "1.0";
60
+ let sHelpFileStoreIndex, sEmbedJSStoreIndex, sEmbedCSSStoreIndex;
61
+ let result = "";
62
+ // Locate the name of the keyboard
63
+ for (let i = 0; i < keyboard.stores.length; i++) {
64
+ const fsp = keyboard.stores[i];
65
+ if (fsp.dwSystemID == KMX.KMXFile.TSS_NAME) {
66
+ sFullName = fsp.dpString;
67
+ }
68
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_KEYBOARDVERSION) { // I4155
69
+ FKeyboardVersion = fsp.dpString;
70
+ }
71
+ else if (fsp.dpName == 'HelpFile' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPFILE) {
72
+ sHelpFile = fsp.dpString;
73
+ sHelpFileStoreIndex = i;
74
+ }
75
+ else if (fsp.dpName == 'Help' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPTEXT) {
76
+ sHelp = '"' + RequotedString(fsp.dpString) + '"';
77
+ }
78
+ else if (fsp.dpName == 'VisualKeyboard' || fsp.dwSystemID == KMX.KMXFile.TSS_VISUALKEYBOARD) {
79
+ sVisualKeyboardFilename = fsp.dpString;
80
+ }
81
+ else if (fsp.dpName == 'EmbedJS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDJS) {
82
+ sEmbedJSFilename = fsp.dpString;
83
+ sEmbedJSStoreIndex = i;
84
+ }
85
+ else if (fsp.dpName == 'EmbedCSS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDCSS) { // I4368
86
+ sEmbedCSSFilename = fsp.dpString;
87
+ sEmbedCSSStoreIndex = i;
88
+ }
89
+ else if (fsp.dpName == 'RTL' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_RTL) {
90
+ sRTL = fsp.dpString == '1' ? FTabStop + 'this.KRTL=1;' + nl : ''; // I3681
91
+ }
92
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_MNEMONIC) {
93
+ vMnemonic = fsp.dpString == '1' ? 1 : 0;
94
+ }
95
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_VKDICTIONARY) { // I3438
96
+ sVKDictionary = fsp.dpString;
97
+ }
98
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_LAYOUTFILE) { // I3483
99
+ sLayoutFilename = fsp.dpString;
100
+ }
101
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_NEWCONTEXT) {
102
+ sBegin_NewContext = fsp.dpString;
103
+ }
104
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_POSTKEYSTROKE) {
105
+ sBegin_PostKeystroke = fsp.dpString;
106
+ }
107
+ }
108
+ const sName = 'Keyboard_' + getKeymanWebCompiledNameFromFileName(kmnfile);
109
+ if (sHelpFile != '') {
110
+ sHelp = '';
111
+ sHelpFile = callbacks.resolveFilename(kmnfile, sHelpFile);
112
+ try {
113
+ const data = callbacks.loadFile(sHelpFile);
114
+ let html = new TextDecoder().decode(data);
115
+ if (!html.endsWith('\n'))
116
+ html += '\n'; // CompileKeymanWeb.pas adds a new line at EOF
117
+ sHelp = html.replace(/\r/g, '').replace(/\n/g, ' ');
118
+ sHelp = requote(sHelp);
119
+ }
120
+ catch (e) {
121
+ callbacks.reportMessage(KmwCompilerMessages.Warn_HelpFileMissing({ line: getStoreLine(sHelpFileStoreIndex), helpFilename: sHelpFile, e }));
122
+ sHelp = '';
123
+ }
124
+ }
125
+ let sEmbedJS = '';
126
+ if (sEmbedJSFilename != '') {
127
+ sEmbedJSFilename = callbacks.resolveFilename(kmnfile, sEmbedJSFilename);
128
+ try {
129
+ const data = callbacks.loadFile(sEmbedJSFilename);
130
+ sEmbedJS = new TextDecoder().decode(data);
131
+ }
132
+ catch (e) {
133
+ callbacks.reportMessage(KmwCompilerMessages.Warn_EmbedJsFileMissing({ line: getStoreLine(sEmbedJSStoreIndex), jsFilename: sEmbedJSFilename, e }));
134
+ sEmbedJS = '';
135
+ }
136
+ }
137
+ let sEmbedCSS = '';
138
+ if (sEmbedCSSFilename != '') { // I4368
139
+ sEmbedCSSFilename = callbacks.resolveFilename(kmnfile, sEmbedCSSFilename);
140
+ try {
141
+ const data = callbacks.loadFile(sEmbedCSSFilename);
142
+ sEmbedCSS = new TextDecoder().decode(data);
143
+ if (sEmbedCSS != '' && !sEmbedCSS.endsWith('\r\n'))
144
+ sEmbedCSS += '\r\n'; // match CompileKeymanWeb.pas
145
+ }
146
+ catch (e) {
147
+ // TODO(lowpri): rename error constant to Warn_EmbedFileMissing
148
+ callbacks.reportMessage(KmwCompilerMessages.Warn_EmbedJsFileMissing({ line: getStoreLine(sEmbedCSSStoreIndex), jsFilename: sEmbedCSSFilename, e }));
149
+ sEmbedCSS = '';
150
+ }
151
+ }
152
+ let sLayoutFile = '';
153
+ if (sLayoutFilename != '') { // I3483
154
+ sLayoutFilename = callbacks.resolveFilename(kmnfile, sLayoutFilename);
155
+ let result = ValidateLayoutFile(keyboard, options.saveDebug, sLayoutFilename, sVKDictionary, kmxResult.displayMap);
156
+ if (!result) {
157
+ sLayoutFile = '';
158
+ return null;
159
+ }
160
+ else if (!result.result) {
161
+ sLayoutFile = '';
162
+ callbacks.reportMessage(KmwCompilerMessages.Error_InvalidTouchLayoutFile({ filename: sLayoutFilename }));
163
+ return null;
164
+ }
165
+ else {
166
+ sLayoutFile = result.output;
167
+ }
168
+ }
169
+ // Default to hide underlying layout characters. This is overridden by touch
170
+ // layout platform.displayUnderlying property or, if that is not present for
171
+ // the given platform, by the OSK property.
172
+ let fDisplayUnderlying = false;
173
+ let sVisualKeyboard = 'null'; // 'null' as a string is correct
174
+ if (sVisualKeyboardFilename != '') {
175
+ const reader = new KvkFileReader();
176
+ const kvk = reader.read(kvkData);
177
+ fDisplayUnderlying = !!(kvk.header.flags & 2 /* KvkFile.BUILDER_KVK_HEADER_FLAGS.kvkhDisplayUnderlying */);
178
+ sVisualKeyboard = VisualKeyboardFromFile(kvk, options.saveDebug);
179
+ }
180
+ const fMnemonic = vMnemonic == 1;
181
+ sModifierBitmask = GetKeyboardModifierBitmask(keyboard, fMnemonic);
182
+ result +=
183
+ `${JavaScript_SetupProlog()}${nl}` +
184
+ `KeymanWeb.KR(new ${sName}());${nl}` +
185
+ `${JavaScript_SetupEpilog()}${nl}` +
186
+ `function ${sName}()${nl}` +
187
+ `{${nl}` +
188
+ `${FTabStop}${JavaScript_SetupDebug()}${nl}` +
189
+ // Following line caches the Keyman major version
190
+ `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` +
191
+ `${FTabStop}this.KI="${sName}";${nl}` +
192
+ `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}` +
193
+ `${FTabStop}this.KMINVER="${(keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MAJOR) >> 8}.${keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MINOR}";${nl}` +
194
+ `${FTabStop}this.KV=${sVisualKeyboard};${nl}` +
195
+ `${FTabStop}this.KDU=${fDisplayUnderlying ? '1' : '0'};${nl}` +
196
+ `${FTabStop}this.KH=${sHelp};${nl}` +
197
+ `${FTabStop}this.KM=${vMnemonic};${nl}` +
198
+ `${FTabStop}this.KBVER="${FKeyboardVersion}";${nl}` + // I4155
199
+ `${FTabStop}this.KMBM=${sModifierBitmask};${nl}` +
200
+ `${sRTL}`; // I3681
201
+ if (HasSupplementaryPlaneChars()) {
202
+ result += `${FTabStop}this.KS=1;${nl}`;
203
+ }
204
+ if (sVKDictionary != '') { // I3438
205
+ result += `${FTabStop}this.KVKD="${RequotedString(sVKDictionary)}";${nl}`; // I3681
206
+ }
207
+ if (sLayoutFile != '') { // I3483
208
+ result += `${FTabStop}this.KVKL=${sLayoutFile};${nl}`; // I3681
209
+ }
210
+ if (sEmbedCSS != '') { // I4368
211
+ result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`;
212
+ }
213
+ // Write the stores out
214
+ FOptionStores = '';
215
+ for (let i = 0; i < keyboard.stores.length; i++) {
216
+ let fsp = keyboard.stores[i];
217
+ // I3438 - Save all system stores to the keyboard, for now // I3684
218
+ if (!isDebugStore(i)) {
219
+ if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPARISON) {
220
+ result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)};${nl}`;
221
+ }
222
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPILEDVERSION) {
223
+ result += `${FTabStop}this.KVER=${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)};${nl}`;
224
+ }
225
+ else if (isOptionStore(i) && !isReservedStore(i)) {
226
+ result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i, fsp.dpName, true)}",` +
227
+ `${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)});${nl}`;
228
+ if (FOptionStores != '') {
229
+ FOptionStores += ',';
230
+ }
231
+ FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}'`;
232
+ }
233
+ else if (fsp.dwSystemID == KMX.KMXFile.TSS_NONE /* aka !isReservedStore(i) */) {
234
+ result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, getStoreLine(i), fsp.dpString)};${nl}`; // I3681
235
+ }
236
+ }
237
+ }
238
+ result += `${FTabStop}this.KVS=[${FOptionStores}];${nl}`;
239
+ // Write the groups out
240
+ // I853 - begin unicode missing causes crash
241
+ if (keyboard.startGroup.unicode == 0xFFFFFFFF) {
242
+ callbacks.reportMessage(KmwCompilerMessages.Error_InvalidBegin());
243
+ return null;
244
+ }
245
+ result += WriteBeginStatement(keyboard, 'gs', keyboard.startGroup.unicode);
246
+ let rec = ExpandSentinel(keyboard, sBegin_NewContext, 0);
247
+ if (rec.Code == KMX.KMXFile.CODE_USE) {
248
+ result += WriteBeginStatement(keyboard, 'gn', rec.Use.GroupIndex);
249
+ }
250
+ rec = ExpandSentinel(keyboard, sBegin_PostKeystroke, 0);
251
+ if (rec.Code == KMX.KMXFile.CODE_USE) {
252
+ result += WriteBeginStatement(keyboard, 'gpk', rec.Use.GroupIndex);
253
+ }
254
+ let fgp = keyboard.groups[keyboard.startGroup.unicode];
255
+ result +=
256
+ `${FTabStop}this.gs=function(t,e) {${nl}` +
257
+ `${FTabStop + FTabStop}return this.g${JavaScript_Name(keyboard.startGroup.unicode, fgp.dpName)}(t,e);${nl}` +
258
+ `${FTabStop}};${nl}`; // I3681
259
+ for (let i = 0; i < keyboard.groups.length; i++) { // I1964
260
+ let fgp = keyboard.groups[i];
261
+ /*
262
+ Note on `r` and `m` variables in a group function:
263
+
264
+ `m` can have one of three values:
265
+ 0: no rule from this group was matched
266
+ 1: a rule from this group was matched and did not include a `use`
267
+ statement
268
+ 2: a rule from this group matched and did include a `use` statement
269
+ (#5440)
270
+
271
+ `m` is only used within a rule group to control the firing of the
272
+ `match` and `nomatch` rules.
273
+
274
+ `r` can have one of two values:
275
+ 0: no rule from the final group matched (even if a rule from an
276
+ higher-level group did)
277
+ 1: a rule from the final group did match;
278
+
279
+ `r` serves as the rule group's return value and is forwarded
280
+ recursively, best serving as a flag for whether or not default
281
+ output for a key should be emitted (0 means yes, emit the
282
+ default character output for that key).
283
+ */
284
+ result +=
285
+ `${FTabStop}this.g${JavaScript_Name(i, fgp.dpName)}=function(t,e) {${nl}` +
286
+ `${FTabStop + FTabStop}var k=KeymanWeb,r=${fgp.fUsingKeys ? 0 : 1},m=0;${nl}`; //I1959
287
+ // fkp := fgp.dpKeyArray;
288
+ let HasRules = false;
289
+ if (FFix183_LadderLength != 0) {
290
+ result += JavaScript_Rules(keyboard, fMnemonic, fgp);
291
+ }
292
+ else {
293
+ for (let j = 0; j < fgp.keys.length; j++) { // I1964
294
+ let fkp = fgp.keys[j];
295
+ if (!RuleIsExcludedByPlatform(keyboard, fkp)) {
296
+ result += FTabStop + FTabStop; // I3681
297
+ if (HasRules) {
298
+ result += 'else ';
299
+ }
300
+ HasRules = true;
301
+ if (fgp.fUsingKeys) {
302
+ result += `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})`;
303
+ }
304
+ if (xstrlen(fkp.dpContext) > 0) {
305
+ result += fgp.fUsingKeys ? '&&' : 'if(';
306
+ result += JavaScript_ContextMatch(keyboard, fkp, fkp.dpContext);
307
+ }
308
+ else if (!fgp.fUsingKeys) {
309
+ result += 'if(1';
310
+ }
311
+ linecomment = (fkp.Line > 0 && FDebug) ? ` // Line ${fkp.Line}` : '';
312
+ result +=
313
+ `) {${linecomment}${nl}` +
314
+ FTabStop + FTabStop + FTabStop;
315
+ if (fgp.fUsingKeys) { // I1959
316
+ result += 'r=m=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681
317
+ }
318
+ else {
319
+ result += 'm=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681
320
+ }
321
+ result += `${nl}${FTabStop}${FTabStop}}${nl}`; // I3681
322
+ }
323
+ }
324
+ }
325
+ if (fgp.dpMatch) {
326
+ result +=
327
+ `${FTabStop + FTabStop}if(m==1) {${nl}` +
328
+ `${FTabStop + FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}` +
329
+ `${FTabStop + FTabStop}}${nl}`;
330
+ }
331
+ if (fgp.dpNoMatch) {
332
+ if (fgp.fUsingKeys) { // I1382 - fixup m=1 to m=g()
333
+ result +=
334
+ `${FTabStop + FTabStop}if(!m&&k.KIK(e)) {${nl}` +
335
+ `${FTabStop + FTabStop + FTabStop}r=1;${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}` +
336
+ `${FTabStop + FTabStop}}${nl}`; // I1959. part 2, I2224 // I3681
337
+ }
338
+ else {
339
+ result +=
340
+ `${FTabStop + FTabStop}if(!m) {${nl}` +
341
+ `${FTabStop + FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}` +
342
+ // TODO: add FTabStop to line above, once we have 100% identical match
343
+ // to legacy compiler, but because legacy compiler missed this
344
+ // tabstop we'll leave it out here for now
345
+ `${FTabStop + FTabStop}}${nl}`;
346
+ }
347
+ }
348
+ result +=
349
+ `${FTabStop + FTabStop}return r;${nl}` +
350
+ `${FTabStop}};${nl}`;
351
+ }
352
+ for (let n = 0; n < FCallFunctions.length; n++) {
353
+ const s = callbacks.resolveFilename(kmnfile, FCallFunctions[n] + '.call_js');
354
+ if (callbacks.fs.existsSync(s)) {
355
+ const data = new TextDecoder().decode(callbacks.loadFile(s));
356
+ result += `${FTabStop}this.c${n}=function(t,e){${data.trim()}};${nl}`;
357
+ }
358
+ else {
359
+ result += `${FTabStop}this.c${n}=function(t,e){alert("call(${FCallFunctions[n]}) not defined");};${nl}`;
360
+ }
361
+ }
362
+ result += sEmbedJS + '}' + nl; // I3681
363
+ return result;
364
+ }
365
+ ///
366
+ /// Determine the modifiers used in the target keyboard and return a bitmask
367
+ /// representing them, or an number value when not in debug mode
368
+ ///
369
+ /// @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 */'
370
+ ///
371
+ function GetKeyboardModifierBitmask(keyboard, fMnemonic) {
372
+ let bitMask = 0;
373
+ for (let gp of keyboard.groups) {
374
+ if (gp.fUsingKeys) {
375
+ for (let kp of gp.keys) {
376
+ if (!RuleIsExcludedByPlatform(keyboard, kp)) {
377
+ bitMask |= JavaScript_Shift(kp, fMnemonic);
378
+ }
379
+ }
380
+ }
381
+ }
382
+ if ((bitMask & KMX.KMXFile.MASK_MODIFIER_CHIRAL) && (bitMask & KMX.KMXFile.MASK_MODIFIER_NONCHIRAL)) {
383
+ callbacks.reportMessage(KmwCompilerMessages.Warn_DontMixChiralAndNonChiralModifiers());
384
+ }
385
+ if (options.saveDebug) {
386
+ return FormatModifierAsBitflags(bitMask & KMX.KMXFile.MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY
387
+ }
388
+ return '0x' + (bitMask & KMX.KMXFile.MASK_KEYS).toString(16).toUpperCase();
389
+ }
390
+ ///
391
+ /// If debug mode, then returns Javascript code necessary for
392
+ /// accessing constants in the compiled keyboard
393
+ ///
394
+ /// @return string of JavaScript code
395
+ ///
396
+ function JavaScript_SetupDebug() {
397
+ if (IsKeyboardVersion10OrLater()) {
398
+ if (options.saveDebug) {
399
+ if (IsKeyboardVersion17OrLater()) {
400
+ return 'var modCodes = KeymanWeb.Codes.modifierCodes;' + nl +
401
+ FTabStop + 'var keyCodes = KeymanWeb.Codes.keyCodes;' + nl;
402
+ }
403
+ else {
404
+ return 'var modCodes = keyman.osk.modifierCodes;' + nl +
405
+ FTabStop + 'var keyCodes = keyman.osk.keyCodes;' + nl;
406
+ }
407
+ }
408
+ }
409
+ return '';
410
+ }
411
+ function JavaScript_SetupProlog() {
412
+ if (IsKeyboardVersion10OrLater()) {
413
+ return 'if(typeof keyman === \'undefined\') {' + nl +
414
+ FTabStop + 'console.log(\'Keyboard requires KeymanWeb 10.0 or later\');' + nl +
415
+ FTabStop + 'if(typeof tavultesoft !== \'undefined\') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");' + nl +
416
+ '} else {';
417
+ }
418
+ return '';
419
+ }
420
+ function JavaScript_SetupEpilog() {
421
+ if (IsKeyboardVersion10OrLater()) {
422
+ return '}';
423
+ }
424
+ return '';
425
+ }
426
+ function HasSupplementaryPlaneChars() {
427
+ const suppChar = /[\uD800-\uDBFF][\uDC00-\uDFFF]/;
428
+ for (let sp of fk.stores) {
429
+ if (suppChar.test(sp.dpString)) {
430
+ return true;
431
+ }
432
+ }
433
+ for (let gp of fk.groups) {
434
+ for (let kp of gp.keys) {
435
+ if (suppChar.test(kp.dpContext) || suppChar.test(kp.dpOutput)) {
436
+ return true;
437
+ }
438
+ }
439
+ if (suppChar.test(gp.dpMatch) || suppChar.test(gp.dpNoMatch)) {
440
+ return true;
441
+ }
442
+ }
443
+ return false;
444
+ }
445
+ export function RuleIsExcludedByPlatform(keyboard, fkp) {
446
+ if (fkp.dpContext == null || fkp.dpContext == '') {
447
+ return false;
448
+ }
449
+ let x = 0;
450
+ while (x < fkp.dpContext.length) {
451
+ let rec = ExpandSentinel(keyboard, fkp.dpContext, x);
452
+ if (rec.IsSentinel &&
453
+ (rec.Code == KMX.KMXFile.CODE_IFSYSTEMSTORE) &&
454
+ (rec.IfSystemStore.dwSystemID == KMX.KMXFile.TSS_PLATFORM) &&
455
+ rec.IfSystemStore.Store.dpString.includes('native')) {
456
+ if (rec.IfSystemStore.Store.dpString.match(/windows|desktop|macosx|linux/)) {
457
+ return true;
458
+ }
459
+ }
460
+ x = incxstr(fkp.dpContext, x);
461
+ }
462
+ return false;
463
+ }
464
+ function WriteBeginStatement(keyboard, name, groupIndex) {
465
+ const fgp = keyboard.groups[groupIndex];
466
+ return `${FTabStop}this.${name}=function(t,e) {${nl}` +
467
+ `${FTabStop + FTabStop}return this.g${JavaScript_Name(groupIndex, fgp.dpName)}(t,e);${nl}` +
468
+ `${FTabStop}};${nl}`;
469
+ }
470
+ /**
471
+ * Converts a modifier bit mask integer into its component bit flags
472
+ *
473
+ * @param FBitMask A KMX modifier bitmask value
474
+ *
475
+ * @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 ./'
476
+ **/
477
+ export function FormatModifierAsBitflags(FBitMask) {
478
+ const mask = [
479
+ 'LCTRL',
480
+ 'RCTRL',
481
+ 'LALT',
482
+ 'RALT',
483
+ 'SHIFT',
484
+ 'CTRL',
485
+ 'ALT',
486
+ '???',
487
+ 'CAPS',
488
+ 'NO_CAPS',
489
+ 'NUM_LOCK',
490
+ 'NO_NUM_LOCK',
491
+ 'SCROLL_LOCK',
492
+ 'NO_SCROLL_LOCK',
493
+ 'VIRTUAL_KEY' // 0X4000
494
+ ];
495
+ let i;
496
+ let result = '';
497
+ //TODO: We need to think about mnemonic layouts which are incompletely supported at present
498
+ //tavultesoft.keymanweb.osk.
499
+ if (IsKeyboardVersion10OrLater()) {
500
+ // This depends on flags defined in KeymanWeb 10.0
501
+ result = '';
502
+ for (i = 0; i < mask.length; i++) {
503
+ if (FBitMask & (1 << i)) {
504
+ if (result != '')
505
+ result += ' | ';
506
+ result += 'modCodes.' + mask[i];
507
+ }
508
+ }
509
+ if (result == '') {
510
+ result = '0';
511
+ }
512
+ result += ' /* 0x' + zeroPadHex(FBitMask, 4) + ' */';
513
+ }
514
+ else {
515
+ result = '0x' + zeroPadHex(FBitMask, 4);
516
+ }
517
+ return result;
518
+ }
519
+ function cleanKeyboardID(name) {
520
+ name = name.toLowerCase();
521
+ if (name.length == 0) {
522
+ return name;
523
+ }
524
+ if (name[0].match(/\d/)) {
525
+ name = '_' + name;
526
+ }
527
+ let result = '';
528
+ for (let i = 0; i < name.length; i++) {
529
+ if (!name[i].match(/[a-z0-9_]/)) {
530
+ result += '_';
531
+ }
532
+ else {
533
+ result += name[i];
534
+ }
535
+ }
536
+ return result;
537
+ }
538
+ function getKeymanWebCompiledNameFromFileName(filename) {
539
+ let m = /([^/\\]+)$/.exec(filename);
540
+ if (!m) {
541
+ return null;
542
+ }
543
+ m = /^(.+?)(\.[^.]+)?$/.exec(m[1]);
544
+ if (!m) {
545
+ return null;
546
+ }
547
+ return cleanKeyboardID(m[1]);
548
+ }
549
549
  //# sourceMappingURL=kmw-compiler.js.map
550
+ //# debugId=bb0f70f6-191e-5f90-80c7-09d068e49b8a