textbrowser 0.49.1 → 0.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/.ncurc.cjs +3 -0
  2. package/CHANGES.md +14 -0
  3. package/dist/WorkInfo-es.js +262 -13
  4. package/dist/activateCallback-es.js +72 -10
  5. package/dist/dist/WorkInfo-es.d.ts +331 -0
  6. package/dist/dist/WorkInfo-es.d.ts.map +1 -0
  7. package/dist/dist/activateCallback-es.d.ts +17 -0
  8. package/dist/dist/activateCallback-es.d.ts.map +1 -0
  9. package/dist/dist/index-es.d.ts +619 -0
  10. package/dist/dist/index-es.d.ts.map +1 -0
  11. package/dist/dist/sw-helper.d.ts +3 -0
  12. package/dist/dist/sw-helper.d.ts.map +1 -0
  13. package/dist/eslint.config.d.ts +126 -0
  14. package/dist/eslint.config.d.ts.map +1 -0
  15. package/dist/index-es.js +860 -134
  16. package/dist/index-es.min.js +2 -2
  17. package/dist/resources/activateCallback.d.ts +23 -0
  18. package/dist/resources/activateCallback.d.ts.map +1 -0
  19. package/dist/resources/index.d.ts +128 -0
  20. package/dist/resources/index.d.ts.map +1 -0
  21. package/dist/resources/resultsDisplay.d.ts +110 -0
  22. package/dist/resources/resultsDisplay.d.ts.map +1 -0
  23. package/dist/resources/templates/index.d.ts +59 -0
  24. package/dist/resources/templates/index.d.ts.map +1 -0
  25. package/dist/resources/templates/languageSelect.d.ts +18 -0
  26. package/dist/resources/templates/languageSelect.d.ts.map +1 -0
  27. package/dist/resources/templates/resultsDisplayClient.d.ts +26 -0
  28. package/dist/resources/templates/resultsDisplayClient.d.ts.map +1 -0
  29. package/dist/resources/templates/resultsDisplayServerOrClient.d.ts +131 -0
  30. package/dist/resources/templates/resultsDisplayServerOrClient.d.ts.map +1 -0
  31. package/dist/resources/templates/utils/dom.d.ts +15 -0
  32. package/dist/resources/templates/utils/dom.d.ts.map +1 -0
  33. package/dist/resources/templates/utils/html.d.ts +3 -0
  34. package/dist/resources/templates/utils/html.d.ts.map +1 -0
  35. package/dist/resources/templates/workDisplay.d.ts +183 -0
  36. package/dist/resources/templates/workDisplay.d.ts.map +1 -0
  37. package/dist/resources/templates/workSelect.d.ts +18 -0
  38. package/dist/resources/templates/workSelect.d.ts.map +1 -0
  39. package/dist/resources/user-sample.d.ts +2 -0
  40. package/dist/resources/user-sample.d.ts.map +1 -0
  41. package/dist/resources/user.d.ts +2 -0
  42. package/dist/resources/user.d.ts.map +1 -0
  43. package/dist/resources/utils/IntlURLSearchParams.d.ts +56 -0
  44. package/dist/resources/utils/IntlURLSearchParams.d.ts.map +1 -0
  45. package/dist/resources/utils/Languages.d.ts +81 -0
  46. package/dist/resources/utils/Languages.d.ts.map +1 -0
  47. package/dist/resources/utils/Metadata.d.ts +133 -0
  48. package/dist/resources/utils/Metadata.d.ts.map +1 -0
  49. package/dist/resources/utils/Params.d.ts +30 -0
  50. package/dist/resources/utils/Params.d.ts.map +1 -0
  51. package/dist/resources/utils/Plugin.d.ts +274 -0
  52. package/dist/resources/utils/Plugin.d.ts.map +1 -0
  53. package/dist/resources/utils/ServiceWorker.d.ts +26 -0
  54. package/dist/resources/utils/ServiceWorker.d.ts.map +1 -0
  55. package/dist/resources/utils/WorkInfo.d.ts +104 -0
  56. package/dist/resources/utils/WorkInfo.d.ts.map +1 -0
  57. package/dist/resources/utils/dialogs.d.ts +155 -0
  58. package/dist/resources/utils/dialogs.d.ts.map +1 -0
  59. package/dist/resources/utils/getLocaleFallbackResults.d.ts +19 -0
  60. package/dist/resources/utils/getLocaleFallbackResults.d.ts.map +1 -0
  61. package/dist/resources/utils/sanitize.d.ts +6 -0
  62. package/dist/resources/utils/sanitize.d.ts.map +1 -0
  63. package/dist/resources/vendor/json-refs-min.d.ts +3 -0
  64. package/dist/resources/vendor/json-refs-min.d.ts.map +1 -0
  65. package/dist/resources/workDisplay.d.ts +81 -0
  66. package/dist/resources/workDisplay.d.ts.map +1 -0
  67. package/dist/resources/workSelect.d.ts +17 -0
  68. package/dist/resources/workSelect.d.ts.map +1 -0
  69. package/dist/rollup.config.d.ts +19 -0
  70. package/dist/rollup.config.d.ts.map +1 -0
  71. package/dist/server/main.d.ts +46 -0
  72. package/dist/server/main.d.ts.map +1 -0
  73. package/dist/sw-helper.d.ts +3 -0
  74. package/dist/sw-helper.d.ts.map +1 -0
  75. package/dist/sw-helper.js +52 -12
  76. package/dist/sw-sample.d.ts +2 -0
  77. package/dist/sw-sample.d.ts.map +1 -0
  78. package/general-schemas/files.jsonschema +6 -0
  79. package/package.json +22 -9
  80. package/resources/activateCallback.js +75 -10
  81. package/resources/index.js +161 -49
  82. package/resources/resultsDisplay.js +517 -152
  83. package/resources/templates/index.js +39 -16
  84. package/resources/templates/languageSelect.js +14 -1
  85. package/resources/templates/resultsDisplayClient.js +22 -3
  86. package/resources/templates/resultsDisplayServerOrClient.js +188 -49
  87. package/resources/templates/utils/dom.js +13 -2
  88. package/resources/templates/workDisplay.js +299 -75
  89. package/resources/templates/workSelect.js +16 -3
  90. package/resources/utils/IntlURLSearchParams.js +46 -4
  91. package/resources/utils/Languages.js +71 -4
  92. package/resources/utils/Metadata.js +219 -22
  93. package/resources/utils/Params.js +70 -23
  94. package/resources/utils/Plugin.js +169 -1
  95. package/resources/utils/ServiceWorker.js +48 -19
  96. package/resources/utils/WorkInfo.js +255 -43
  97. package/resources/utils/dialogs.js +105 -7
  98. package/resources/utils/getLocaleFallbackResults.js +12 -2
  99. package/resources/utils/sanitize.js +4 -0
  100. package/resources/workDisplay.js +151 -25
  101. package/resources/workSelect.js +37 -17
  102. package/server/main.js +111 -19
  103. package/tsconfig.json +30 -0
  104. package/resources/user.js +0 -20
package/dist/index-es.js CHANGED
@@ -3748,6 +3748,17 @@ function deserialize(form, hash) {
3748
3748
  /**
3749
3749
  * @file Note that this should be kept as a polyglot client-server file.
3750
3750
  */
3751
+
3752
+ /**
3753
+ * @param {{
3754
+ * $p: import('./IntlURLSearchParams').default,
3755
+ * lang: string[],
3756
+ * langs: import('../../server/main.js').LanguageInfo[],
3757
+ * langData: import('../../server/main.js').LanguagesData,
3758
+ * fallbackLanguages?: string[],
3759
+ * basePath?: string
3760
+ * }} options
3761
+ */
3751
3762
  async function getLocaleFallbackResults(_ref) {
3752
3763
  let {
3753
3764
  $p,
@@ -3766,9 +3777,9 @@ async function getLocaleFallbackResults(_ref) {
3766
3777
  // `$ref` (as with <https://github.com/whitlockjc/json-refs>) and
3767
3778
  // replace `loadLocales` behavior with our own now resolved
3768
3779
  // locales; see https://github.com/jdorn/json-editor/issues/132
3769
- return basePath + langData.localeFileBasePath + langs.find(l => {
3780
+ return basePath + langData.localeFileBasePath + (langs.find(l => {
3770
3781
  return l.code === code;
3771
- }).locale.$ref;
3782
+ })?.locale?.$ref ?? '');
3772
3783
  }
3773
3784
  });
3774
3785
  if (!$p.l10n) {
@@ -6099,13 +6110,35 @@ if (doc && doc.body) {
6099
6110
  }
6100
6111
  const nbsp = '\u00A0'; // Very commonly needed in templates
6101
6112
 
6113
+ /**
6114
+ * @param {string} sel
6115
+ */
6102
6116
  const $ = sel => document.querySelector(sel);
6117
+
6118
+ /**
6119
+ * @param {string|HTMLElement} el
6120
+ * @param {string} descendentsSel
6121
+ */
6103
6122
  const $e = (el, descendentsSel) => {
6104
- el = typeof el === 'string' ? $(el) : el;
6105
- return el.querySelector(descendentsSel);
6123
+ const elem = typeof el === 'string' ? $(el) : el;
6124
+ return elem?.querySelector(descendentsSel);
6106
6125
  };
6107
6126
 
6127
+ /**
6128
+ * @typedef {{
6129
+ * submit: string,
6130
+ * cancel: string,
6131
+ * ok: string
6132
+ * }} LocaleObject
6133
+ */
6134
+
6135
+ /**
6136
+ * @typedef {{[locale: string]: LocaleObject}} Locales
6137
+ */
6138
+
6108
6139
  const defaultLocale = 'en';
6140
+
6141
+ /** @type {Locales} */
6109
6142
  const localeStrings = {
6110
6143
  en: {
6111
6144
  submit: 'Submit',
@@ -6114,27 +6147,72 @@ const localeStrings = {
6114
6147
  }
6115
6148
  };
6116
6149
  class Dialog {
6150
+ /**
6151
+ * @param {{
6152
+ * locale?: string,
6153
+ * localeObject?: LocaleObject
6154
+ * }} [cfg]
6155
+ */
6117
6156
  constructor() {
6118
6157
  let {
6119
6158
  locale,
6120
6159
  localeObject
6121
6160
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6161
+ this.localeStrings = localeStrings.en; // For types
6122
6162
  this.setLocale({
6123
6163
  locale,
6124
6164
  localeObject
6125
6165
  });
6126
6166
  }
6167
+ /**
6168
+ * @param {{
6169
+ * locale?: string,
6170
+ * localeObject?: Partial<LocaleObject>
6171
+ * }} cfg
6172
+ * @returns {void}
6173
+ */
6127
6174
  setLocale(_ref) {
6128
6175
  let {
6129
- locale = {},
6176
+ locale,
6130
6177
  localeObject = {}
6131
6178
  } = _ref;
6132
6179
  this.localeStrings = {
6133
6180
  ...localeStrings[defaultLocale],
6134
- ...localeStrings[locale],
6181
+ ...(locale ? localeStrings[locale] : {}),
6135
6182
  ...localeObject
6136
6183
  };
6137
6184
  }
6185
+
6186
+ /**
6187
+ * @typedef {{
6188
+ * atts?: import('jamilih').JamilihAttributes,
6189
+ * children?: import('jamilih').JamilihChildren,
6190
+ * close?: () => void,
6191
+ * remove?: boolean
6192
+ * }} MakeDialogCfg
6193
+ */
6194
+
6195
+ /**
6196
+ * @typedef {MakeDialogCfg & {
6197
+ * submit?: (
6198
+ * this: HTMLElement, args: {e: Event, dialog: HTMLDialogElement}
6199
+ * ) => void,
6200
+ * cancel: (
6201
+ * this: HTMLElement,
6202
+ * args: {
6203
+ * e: Event,
6204
+ * dialog: HTMLDialogElement
6205
+ * }
6206
+ * ) => boolean|void,
6207
+ * cancelClass?: string,
6208
+ * submitClass?: string
6209
+ * }} CancelDialogCfg
6210
+ */
6211
+
6212
+ /**
6213
+ * @param {MakeDialogCfg} cfg
6214
+ * @returns {HTMLDialogElement}
6215
+ */
6138
6216
  makeDialog(_ref2) {
6139
6217
  let {
6140
6218
  atts = {
@@ -6152,7 +6230,8 @@ class Dialog {
6152
6230
  atts.$on.close = close;
6153
6231
  }
6154
6232
  }
6155
- const dialog = /** @type {HTMLDialogElement} */jml('dialog', atts, children, $$1('#main'));
6233
+ const dialog = /** @type {HTMLDialogElement} */
6234
+ jml('dialog', atts, children, $$1('#main'));
6156
6235
  dialog.showModal();
6157
6236
  if (remove) {
6158
6237
  dialog.addEventListener('close', () => {
@@ -6161,6 +6240,10 @@ class Dialog {
6161
6240
  }
6162
6241
  return dialog;
6163
6242
  }
6243
+ /**
6244
+ * @param {CancelDialogCfg} cfg
6245
+ * @returns {HTMLDialogElement}
6246
+ */
6164
6247
  makeSubmitDialog(_ref3) {
6165
6248
  let {
6166
6249
  submit,
@@ -6169,6 +6252,7 @@ class Dialog {
6169
6252
  ...args
6170
6253
  } = _ref3;
6171
6254
  const dialog = this.makeCancelDialog(args);
6255
+ /** @type {HTMLDialogElement} */
6172
6256
  $e(dialog, `button.${args.cancelClass || 'cancel'}`).before(jml('button', {
6173
6257
  class: submitClass,
6174
6258
  $on: {
@@ -6184,6 +6268,11 @@ class Dialog {
6184
6268
  }, [this.localeStrings.submit]), nbsp.repeat(2));
6185
6269
  return dialog;
6186
6270
  }
6271
+
6272
+ /**
6273
+ * @param {CancelDialogCfg} cfg
6274
+ * @returns {HTMLDialogElement}
6275
+ */
6187
6276
  makeCancelDialog(_ref4) {
6188
6277
  let {
6189
6278
  // eslint-disable-next-line no-unused-vars -- Discarding
@@ -6216,6 +6305,12 @@ class Dialog {
6216
6305
  }, [this.localeStrings.cancel]]], dialog);
6217
6306
  return dialog;
6218
6307
  }
6308
+
6309
+ /**
6310
+ * @param {string|{message: string, ok?: boolean, submitClass?: string}} message
6311
+ * @param {boolean|{ok: boolean}} [ok]
6312
+ * @returns {Promise<void>}
6313
+ */
6219
6314
  alert(message, ok) {
6220
6315
  message = typeof message === 'string' ? {
6221
6316
  message
@@ -6226,7 +6321,7 @@ class Dialog {
6226
6321
  submitClass = 'submit'
6227
6322
  } = message;
6228
6323
  return new Promise(resolve => {
6229
- const dialog = /** @type {HTMLDialogElement} */jml('dialog', [msg, ...(includeOk ? [['br'], ['br'], ['div', {
6324
+ const dialog = /** @type {HTMLDialogElement} */jml('dialog', [msg, ...(includeOk ? (/** @type {import('jamilih').JamilihChildren} */[['br'], ['br'], ['div', {
6230
6325
  class: submitClass
6231
6326
  }, [['button', {
6232
6327
  $on: {
@@ -6235,10 +6330,16 @@ class Dialog {
6235
6330
  resolve();
6236
6331
  }
6237
6332
  }
6238
- }, [this.localeStrings.ok]]]]] : [])], $$1('#main'));
6333
+ }, [this.localeStrings.ok]]]]]) : [])], $$1('#main'));
6239
6334
  dialog.showModal();
6240
6335
  });
6241
6336
  }
6337
+ /**
6338
+ * @param {string|Partial<CancelDialogCfg> & {
6339
+ * message: string
6340
+ * }} message
6341
+ * @returns {Promise<string>}
6342
+ */
6242
6343
  prompt(message) {
6243
6344
  message = typeof message === 'string' ? {
6244
6345
  message
@@ -6249,19 +6350,28 @@ class Dialog {
6249
6350
  ...submitArgs
6250
6351
  } = message;
6251
6352
  return new Promise((resolve, reject) => {
6353
+ /**
6354
+ * @param {{
6355
+ * e: Event,
6356
+ * dialog: HTMLDialogElement
6357
+ * }} args
6358
+ */
6252
6359
  const submit = function (_ref5) {
6253
6360
  let {
6254
6361
  e,
6255
6362
  dialog
6256
6363
  } = _ref5;
6257
6364
  if (userSubmit) {
6258
- userSubmit.call(this, {
6365
+ userSubmit.call(
6366
+ // @ts-expect-error Ok
6367
+ /** @type {HTMLElement} */
6368
+ this, {
6259
6369
  e,
6260
6370
  dialog
6261
6371
  });
6262
6372
  }
6263
6373
  dialog.close();
6264
- resolve($e(dialog, 'input').value);
6374
+ resolve(/** @type {HTMLInputElement} */$e(dialog, 'input').value);
6265
6375
  };
6266
6376
  /* const dialog = */
6267
6377
  this.makeSubmitDialog({
@@ -6274,6 +6384,10 @@ class Dialog {
6274
6384
  });
6275
6385
  });
6276
6386
  }
6387
+ /**
6388
+ * @param {string|{message: string, submitClass?: string}} message
6389
+ * @returns {Promise<void>}
6390
+ */
6277
6391
  confirm(message) {
6278
6392
  message = typeof message === 'string' ? {
6279
6393
  message
@@ -6307,6 +6421,13 @@ class Dialog {
6307
6421
  const dialogs = new Dialog();
6308
6422
 
6309
6423
  // Todo: remember this locales choice by cookie?
6424
+
6425
+ /**
6426
+ * @param {{
6427
+ * namespace: string,
6428
+ * preferredLocale: string
6429
+ * }} cfg
6430
+ */
6310
6431
  const getPreferredLanguages = _ref => {
6311
6432
  let {
6312
6433
  namespace,
@@ -6316,7 +6437,10 @@ const getPreferredLanguages = _ref => {
6316
6437
  // Todo: Switch to fallbackLanguages so can default to
6317
6438
  // navigator.languages?
6318
6439
  const langCodes = localStorage.getItem(namespace + '-langCodes');
6319
- const lngs = langCodes && JSON.parse(langCodes) || [preferredLocale];
6440
+ const lngs = /** @type {string[]} */
6441
+ langCodes && JSON.parse(langCodes) || [preferredLocale];
6442
+
6443
+ /** @type {string[]} */
6320
6444
  const langArr = [];
6321
6445
  lngs.forEach(lng => {
6322
6446
  // Todo: Check for multiple separate hyphenated
@@ -6335,20 +6459,62 @@ const getPreferredLanguages = _ref => {
6335
6459
  * @classdesc Note that this should be kept as a polyglot client-server class.
6336
6460
  */
6337
6461
  class Languages {
6462
+ /**
6463
+ * @param {{
6464
+ * langData: import('../../server/main.js').LanguagesData
6465
+ * }} cfg
6466
+ */
6338
6467
  constructor(_ref2) {
6339
6468
  let {
6340
6469
  langData
6341
6470
  } = _ref2;
6342
6471
  this.langData = langData;
6343
6472
  }
6473
+ /**
6474
+ * @param {string} langCode
6475
+ * @returns {{
6476
+ * languages: {
6477
+ * [key: string]: string
6478
+ * }
6479
+ * }}
6480
+ */
6344
6481
  localeFromLangData(langCode) {
6345
- return this.langData['localization-strings'][langCode];
6482
+ return (
6483
+ /**
6484
+ * @type {{
6485
+ * languages: {
6486
+ * [key: string]: string
6487
+ * }
6488
+ * }}
6489
+ */
6490
+ this.langData['localization-strings'][langCode]
6491
+ );
6346
6492
  }
6493
+ /**
6494
+ * @param {string} code
6495
+ * @returns {string}
6496
+ */
6347
6497
  getLanguageFromCode(code) {
6348
6498
  return this.localeFromLangData(code).languages[code];
6349
6499
  // Could add something like this in place or as fallback, though need to pass in locale
6350
6500
  // || new Intl.DisplayNames([locale], {type: 'language'}).of(code);
6351
6501
  }
6502
+
6503
+ /**
6504
+ * @param {{
6505
+ * pluginName: string,
6506
+ * workI18n: import('intl-dom').I18NCallback,
6507
+ * targetLanguage: string,
6508
+ * applicableFieldI18N: string,
6509
+ * meta: {
6510
+ * [key: string]: string
6511
+ * },
6512
+ * metaApplicableField: {
6513
+ * [key: string]: string
6514
+ * },
6515
+ * }} cfg
6516
+ * @returns {string}
6517
+ */
6352
6518
  getFieldNameFromPluginNameAndLocales(_ref3) {
6353
6519
  let {
6354
6520
  pluginName,
@@ -6359,7 +6525,7 @@ class Languages {
6359
6525
  meta,
6360
6526
  metaApplicableField
6361
6527
  } = _ref3;
6362
- return workI18n(['plugins', pluginName, 'fieldname'], {
6528
+ return /** @type {string} */workI18n(['plugins', pluginName, 'fieldname'], {
6363
6529
  ...meta,
6364
6530
  ...metaApplicableField,
6365
6531
  applicableField: applicableFieldI18N,
@@ -6369,11 +6535,24 @@ class Languages {
6369
6535
  throwOnExtraSuppliedFormatters: false
6370
6536
  });
6371
6537
  }
6538
+
6539
+ /**
6540
+ * @param {{$p: import('./IntlURLSearchParams.js').default}} cfg
6541
+ * @returns {{
6542
+ * lang: string[],
6543
+ * langs: import('../../server/main.js').LanguageInfo[],
6544
+ * languageParam: string|null,
6545
+ * fallbackLanguages: string[]
6546
+ * }}
6547
+ */
6372
6548
  getLanguageInfo(_ref4) {
6373
6549
  let {
6374
6550
  $p
6375
6551
  } = _ref4;
6376
6552
  const langs = this.langData.languages;
6553
+ /**
6554
+ * @param {string} lcl
6555
+ */
6377
6556
  const localePass = lcl => {
6378
6557
  return langs.some(_ref5 => {
6379
6558
  let {
@@ -14323,23 +14502,57 @@ var JsonRefs = function (t) {
14323
14502
  const getCurrDir = () => {
14324
14503
  return window.location.href.replace(/(index\.html)?#.*$/, '');
14325
14504
  };
14505
+
14506
+ /**
14507
+ * @typedef {{
14508
+ * "localization-strings": import('../../server/main.js').LocalizationStrings
14509
+ * table: {browse_fields: (string|{
14510
+ * name?: string,
14511
+ * set: string[],
14512
+ * presort?: boolean
14513
+ * })[]}
14514
+ * fields: {
14515
+ * [key: string]: {
14516
+ * prefer_alias: boolean,
14517
+ * lang: string,
14518
+ * 'fieldvalue-aliases': {
14519
+ * localeKey: string,
14520
+ * [key: string]: string|string[]
14521
+ * }
14522
+ * }
14523
+ * }
14524
+ * }} MetadataObj
14525
+ */
14526
+
14527
+ /**
14528
+ * @param {string[]} lang
14529
+ * @param {MetadataObj} metadataObj
14530
+ * @param {string|string[]} properties
14531
+ * @param {boolean} [allowObjects]
14532
+ * @returns {string|string[]|import('../../server/main.js').LocalizationStrings}
14533
+ */
14326
14534
  const getMetaProp = function getMetaProp(lang, metadataObj, properties, allowObjects) {
14327
14535
  let prop;
14328
14536
  properties = typeof properties === 'string' ? [properties] : properties;
14329
- lang.some(lan => {
14537
+ for (const lan of lang) {
14330
14538
  const p = [...properties];
14331
- let strings = metadataObj['localization-strings'][lan];
14539
+ let strings = /** @type {string | string[]|import('../../server/main.js').LocalizationStrings} */
14540
+ metadataObj['localization-strings'][lan];
14332
14541
  while (strings && p.length) {
14333
- strings = strings[p.shift()];
14542
+ strings = /** @type {import('../../server/main.js').LocalizationStrings} */strings[(/** @type {string} */p.shift())];
14334
14543
  }
14335
14544
  // Todo: Fix this allowance for allowObjects (as it does not properly
14336
14545
  // fallback if an object is returned from a language because
14337
14546
  // that language is missing content and is only thus returning
14338
14547
  // an object)
14339
14548
  prop = allowObjects || typeof strings === 'string' ? strings : undefined;
14340
- return prop;
14341
- });
14342
- return prop;
14549
+ if (prop) {
14550
+ break;
14551
+ }
14552
+ }
14553
+ return /** @type {string|string[]|import('../../server/main.js').LocalizationStrings} */(
14554
+ prop
14555
+ );
14343
14556
  };
14344
14557
 
14345
14558
  // Use the following to dynamically add specific file schema in place of
@@ -14347,6 +14560,12 @@ const getMetaProp = function getMetaProp(lang, metadataObj, properties, allowObj
14347
14560
  // filesSchema.properties.groups.items.properties.files.items.properties.
14348
14561
  // file.anyOf.splice(1, 1, {$ref: schemaFile});
14349
14562
  // Todo: Allow use of dbs and fileGroup together in base directories?
14563
+
14564
+ /**
14565
+ * @param {string} file
14566
+ * @param {string} property
14567
+ * @param {string} basePath
14568
+ */
14350
14569
  const getMetadata = async (file, property, basePath) => {
14351
14570
  const url = new URL(basePath || getCurrDir());
14352
14571
  url.search = ''; // Clear out query string, e.g., `?fbclid` from Facebook
@@ -14354,6 +14573,13 @@ const getMetadata = async (file, property, basePath) => {
14354
14573
  url.hash = property ? '#/' + property : '';
14355
14574
  return (await JsonRefs.resolveRefsAt(url.toString(), {
14356
14575
  loaderOptions: {
14576
+ /**
14577
+ * @param {{
14578
+ * text: string,
14579
+ * body: any
14580
+ * }} res
14581
+ * @param {(err?: Error, cbValue: any) => void} callback
14582
+ */
14357
14583
  processContent(res, callback) {
14358
14584
  callback(undefined, JSON.parse(res.text ||
14359
14585
  // `.metadata` not a recognized extension, so
@@ -14363,6 +14589,37 @@ const getMetadata = async (file, property, basePath) => {
14363
14589
  }
14364
14590
  })).resolved;
14365
14591
  };
14592
+
14593
+ /**
14594
+ * @typedef {{
14595
+ * field: string,
14596
+ * schemaItems: {
14597
+ * title: string,
14598
+ * type: string,
14599
+ * enum?: string[]
14600
+ * }[],
14601
+ * metadataObj: MetadataObj,
14602
+ * getFieldAliasOrName: (field: string) => string,
14603
+ * lang: string[]
14604
+ * }} GetFieldNameAndValueAliasesOptions
14605
+ */
14606
+
14607
+ /**
14608
+ * @param {GetFieldNameAndValueAliasesOptions} cfg
14609
+ * @returns {{
14610
+ * aliases: string[]|null,
14611
+ * fieldValueAliasMap: Record<string, string[]>|null,
14612
+ * rawFieldValueAliasMap: Record<string, string[]>|null,
14613
+ * fieldName: string,
14614
+ * fieldSchema: {
14615
+ * title: string,
14616
+ * type: string
14617
+ * },
14618
+ * fieldSchemaIndex: number,
14619
+ * preferAlias: boolean,
14620
+ * lang: string
14621
+ * }}
14622
+ */
14366
14623
  const getFieldNameAndValueAliases = function (_ref) {
14367
14624
  let {
14368
14625
  field,
@@ -14376,6 +14633,22 @@ const getFieldNameAndValueAliases = function (_ref) {
14376
14633
  });
14377
14634
  const fieldSchema = schemaItems[fieldSchemaIndex];
14378
14635
  const fieldInfo = metadataObj.fields[field];
14636
+
14637
+ /**
14638
+ * @type {{
14639
+ * aliases: string[]|null,
14640
+ * fieldValueAliasMap: Record<string, string[]>|null,
14641
+ * rawFieldValueAliasMap: Record<string, string[]>|null,
14642
+ * fieldName: string,
14643
+ * fieldSchema: {
14644
+ * title: string,
14645
+ * type: string
14646
+ * },
14647
+ * fieldSchemaIndex: number,
14648
+ * preferAlias: boolean,
14649
+ * lang: string
14650
+ * }}
14651
+ */
14379
14652
  const ret = {
14380
14653
  // field,
14381
14654
  aliases: null,
@@ -14387,10 +14660,14 @@ const getFieldNameAndValueAliases = function (_ref) {
14387
14660
  preferAlias: fieldInfo.prefer_alias,
14388
14661
  lang: fieldInfo.lang
14389
14662
  };
14663
+
14664
+ /** @type {import('../../server/main.js').LocalizationStrings} */
14390
14665
  let fieldValueAliasMap = fieldInfo && fieldInfo['fieldvalue-aliases'];
14391
14666
  if (fieldValueAliasMap) {
14392
14667
  if (fieldValueAliasMap.localeKey) {
14393
- fieldValueAliasMap = getMetaProp(lang, metadataObj, fieldValueAliasMap.localeKey.split('/'), true);
14668
+ fieldValueAliasMap = /** @type {import('../../server/main.js').LocalizationStrings} */
14669
+ getMetaProp(lang, metadataObj, /** @type {string} */
14670
+ fieldValueAliasMap.localeKey.split('/'), true);
14394
14671
  }
14395
14672
  // eslint-disable-next-line unicorn/prefer-structured-clone -- Expecting JSON
14396
14673
  ret.rawFieldValueAliasMap = JSON.parse(JSON.stringify(fieldValueAliasMap));
@@ -14399,11 +14676,14 @@ const getFieldNameAndValueAliases = function (_ref) {
14399
14676
  // needed cases
14400
14677
  if (fieldSchema.enum && fieldSchema.enum.length) {
14401
14678
  fieldSchema.enum.forEach(enm => {
14402
- ret.aliases.push(getMetaProp(lang, metadataObj, ['fieldvalue', field, enm], true));
14679
+ /** @type {string[]} */
14680
+ ret.aliases.push(/** @type {string} */
14681
+ getMetaProp(lang, metadataObj, ['fieldvalue', field, enm], true));
14403
14682
  if (enm in fieldValueAliasMap &&
14404
14683
  // Todo: We could allow numbers here too, but crowds
14405
14684
  // pull-down
14406
14685
  typeof fieldValueAliasMap[enm] === 'string') {
14686
+ /** @type {string[]} */
14407
14687
  ret.aliases.push(...fieldValueAliasMap[enm]);
14408
14688
  }
14409
14689
  });
@@ -14416,9 +14696,12 @@ const getFieldNameAndValueAliases = function (_ref) {
14416
14696
  // We'll preserve the numbers since probably more useful if
14417
14697
  // stored with data (as opposed to enums)
14418
14698
  if (!Array.isArray(aliases)) {
14419
- aliases = Object.values(aliases);
14699
+ aliases = /** @type {string[]} */
14700
+ Object.values(/** @type {import('../../server/main.js').LocalizationStrings} */
14701
+ aliases);
14420
14702
  }
14421
14703
  // We'll assume the longest version is best for auto-complete
14704
+ /** @type {string[]} */
14422
14705
  ret.aliases.push(...aliases.filter(v => {
14423
14706
  return aliases.every(x => {
14424
14707
  return x === v || !x.toLowerCase().startsWith(v.toLowerCase());
@@ -14433,6 +14716,40 @@ const getFieldNameAndValueAliases = function (_ref) {
14433
14716
  }
14434
14717
  return ret;
14435
14718
  };
14719
+
14720
+ /**
14721
+ * @typedef {{
14722
+ * metadataObj: MetadataObj,
14723
+ * schemaItems: {
14724
+ * title: string,
14725
+ * type: string
14726
+ * }[],
14727
+ * getFieldAliasOrName: (field: string) => string,
14728
+ * lang: string[],
14729
+ * callback: (cfg: {
14730
+ * setName: string,
14731
+ * browseFields: {
14732
+ * aliases: string[]|null,
14733
+ * fieldValueAliasMap: Record<string, string[]>|null,
14734
+ * rawFieldValueAliasMap: Record<string, string[]>|null,
14735
+ * fieldName: string,
14736
+ * fieldSchema: {
14737
+ * title: string,
14738
+ * type: string
14739
+ * },
14740
+ * fieldSchemaIndex: number,
14741
+ * preferAlias: boolean,
14742
+ * lang: string
14743
+ * }[],
14744
+ * i: number,
14745
+ * presort: boolean|undefined
14746
+ * }) => void
14747
+ * }} GetBrowseFieldDataOptions
14748
+ */
14749
+
14750
+ /**
14751
+ * @param {GetBrowseFieldDataOptions} cfg
14752
+ */
14436
14753
  const getBrowseFieldData = function (_ref3) {
14437
14754
  let {
14438
14755
  metadataObj,
@@ -14478,12 +14795,22 @@ const getBrowseFieldData = function (_ref3) {
14478
14795
 
14479
14796
  // Todo: Incorporate other methods into this class
14480
14797
  class Metadata {
14798
+ /**
14799
+ * @param {{
14800
+ * metadataObj: MetadataObj
14801
+ * }} cfg
14802
+ */
14481
14803
  constructor(_ref4) {
14482
14804
  let {
14483
14805
  metadataObj
14484
14806
  } = _ref4;
14485
14807
  this.metadataObj = metadataObj;
14486
14808
  }
14809
+
14810
+ /**
14811
+ * @param {string} field
14812
+ * @returns {string|undefined}
14813
+ */
14487
14814
  getFieldLang(field) {
14488
14815
  const {
14489
14816
  metadataObj
@@ -14491,6 +14818,19 @@ class Metadata {
14491
14818
  const fields = metadataObj && metadataObj.fields;
14492
14819
  return fields && fields[field] && fields[field].lang;
14493
14820
  }
14821
+
14822
+ /**
14823
+ * @param {{
14824
+ * namespace: string,
14825
+ * preferredLocale: string,
14826
+ * schemaItems: {
14827
+ * title: string,
14828
+ * type: string
14829
+ * }[],
14830
+ * pluginsForWork: import('./Plugin.js').PluginsForWork
14831
+ * }} cfg
14832
+ * @returns {(field: string) => boolean}
14833
+ */
14494
14834
  getFieldMatchesLocale(_ref5) {
14495
14835
  let {
14496
14836
  namespace,
@@ -14525,7 +14865,9 @@ class Metadata {
14525
14865
  // If this is a localized field (e.g., enum), we don't want
14526
14866
  // to avoid as may be translated (should check though)
14527
14867
  const hasFieldValue = localeStrings && Object.keys(localeStrings).some(lng => {
14528
- const fv = localeStrings[lng] && localeStrings[lng].fieldvalue;
14868
+ const fv = localeStrings[lng] && (/** @type {import('../../server/main.js').LocalizationStrings} */
14869
+ /** @type {import('../../server/main.js').LocalizationStrings} */
14870
+ localeStrings[lng].fieldvalue);
14529
14871
  return fv && fv[field];
14530
14872
  });
14531
14873
  return hasFieldValue || metaLang && preferredLanguages.includes(metaLang) || schemaItems.some(item => {
@@ -14535,11 +14877,18 @@ class Metadata {
14535
14877
  }
14536
14878
  }
14537
14879
 
14880
+ /**
14881
+ * @param {string} pluginName
14882
+ */
14538
14883
  const escapePluginComponent = pluginName => {
14539
14884
  return pluginName.replaceAll('^', '^^').
14540
14885
  // Escape our escape
14541
14886
  replaceAll('-', '^0');
14542
14887
  };
14888
+
14889
+ /**
14890
+ * @param {string|undefined} pluginName
14891
+ */
14543
14892
  const unescapePluginComponent = pluginName => {
14544
14893
  if (!pluginName) {
14545
14894
  return pluginName;
@@ -14548,6 +14897,14 @@ const unescapePluginComponent = pluginName => {
14548
14897
  return esc.length % 2 ? esc.slice(1) + '-' : n0;
14549
14898
  }).replaceAll('^^', '^');
14550
14899
  };
14900
+
14901
+ /**
14902
+ * @param {{
14903
+ * pluginName: string,
14904
+ * applicableField: string,
14905
+ * targetLanguage: string
14906
+ * }} cfg
14907
+ */
14551
14908
  const escapePlugin = _ref => {
14552
14909
  let {
14553
14910
  pluginName,
@@ -14556,7 +14913,28 @@ const escapePlugin = _ref => {
14556
14913
  } = _ref;
14557
14914
  return escapePluginComponent(pluginName) + (applicableField ? '-' + escapePluginComponent(applicableField) : '-') + (targetLanguage ? '-' + escapePluginComponent(targetLanguage) : '');
14558
14915
  };
14916
+
14917
+ /**
14918
+ * @todo Complete
14919
+ * @typedef {{}} PluginObject
14920
+ */
14921
+
14559
14922
  class PluginsForWork {
14923
+ /**
14924
+ * @param {{
14925
+ * pluginsInWork: [string, {
14926
+ * lang: string,
14927
+ * meta: any,
14928
+ * onByDefault: boolean
14929
+ * }][],
14930
+ * pluginFieldMappings: {
14931
+ * placement: string,
14932
+ * 'applicable-fields': {
14933
+ * }
14934
+ * }[],
14935
+ * pluginObjects: PluginObject[]
14936
+ * }} cfg
14937
+ */
14560
14938
  constructor(_ref2) {
14561
14939
  let {
14562
14940
  pluginsInWork,
@@ -14567,6 +14945,11 @@ class PluginsForWork {
14567
14945
  this.pluginFieldMappings = pluginFieldMappings;
14568
14946
  this.pluginObjects = pluginObjects;
14569
14947
  }
14948
+
14949
+ /**
14950
+ * @param {string} pluginName
14951
+ * @returns {PluginObject}
14952
+ */
14570
14953
  getPluginObject(pluginName) {
14571
14954
  const idx = this.pluginsInWork.findIndex(_ref3 => {
14572
14955
  let [name] = _ref3;
@@ -14575,6 +14958,25 @@ class PluginsForWork {
14575
14958
  const plugin = this.pluginObjects[idx];
14576
14959
  return plugin;
14577
14960
  }
14961
+
14962
+ /**
14963
+ * @param {(cfg: {
14964
+ * plugin: PluginObject,
14965
+ * placement: string,
14966
+ * applicableFields: {
14967
+ * [applicableField: string]: {
14968
+ * targetLanguage: string|string[],
14969
+ * onByDefault: boolean,
14970
+ * meta: any
14971
+ * }
14972
+ * },
14973
+ * pluginName: string,
14974
+ * pluginLang: string,
14975
+ * onByDefaultDefault: boolean,
14976
+ * meta: {}
14977
+ * }) => void} cb
14978
+ * @returns {void}
14979
+ */
14578
14980
  iterateMappings(cb) {
14579
14981
  this.pluginFieldMappings.forEach((_ref4, i) => {
14580
14982
  let {
@@ -14604,6 +15006,25 @@ class PluginsForWork {
14604
15006
  });
14605
15007
  });
14606
15008
  }
15009
+
15010
+ /**
15011
+ * @param {{
15012
+ * [applicableField: string]: {
15013
+ * targetLanguage: string|string[],
15014
+ * onByDefault: boolean,
15015
+ * meta: any
15016
+ * }
15017
+ * }} applicableFields
15018
+ * @param {(cfg: {
15019
+ * applicableField: string,
15020
+ * targetLanguage: string,
15021
+ * onByDefault: boolean,
15022
+ * metaApplicableField: {
15023
+ * [key: string]: string
15024
+ * }
15025
+ * }) => void} cb
15026
+ * @returns {boolean}
15027
+ */
14607
15028
  processTargetLanguages(applicableFields, cb) {
14608
15029
  if (!applicableFields) {
14609
15030
  return false;
@@ -14634,6 +15055,14 @@ class PluginsForWork {
14634
15055
  });
14635
15056
  return true;
14636
15057
  }
15058
+
15059
+ /**
15060
+ * @param {{
15061
+ * namespace: string,
15062
+ * field: string
15063
+ * }} cfg
15064
+ * @returns {boolean}
15065
+ */
14637
15066
  isPluginField(_ref6) {
14638
15067
  let {
14639
15068
  namespace,
@@ -14641,6 +15070,14 @@ class PluginsForWork {
14641
15070
  } = _ref6;
14642
15071
  return field.startsWith(`${namespace}-plugin-`);
14643
15072
  }
15073
+
15074
+ /**
15075
+ * @param {{
15076
+ * namespace: string,
15077
+ * field: string
15078
+ * }} cfg
15079
+ * @returns {[string, string|undefined, string|undefined]}
15080
+ */
14644
15081
  getPluginFieldParts(_ref7) {
14645
15082
  let {
14646
15083
  namespace,
@@ -14653,11 +15090,19 @@ class PluginsForWork {
14653
15090
  } else {
14654
15091
  pluginName = field;
14655
15092
  }
14656
- return [pluginName, applicableField, targetLanguage].map(unescapePluginComponent);
15093
+ return /** @type {[string, string|undefined, string|undefined]} */(
15094
+ [pluginName, applicableField, targetLanguage].map(unescapePluginComponent)
15095
+ );
14657
15096
  }
14658
15097
  }
14659
15098
 
14660
15099
  /* globals process -- Node polyglot */
15100
+
15101
+ /**
15102
+ * @param {FilesObject} filesObj
15103
+ * @param {FileGroup} fileGroup
15104
+ * @param {FileData} fileData
15105
+ */
14661
15106
  const getFilePaths = function getFilePaths(filesObj, fileGroup, fileData) {
14662
15107
  const baseDir = (filesObj.baseDirectory || '') + (fileGroup.baseDirectory || '') + '/';
14663
15108
  const schemaBaseDir = (filesObj.schemaBaseDirectory || '') + (fileGroup.schemaBaseDirectory || '') + '/';
@@ -14671,6 +15116,23 @@ const getFilePaths = function getFilePaths(filesObj, fileGroup, fileData) {
14671
15116
  metadataFile
14672
15117
  };
14673
15118
  };
15119
+
15120
+ /**
15121
+ * @typedef {{
15122
+ * lang: string[],
15123
+ * fallbackLanguages: string[],
15124
+ * work: string,
15125
+ * files: string,
15126
+ * allowPlugins: boolean|undefined,
15127
+ * basePath: string,
15128
+ * languages: import('./Languages.js').Languages,
15129
+ * preferredLocale: string
15130
+ * }} GetWorkDataOptions
15131
+ */
15132
+
15133
+ /**
15134
+ * @param {GetWorkDataOptions} cfg
15135
+ */
14674
15136
  const getWorkData = async function (_ref) {
14675
15137
  let {
14676
15138
  lang,
@@ -14683,7 +15145,15 @@ const getWorkData = async function (_ref) {
14683
15145
  preferredLocale
14684
15146
  } = _ref;
14685
15147
  const filesObj = await getJSON(files);
14686
- const localizationStrings = filesObj['localization-strings'];
15148
+ const localizationStrings =
15149
+ /**
15150
+ * @type {{
15151
+ * "localization-strings": {
15152
+ * [key: string]: {}
15153
+ * }
15154
+ * }}
15155
+ */
15156
+ filesObj?.['localization-strings'];
14687
15157
  const workI18n = await i18n({
14688
15158
  messageStyle: 'plainNested',
14689
15159
  locales: lang,
@@ -14923,16 +15393,21 @@ const getWorkData = async function (_ref) {
14923
15393
  // import {escapeHTML} from './sanitize.js';
14924
15394
 
14925
15395
  /**
14926
- * Note that this function be kept as a polyglot client-server file.
14927
- * @param {PlainObject} target
14928
- * @param {PlainObject} source
14929
- * @returns {{
15396
+ * @typedef {{
14930
15397
  * userJSON: string,
14931
15398
  * languages: string,
14932
15399
  * serviceWorkerPath: string,
14933
15400
  * files: string,
14934
- * namespace: string
14935
- * }}
15401
+ * namespace: string,
15402
+ * stylesheets?: string[]
15403
+ * }} ServiceWorkerConfig
15404
+ */
15405
+
15406
+ /**
15407
+ * Note that this function be kept as a polyglot client-server file.
15408
+ * @param {Partial<ServiceWorkerConfig>} target
15409
+ * @param {Partial<ServiceWorkerConfig>} source
15410
+ * @returns {ServiceWorkerConfig}
14936
15411
  */
14937
15412
  const setServiceWorkerDefaults = (target, source) => {
14938
15413
  target.userJSON = source.userJSON || 'resources/user.json';
@@ -14940,13 +15415,18 @@ const setServiceWorkerDefaults = (target, source) => {
14940
15415
  target.serviceWorkerPath = source.serviceWorkerPath || `sw.js?pathToUserJSON=${encodeURIComponent(target.userJSON)}&stylesheets=${encodeURIComponent(JSON.stringify(target.stylesheets || []))}`;
14941
15416
  target.files = source.files || 'files.json';
14942
15417
  target.namespace = source.namespace || 'textbrowser';
14943
- return target;
15418
+ return /** @type {ServiceWorkerConfig} */target;
14944
15419
  };
14945
15420
 
14946
15421
  // (Unless skipped in code, will wait between install
14947
15422
  // of new and activation of new or existing if still
14948
15423
  // some tabs open)
14949
15424
 
15425
+ /**
15426
+ * @param {{
15427
+ * r: ServiceWorkerRegistration
15428
+ * }} cfg
15429
+ */
14950
15430
  const listenForWorkerUpdate = _ref => {
14951
15431
  let {
14952
15432
  r
@@ -14957,7 +15437,7 @@ const listenForWorkerUpdate = _ref => {
14957
15437
  // r.installing now available (though r.active is also,
14958
15438
  // apparently due to prior activation; but not r.waiting)
14959
15439
  console.log('update found', e);
14960
- const newWorker = r.installing;
15440
+ const newWorker = /** @type {ServiceWorker} */r.installing;
14961
15441
 
14962
15442
  // statechange won't catch this installing event as already installing
14963
15443
 
@@ -15013,6 +15493,19 @@ for offline installation.
15013
15493
  });
15014
15494
  });
15015
15495
  };
15496
+
15497
+ /**
15498
+ * @typedef {{
15499
+ * addLogEntry: (entry: {text: string}) => void,
15500
+ * }} Logger
15501
+ */
15502
+
15503
+ /**
15504
+ * @param {{
15505
+ * r: ServiceWorkerRegistration,
15506
+ * logger: Logger
15507
+ * }} cfg
15508
+ */
15016
15509
  const respondToState = async _ref2 => {
15017
15510
  let {
15018
15511
  r,
@@ -15083,20 +15576,20 @@ const respondToState = async _ref2 => {
15083
15576
  text: message + `${errorType === 'dbError' ? `Database error ${name}` : ''}; trying again...`
15084
15577
  });
15085
15578
  /*
15086
- if (errorType === 'dbError') {
15087
- logger.dbError({
15088
- type: name || errorType,
15089
- escapedErrorMessage: escapeHTML(message)
15090
- });
15091
- }
15092
- */
15579
+ if (errorType === 'dbError') {
15580
+ logger.dbError({
15581
+ type: name || errorType,
15582
+ escapedErrorMessage: escapeHTML(message)
15583
+ });
15584
+ }
15585
+ */
15093
15586
  // Todo: auto-close any dbError dialog if retrying
15094
15587
  // No longer rejecting as should auto-retry
15095
15588
  /*
15096
- const err = new Error(message);
15097
- err.type = type;
15098
- reject(err);
15099
- */
15589
+ const err = new Error(message);
15590
+ err.type = type;
15591
+ reject(err);
15592
+ */
15100
15593
  break;
15101
15594
  default:
15102
15595
  console.error('Unexpected type', type);
@@ -15147,6 +15640,13 @@ any indication it is installing.
15147
15640
 
15148
15641
  // Keep in this file as may wish to avoid using for server (while still
15149
15642
  // doing other service worker work)
15643
+
15644
+ /**
15645
+ * @param {{
15646
+ * serviceWorkerPath: string,
15647
+ * logger: Logger
15648
+ * }} cfg
15649
+ */
15150
15650
  const registerServiceWorker = async _ref4 => {
15151
15651
  let {
15152
15652
  serviceWorkerPath,
@@ -15205,6 +15705,10 @@ Please refresh the page if you wish to reattempt.
15205
15705
  });
15206
15706
  };
15207
15707
 
15708
+ /**
15709
+ * Prevent XSS attacks.
15710
+ * @param {string} s - The string to sanitize
15711
+ */
15208
15712
  const escapeHTML = s => {
15209
15713
  return !s ? '' : s.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
15210
15714
  };
@@ -16634,7 +17138,7 @@ const Templates = {
16634
17138
  // We empty rather than `replaceWith` as our Jamilih `body`
16635
17139
  // aliases expect the old instance
16636
17140
  while (body.hasChildNodes()) {
16637
- body.firstChild.remove();
17141
+ body.firstChild?.remove();
16638
17142
  }
16639
17143
  return jml('div', {
16640
17144
  id: 'main',
@@ -16643,21 +17147,27 @@ const Templates = {
16643
17147
  },
16644
17148
  permissions: {
16645
17149
  versionChange() {
16646
- $$1('#versionChange').showModal();
17150
+ /** @type {HTMLDialogElement} */
17151
+ $$1('#versionChange')?.showModal();
16647
17152
  },
17153
+ /**
17154
+ * @param {{text: string}} cfg
17155
+ */
16648
17156
  addLogEntry(_ref) {
16649
17157
  let {
16650
17158
  text
16651
17159
  } = _ref;
16652
17160
  const installationDialog = $$1('#installationLogContainer');
16653
17161
  try {
17162
+ /** @type {HTMLDialogElement} */
16654
17163
  installationDialog.showModal();
16655
- const container = $$1('#dialogContainer');
17164
+ const container = /** @type {HTMLElement} */$$1('#dialogContainer');
16656
17165
  container.hidden = false;
16657
17166
  // eslint-disable-next-line no-unused-vars -- Ok
16658
17167
  } catch (err) {
16659
17168
  // May already be open
16660
17169
  }
17170
+ /** @type {HTMLElement} */
16661
17171
  $$1('#installationLog').append(text + '\n');
16662
17172
  },
16663
17173
  exitDialogs() {
@@ -16666,6 +17176,12 @@ const Templates = {
16666
17176
  container.hidden = true;
16667
17177
  }
16668
17178
  },
17179
+ /**
17180
+ * @param {{
17181
+ * type: string,
17182
+ * escapedErrorMessage: string
17183
+ * }} cfg
17184
+ */
16669
17185
  dbError(_ref2) {
16670
17186
  let {
16671
17187
  type,
@@ -16674,26 +17190,32 @@ const Templates = {
16674
17190
  if (type) {
16675
17191
  jml('span', [type, ' ', escapedErrorMessage], $$1('#dbError'));
16676
17192
  }
17193
+ /** @type {HTMLDialogElement} */
16677
17194
  $$1('#dbError').showModal();
16678
17195
  },
17196
+ /**
17197
+ * @param {string} escapedErrorMessage
17198
+ */
16679
17199
  errorRegistering(escapedErrorMessage) {
16680
17200
  if (escapedErrorMessage) {
16681
17201
  jml('span', [escapedErrorMessage], $$1('#errorRegistering'));
16682
17202
  }
17203
+ /** @type {HTMLDialogElement} */
16683
17204
  $$1('#errorRegistering').showModal();
16684
17205
  },
16685
17206
  browserNotGrantingPersistence() {
17207
+ /** @type {HTMLDialogElement} */
16686
17208
  $$1('#browserNotGrantingPersistence').showModal();
16687
17209
  },
16688
17210
  /**
16689
- * @param {PlainObject} cfg
16690
- * @param {I18NCallback} cfg.siteI18n
16691
- * @param {() => Promise<void>} cfg.ok
16692
- * @param {() => void} cfg.refuse
16693
- * @param {() => Promise<void>} cfg.close
16694
- * @param {() => void} cfg.closeBrowserNotGranting
17211
+ * @param {object} cfg
17212
+ * @param {import('intl-dom').I18NCallback} cfg.siteI18n
17213
+ * @param {() => Promise<void>} [cfg.ok]
17214
+ * @param {() => void} [cfg.refuse]
17215
+ * @param {() => Promise<void>} [cfg.close]
17216
+ * @param {() => void} [cfg.closeBrowserNotGranting]
16695
17217
  * @returns {[
16696
- * HTMLDialogElement, HTMLDialogElement, HTMLDialogElement,
17218
+ * HTMLDialogElement, HTMLDialogElement|"", HTMLDialogElement|"",
16697
17219
  * HTMLDialogElement, HTMLDialogElement, HTMLDialogElement
16698
17220
  * ]}
16699
17221
  */
@@ -16716,8 +17238,10 @@ const Templates = {
16716
17238
  }, []]]]
16717
17239
  // ['textarea', {readonly: true, style: 'width: 80%; height: 80%;'}]
16718
17240
  ]);
17241
+
17242
+ /** @type {""|HTMLDialogElement} */
16719
17243
  let requestPermissionsDialog = '';
16720
- if (ok) {
17244
+ if (ok && refuse && close) {
16721
17245
  requestPermissionsDialog = jml('dialog', {
16722
17246
  id: 'willRequestStoragePermissions',
16723
17247
  $on: {
@@ -16738,6 +17262,8 @@ const Templates = {
16738
17262
  const errorRegisteringNotice = jml('dialog', {
16739
17263
  id: 'errorRegistering'
16740
17264
  }, [['section', [siteI18n('errorRegistering')]]]);
17265
+
17266
+ /** @type {""|HTMLDialogElement} */
16741
17267
  let browserNotGrantingPersistenceAlert = '';
16742
17268
  if (closeBrowserNotGranting) {
16743
17269
  browserNotGrantingPersistenceAlert = jml('dialog', {
@@ -16769,10 +17295,10 @@ const Templates = {
16769
17295
  * @file Note that this should be kept as a polyglot client-server file.
16770
17296
  */
16771
17297
  /**
16772
- *
16773
- * @param {string} param
16774
- * @param {boolean} skip
16775
17298
  * @this {IntlURLSearchParams}
17299
+ * @param {string} param
17300
+ * @param {boolean} [skip]
17301
+ * @throws {Error}
16776
17302
  * @returns {string}
16777
17303
  */
16778
17304
  function _prepareParam(param, skip) {
@@ -16784,42 +17310,84 @@ function _prepareParam(param, skip) {
16784
17310
  // start, end, toggle
16785
17311
  const endNums = /\d+(-\d+)?$/;
16786
17312
  const indexed = param.match(endNums);
17313
+ if (!this.l10n) {
17314
+ throw new Error('l10n is not defined');
17315
+ }
16787
17316
  if (indexed) {
16788
17317
  // Todo: We could i18nize numbers as well
16789
17318
  return this.l10n(['params', 'indexed', param.replace(endNums, '')]) + indexed[0];
16790
17319
  }
16791
- return this.l10n(['params', param]);
17320
+ return /** @type {string} */this.l10n(['params', param]);
16792
17321
  }
16793
17322
  class IntlURLSearchParams {
17323
+ /**
17324
+ * @param {object} [options]
17325
+ * @param {import('intl-dom').I18NCallback} [options.l10n]
17326
+ * @param {URLSearchParams|string} [options.params]
17327
+ */
16794
17328
  constructor() {
16795
17329
  let {
16796
17330
  l10n,
16797
17331
  params
16798
17332
  } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
16799
17333
  this.l10n = l10n;
17334
+ this.localizeParamNames = false;
16800
17335
  if (!params) {
16801
17336
  params = location.hash.slice(1);
16802
17337
  }
16803
17338
  if (typeof params === 'string') {
16804
17339
  params = new URLSearchParams(params);
16805
17340
  }
17341
+ /** @type {URLSearchParams} */
16806
17342
  this.params = params;
16807
17343
  }
17344
+ /**
17345
+ * @param {string} param
17346
+ * @param {boolean} [skip]
17347
+ * @returns {string|null}
17348
+ */
16808
17349
  get(param, skip) {
16809
17350
  return this.params.get(_prepareParam.call(this, param, skip));
16810
17351
  }
17352
+ /**
17353
+ * @param {string} param
17354
+ * @param {boolean} skip
17355
+ * @returns {string[]}
17356
+ */
16811
17357
  getAll(param, skip) {
16812
17358
  return this.params.getAll(_prepareParam.call(this, param, skip));
16813
17359
  }
17360
+ /**
17361
+ * @param {string} param
17362
+ * @param {boolean} skip
17363
+ * @returns {boolean}
17364
+ */
16814
17365
  has(param, skip) {
16815
17366
  return this.params.has(_prepareParam.call(this, param, skip));
16816
17367
  }
17368
+ /**
17369
+ * @param {string} param
17370
+ * @param {boolean} skip
17371
+ * @returns {void}
17372
+ */
16817
17373
  delete(param, skip) {
16818
17374
  return this.params.delete(_prepareParam.call(this, param, skip));
16819
17375
  }
17376
+ /**
17377
+ * @param {string} param
17378
+ * @param {string} value
17379
+ * @param {boolean} skip
17380
+ * @returns {void}
17381
+ */
16820
17382
  set(param, value, skip) {
16821
17383
  return this.params.set(_prepareParam.call(this, param, skip), value);
16822
17384
  }
17385
+ /**
17386
+ * @param {string} param
17387
+ * @param {string} value
17388
+ * @param {boolean} skip
17389
+ * @returns {void}
17390
+ */
16823
17391
  append(param, value, skip) {
16824
17392
  return this.params.append(_prepareParam.call(this, param, skip), value);
16825
17393
  }
@@ -16828,6 +17396,15 @@ class IntlURLSearchParams {
16828
17396
  }
16829
17397
  }
16830
17398
 
17399
+ /**
17400
+ * @param {{
17401
+ * files: string,
17402
+ * lang: string[],
17403
+ * fallbackLanguages: string[],
17404
+ * $p: import('./utils/IntlURLSearchParams.js').default,
17405
+ * followParams: (formSelector: string, cb: () => void) => void
17406
+ * }} cfg
17407
+ */
16831
17408
  async function workSelect(_ref) {
16832
17409
  let {
16833
17410
  files,
@@ -16868,7 +17445,7 @@ async function workSelect(_ref) {
16868
17445
  };
16869
17446
  }
16870
17447
  });
16871
- document.title = workI18n('browserfile-workselect');
17448
+ document.title = /** @type {string} */workI18n('browserfile-workselect');
16872
17449
  /*
16873
17450
  // Would need adapting now that not using IMF
16874
17451
  function lDirectional (key, substitutions, formats) {
@@ -16904,22 +17481,63 @@ async function workSelect(_ref) {
16904
17481
  }
16905
17482
 
16906
17483
  // Todo: Reimplement this with `formSerialize.deserialize` as possible
17484
+
17485
+
17486
+ /**
17487
+ * @param {URLSearchParams} paramsCopy
17488
+ */
16907
17489
  const replaceHash = paramsCopy => {
16908
17490
  return location.href.replace(/#.*$/, '') + '#' + paramsCopy.toString();
16909
17491
  };
16910
- const getSerializeParamsAsURL = function () {
16911
- const setter = getParamsSetter(...arguments);
16912
- return function () {
16913
- const paramsCopy = setter(...arguments);
17492
+
17493
+ /**
17494
+ * @param {{
17495
+ * l: import('intl-dom').I18NCallback,
17496
+ * lParam: (key: string) => string,
17497
+ * $p: import('./IntlURLSearchParams.js').default
17498
+ * }} args
17499
+ */
17500
+ const getSerializeParamsAsURL = function (args) {
17501
+ const setter = getParamsSetter(args);
17502
+ /**
17503
+ * @param {{
17504
+ * form: HTMLFormElement,
17505
+ * random: {checked: boolean},
17506
+ * checkboxes: HTMLInputElement[],
17507
+ * type: string,
17508
+ * fieldAliasOrNames: string[],
17509
+ * workName: string
17510
+ * }} innerArg
17511
+ */
17512
+ return function (innerArg) {
17513
+ const paramsCopy = setter(innerArg);
16914
17514
  return replaceHash(paramsCopy);
16915
17515
  };
16916
17516
  };
17517
+
17518
+ /**
17519
+ * @param {{
17520
+ * l: import('intl-dom').I18NCallback,
17521
+ * lParam: (key: string) => string,
17522
+ * $p: import('./IntlURLSearchParams.js').default
17523
+ * }} cfg
17524
+ */
16917
17525
  const getParamsSetter = function (_ref) {
16918
17526
  let {
16919
17527
  l,
16920
17528
  lParam,
16921
17529
  $p
16922
17530
  } = _ref;
17531
+ /**
17532
+ * @param {{
17533
+ * form: HTMLFormElement,
17534
+ * random: {checked: boolean},
17535
+ * checkboxes: HTMLInputElement[],
17536
+ * type: string,
17537
+ * fieldAliasOrNames: string[],
17538
+ * workName: string
17539
+ * }} cfg
17540
+ */
16923
17541
  return function (_ref2) {
16924
17542
  let {
16925
17543
  form,
@@ -16942,7 +17560,8 @@ const getParamsSetter = function (_ref) {
16942
17560
 
16943
17561
  // Follow the same style (and order) for checkboxes
16944
17562
  paramsCopy.delete(lParam('rand'));
16945
- paramsCopy.set(lParam('rand'), random.checked ? l('yes') : l('no'));
17563
+ paramsCopy.set(lParam('rand'), /** @type {string} */
17564
+ random.checked ? l('yes') : l('no'));
16946
17565
 
16947
17566
  // We want checkboxes to typically show by default, so we cannot use the
16948
17567
  // standard serialization
@@ -16951,7 +17570,8 @@ const getParamsSetter = function (_ref) {
16951
17570
  paramsCopy.delete(checkbox.name);
16952
17571
  if (checkbox.name) {
16953
17572
  // We don't want, e.g., preference controls added to URL
16954
- paramsCopy.set(checkbox.name, checkbox.checked ? l('yes') : l('no'));
17573
+ paramsCopy.set(checkbox.name, /** @type {string} */
17574
+ checkbox.checked ? l('yes') : l('no'));
16955
17575
  }
16956
17576
  });
16957
17577
 
@@ -16962,11 +17582,11 @@ const getParamsSetter = function (_ref) {
16962
17582
  function removeStartsEndsAndAnchors() {
16963
17583
  let num = 1;
16964
17584
  let num2 = 1;
16965
- while (paramsCopy.has(`${workName}-start${num}-${num2}`, true)) {
16966
- while (paramsCopy.has(`${workName}-start${num}-${num2}`, true)) {
16967
- paramsCopy.delete(`${workName}-start${num}-${num2}`, true);
16968
- paramsCopy.delete(`${workName}-end${num}-${num2}`, true);
16969
- paramsCopy.delete(`${workName}-anchor${num}-${num2}`, true);
17585
+ while (paramsCopy.has(`${workName}-start${num}-${num2}`)) {
17586
+ while (paramsCopy.has(`${workName}-start${num}-${num2}`)) {
17587
+ paramsCopy.delete(`${workName}-start${num}-${num2}`);
17588
+ paramsCopy.delete(`${workName}-end${num}-${num2}`);
17589
+ paramsCopy.delete(`${workName}-anchor${num}-${num2}`);
16970
17590
  num2++;
16971
17591
  }
16972
17592
  num2 = 1;
@@ -16985,28 +17605,28 @@ const getParamsSetter = function (_ref) {
16985
17605
  {
16986
17606
  paramsCopy.delete(lParam('rand'));
16987
17607
  let num = 1;
16988
- while (paramsCopy.has(`anchorfield${num}`, true)) {
16989
- paramsCopy.delete(`anchorfield${num}`, true);
17608
+ while (paramsCopy.has(`anchorfield${num}`)) {
17609
+ paramsCopy.delete(`anchorfield${num}`);
16990
17610
  num++;
16991
17611
  }
16992
17612
  removeStartsEndsAndAnchors();
16993
17613
  num = 1;
16994
17614
  // Delete field-specific so we can add our own
16995
- while (paramsCopy.has(`field${num}`, true)) {
16996
- paramsCopy.delete(`field${num}`, true);
16997
- paramsCopy.delete(`checked${num}`, true);
16998
- paramsCopy.delete(`interlin${num}`, true);
16999
- paramsCopy.delete(`css${num}`, true);
17615
+ while (paramsCopy.has(`field${num}`)) {
17616
+ paramsCopy.delete(`field${num}`);
17617
+ paramsCopy.delete(`checked${num}`);
17618
+ paramsCopy.delete(`interlin${num}`);
17619
+ paramsCopy.delete(`css${num}`);
17000
17620
  num++;
17001
17621
  }
17002
17622
  fieldAliasOrNames.forEach((fieldAliasOrName, i) => {
17003
- paramsCopy.set(`field${i + 1}`, fieldAliasOrName, true);
17623
+ paramsCopy.set(`field${i + 1}`, fieldAliasOrName);
17004
17624
  // Todo: Restrict by content locale?
17005
- paramsCopy.set(`checked${i + 1}`, l('yes'), true);
17625
+ paramsCopy.set(`checked${i + 1}`, /** @type {string} */l('yes'));
17006
17626
  paramsCopy.set(`interlin${i + 1}`, '');
17007
17627
  paramsCopy.set(`css${i + 1}`, '');
17008
17628
  });
17009
- paramsCopy.delete('work', true);
17629
+ paramsCopy.delete('work');
17010
17630
  }
17011
17631
  // Fallthrough
17012
17632
  case 'startEndResult':
@@ -17020,9 +17640,9 @@ const getParamsSetter = function (_ref) {
17020
17640
  // let's put random again toward the end.
17021
17641
  if (type === 'randomResult' || random.checked) {
17022
17642
  paramsCopy.delete(lParam('rand'));
17023
- paramsCopy.set(lParam('rand'), l('yes'));
17643
+ paramsCopy.set(lParam('rand'), /** @type {string} */l('yes'));
17024
17644
  }
17025
- paramsCopy.set(lParam('result'), l('yes'));
17645
+ paramsCopy.set(lParam('result'), /** @type {string} */l('yes'));
17026
17646
  break;
17027
17647
  }
17028
17648
  default:
@@ -17034,6 +17654,18 @@ const getParamsSetter = function (_ref) {
17034
17654
  };
17035
17655
  };
17036
17656
 
17657
+ /**
17658
+ * @this {import('./index.js').default}
17659
+ * @param {{
17660
+ * l: import('intl-dom').I18NCallback,
17661
+ * languageParam: string,
17662
+ * lang: string[],
17663
+ * preferredLocale: string,
17664
+ * languages: import('./utils/Languages.js').Languages,
17665
+ * fallbackLanguages: string[],
17666
+ * $p: import('./utils/IntlURLSearchParams.js').default
17667
+ * }} cfg
17668
+ */
17037
17669
  async function workDisplay(_ref) {
17038
17670
  let {
17039
17671
  l,
@@ -17225,7 +17857,7 @@ async function workDisplay(_ref) {
17225
17857
  fallbackLanguages,
17226
17858
  preferredLocale,
17227
17859
  languages,
17228
- work: $p.get('work')
17860
+ work: (/** @type {string} */$p.get('work'))
17229
17861
  });
17230
17862
  document.title = workI18n('browserfile-workdisplay', {
17231
17863
  work: fileData ? getMetaProp(lang, metadataObj, 'alias') : ''
@@ -17672,6 +18304,9 @@ Locale._BIDI_RTL_LANGS = [
17672
18304
  'zdj' // Comorian, Ngazidja
17673
18305
  ];
17674
18306
 
18307
+ /**
18308
+ * @param {string} locale
18309
+ */
17675
18310
  const getLangDir = locale => {
17676
18311
  const {
17677
18312
  direction
@@ -17885,7 +18520,7 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
17885
18520
  tr,
17886
18521
  foundState
17887
18522
  } = _ref9;
17888
- const rowIDPartsPreferred = [];
18523
+ const rowIDPartsPreferred = /** @type {string[]} */[];
17889
18524
  const rowIDParts = applicableBrowseFieldNames.map(fieldName => {
17890
18525
  const idx = localizedFieldNames.indexOf(fieldName);
17891
18526
  // This works to put alias in anchor but this includes
@@ -18120,7 +18755,7 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
18120
18755
  const p = $p.get(param, true);
18121
18756
  /**
18122
18757
  *
18123
- * @param {GenericArray|PlainObject} locale
18758
+ * @param {GenericArray|object} locale
18124
18759
  * @returns {boolean}
18125
18760
  */
18126
18761
  function reverseLocaleLookup(locale) {
@@ -18640,7 +19275,16 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
18640
19275
  };
18641
19276
 
18642
19277
  /**
18643
- *
19278
+ * @typedef {{
19279
+ * 'localization-strings': {
19280
+ * [locale: string]: {
19281
+ * [key: string]: string
19282
+ * }
19283
+ * }
19284
+ * }} SiteData
19285
+ */
19286
+ /**
19287
+ * @this {TextBrowser}
18644
19288
  * @returns {Promise<void>}
18645
19289
  */
18646
19290
  async function prepareForServiceWorker() {
@@ -18667,32 +19311,29 @@ async function prepareForServiceWorker() {
18667
19311
  } catch (err) {
18668
19312
  console.log('err', err);
18669
19313
  if (err && typeof err === 'object') {
18670
- const {
18671
- errorType
18672
- } = err;
18673
- if (errorType === 'versionChange') {
19314
+ if ('errorType' in err && err.errorType === 'versionChange') {
18674
19315
  Templates.permissions.versionChange();
18675
19316
  return;
18676
19317
  }
18677
19318
  }
18678
- Templates.permissions.errorRegistering(escapeHTML(err && err.message));
19319
+ Templates.permissions.errorRegistering(escapeHTML(/** @type {Error} */err?.message));
18679
19320
  }
18680
19321
  }
18681
19322
 
18682
19323
  /**
18683
- * @typedef {PlainObject} Langs
19324
+ * @typedef {object} Langs
18684
19325
  * @property {string} code
18685
19326
  * @property {string} direction
18686
- * @property {PlainObject} locale
19327
+ * @property {object} locale
18687
19328
  */
18688
19329
 
18689
19330
  /**
18690
- *
18691
- * @param {Langs} langs
18692
- * @param {Logger} l
19331
+ * @this {TextBrowser}
19332
+ * @param {import('../server/main.js').LanguageInfo[]} _langs
19333
+ * @param {import('intl-dom').I18NCallback} siteI18n
18693
19334
  * @returns {Promise<void>}
18694
19335
  */
18695
- async function requestPermissions(langs, l) {
19336
+ async function requestPermissions(_langs, siteI18n) {
18696
19337
  return await new Promise(resolve => {
18697
19338
  // Todo: We could run the dialog code below for every page if
18698
19339
  // `Notification.permission === 'default'` (i.e., not choice
@@ -18716,18 +19357,19 @@ async function requestPermissions(langs, l) {
18716
19357
  *
18717
19358
  * @returns {void}
18718
19359
  */
18719
- function rememberRefusal() {
19360
+ const rememberRefusal = () => {
18720
19361
  // Todo: We could go forward with worker, caching files, and
18721
19362
  // indexedDB regardless of permissions, but this way
18722
19363
  // we can continue to gauge performance differences for now
18723
19364
  localStorage.setItem(this.namespace + '-refused', 'true');
18724
- }
19365
+ };
18725
19366
  try {
18726
19367
  if (!requestPermissionsDialog.returnValue) {
18727
19368
  rememberRefusal();
18728
19369
  return;
18729
19370
  }
18730
- } catch (err) {
19371
+ } catch (error) {
19372
+ const err = /** @type {Error} */error;
18731
19373
  console.log('err', err);
18732
19374
  Templates.permissions.errorRegistering(escapeHTML(err && err.message));
18733
19375
  }
@@ -18758,19 +19400,48 @@ async function requestPermissions(langs, l) {
18758
19400
  break;
18759
19401
  }
18760
19402
  };
18761
- const [, requestPermissionsDialog, browserNotGrantingPersistenceAlert] =
19403
+ const permissionsInfo =
18762
19404
  // , errorRegisteringNotice
18763
19405
  Templates.permissions.main({
18764
- l,
19406
+ siteI18n,
18765
19407
  ok,
18766
19408
  refuse,
18767
19409
  close,
18768
19410
  closeBrowserNotGranting
18769
19411
  });
19412
+ const requestPermissionsDialog = /** @type {HTMLDialogElement} */permissionsInfo[1];
19413
+ const browserNotGrantingPersistenceAlert = /** @type {HTMLDialogElement} */
19414
+ permissionsInfo[2];
18770
19415
  requestPermissionsDialog.showModal();
18771
19416
  });
18772
19417
  }
19418
+
19419
+ /**
19420
+ * @typedef {import('./utils/ServiceWorker.js').ServiceWorkerConfig} ServiceWorkerConfig
19421
+ */
19422
+
19423
+ /**
19424
+ * @implements {ServiceWorkerConfig}
19425
+ */
18773
19426
  class TextBrowser {
19427
+ /**
19428
+ * @param {ServiceWorkerConfig & {
19429
+ * site?: string,
19430
+ * stylesheets?: string[],
19431
+ * allowPlugins?: boolean,
19432
+ * dynamicBasePath?: string,
19433
+ * trustFormatHTML?: boolean,
19434
+ * requestPersistentStorage?: boolean,
19435
+ * localizeParamNames?: boolean,
19436
+ * hideFormattingSection?: boolean,
19437
+ * preferencesPlugin?: string,
19438
+ * interlinearSeparator?: string,
19439
+ * showEmptyInterlinear?: boolean,
19440
+ * showTitleOnSingleInterlinear?: boolean,
19441
+ * noDynamic?: boolean,
19442
+ * skipIndexedDB?: boolean
19443
+ * }} options
19444
+ */
18774
19445
  constructor(options) {
18775
19446
  this.site = options.site || 'site.json';
18776
19447
  const stylesheets = options.stylesheets || ['@builtin'];
@@ -18779,6 +19450,25 @@ class TextBrowser {
18779
19450
  stylesheets.splice(builtinIndex, 1, new URL(new URL('assets/index-D_XVedS3.css', import.meta.url).href, import.meta.url).href);
18780
19451
  }
18781
19452
  this.stylesheets = stylesheets;
19453
+
19454
+ // Satisfy TS
19455
+
19456
+ /** @type {SiteData} */
19457
+ this.siteData = {
19458
+ 'localization-strings': {}
19459
+ };
19460
+ /** @type {import('../server/main.js').LanguagesData} */
19461
+ this.langData = {
19462
+ languages: [],
19463
+ 'localization-strings': {}
19464
+ };
19465
+ /** @type {string[]} */
19466
+ this.lang = [];
19467
+ this.userJSON = '';
19468
+ this.languages = '';
19469
+ this.serviceWorkerPath = '';
19470
+ this.files = '';
19471
+ this.namespace = '';
18782
19472
  setServiceWorkerDefaults(this, options);
18783
19473
  this.allowPlugins = options.allowPlugins;
18784
19474
  this.dynamicBasePath = options.dynamicBasePath;
@@ -18799,9 +19489,16 @@ class TextBrowser {
18799
19489
 
18800
19490
  // We use getJSON instead of JsonRefs as we do not need to resolve the locales here
18801
19491
  try {
18802
- const [langData, siteData] = await getJSON([this.languages, this.site]);
18803
- this.langData = langData;
18804
- this.siteData = siteData;
19492
+ const data =
19493
+ /**
19494
+ * @type {[
19495
+ * import('../server/main.js').LanguagesData,
19496
+ * SiteData
19497
+ * ]}
19498
+ */
19499
+ await getJSON([this.languages, this.site]);
19500
+ this.langData = data[0];
19501
+ this.siteData = data[1];
18805
19502
  const p = this.paramChange();
18806
19503
 
18807
19504
  // INIT/ADD EVENTS
@@ -18809,11 +19506,16 @@ class TextBrowser {
18809
19506
  // and just check `history.state`
18810
19507
  window.addEventListener('hashchange', () => this.paramChange());
18811
19508
  return p;
18812
- } catch (err) {
19509
+ } catch (error) {
19510
+ const err = /** @type {Error} */error;
18813
19511
  console.log('err', err);
18814
19512
  dialogs.alert(err);
18815
19513
  }
18816
19514
  }
19515
+
19516
+ /**
19517
+ * @param {import('./utils/WorkInfo.js').GetWorkDataOptions} opts
19518
+ */
18817
19519
  getWorkData(opts) {
18818
19520
  try {
18819
19521
  return getWorkData.call(this, {
@@ -18830,6 +19532,10 @@ class TextBrowser {
18830
19532
  // Need for directionality even if language specified (and we don't want
18831
19533
  // to require it as a param)
18832
19534
  // Todo: Use intl-locale-textinfo-polyfill (already included)
19535
+
19536
+ /**
19537
+ * @param {string} code
19538
+ */
18833
19539
  getDirectionForLanguageCode(code) {
18834
19540
  const langs = this.langData.languages;
18835
19541
  const exactMatch = langs.find(lang => {
@@ -18839,12 +19545,21 @@ class TextBrowser {
18839
19545
  return lang.code.startsWith(code + '-');
18840
19546
  });
18841
19547
  }
19548
+
19549
+ /**
19550
+ * @param {import('./utils/Metadata.js').GetFieldNameAndValueAliasesOptions} args
19551
+ */
18842
19552
  getFieldNameAndValueAliases(args) {
18843
19553
  return getFieldNameAndValueAliases({
18844
19554
  ...args,
18845
19555
  lang: this.lang
18846
19556
  });
18847
19557
  }
19558
+
19559
+ /**
19560
+ * @param {import('./utils/Metadata.js').GetBrowseFieldDataOptions} args
19561
+ * @returns {void}
19562
+ */
18848
19563
  getBrowseFieldData(args) {
18849
19564
  return getBrowseFieldData({
18850
19565
  ...args,
@@ -18859,6 +19574,10 @@ class TextBrowser {
18859
19574
  params: history.state
18860
19575
  }) : new IntlURLSearchParams(); // Uses URL hash for params
18861
19576
 
19577
+ /**
19578
+ * @param {string} formSelector
19579
+ * @param {() => void} cb
19580
+ */
18862
19581
  const followParams = (formSelector, cb) => {
18863
19582
  const form = document.querySelector(formSelector);
18864
19583
  // Record current URL along with state
@@ -18886,25 +19605,26 @@ class TextBrowser {
18886
19605
  const [preferredLocale] = lang;
18887
19606
  const direction = this.getDirectionForLanguageCode(preferredLocale);
18888
19607
  document.documentElement.lang = preferredLocale;
18889
- document.dir = direction;
19608
+ document.dir = /** @type {string} */direction;
18890
19609
  const localizationStrings = this.siteData['localization-strings'];
18891
19610
  const siteI18n = await i18n({
18892
19611
  messageStyle: 'plainNested',
18893
19612
  locales: lang,
18894
19613
  defaultLocales: fallbackLanguages,
18895
- localeStringFinder(_ref) {
19614
+ async localeStringFinder() {
18896
19615
  let {
18897
19616
  locales,
18898
19617
  defaultLocales
18899
- } = _ref;
18900
- const locale = [...locales, ...defaultLocales].find(language => {
19618
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
19619
+ const locale = [...(/** @type {string[]} */locales), ...(/** @type {string[]} */defaultLocales)].find(language => {
18901
19620
  return language in localizationStrings;
18902
19621
  });
18903
19622
  return {
18904
- locale,
19623
+ // eslint-disable-next-line object-shorthand -- TS
19624
+ locale: (/** @type {string} */locale),
18905
19625
  strings: {
18906
19626
  head: {},
18907
- body: localizationStrings[locale]
19627
+ body: localizationStrings[(/** @type {string} */locale)]
18908
19628
  }
18909
19629
  };
18910
19630
  }
@@ -18912,7 +19632,7 @@ class TextBrowser {
18912
19632
 
18913
19633
  // Even if individual pages may end up changing, we need a
18914
19634
  // title now for accessibility
18915
- document.title = siteI18n('browser-title');
19635
+ document.title = /** @type {string} */siteI18n('browser-title');
18916
19636
  const refusedIndexedDB =
18917
19637
  // User may have persistence via bookmarks, etc. but just not
18918
19638
  // want commital on notification
@@ -19009,8 +19729,8 @@ class TextBrowser {
19009
19729
  try {
19010
19730
  return respondToState({
19011
19731
  r,
19012
- langs,
19013
- languages: this.languages,
19732
+ // langs,
19733
+ // languages: this.languages,
19014
19734
  logger: Templates.permissions
19015
19735
  });
19016
19736
  } catch (err) {
@@ -19039,13 +19759,13 @@ class TextBrowser {
19039
19759
  // We don't await the fulfillment of this promise
19040
19760
  respondToStateOfWorker();
19041
19761
  listenForWorkerUpdate({
19042
- r,
19043
- logger: {
19044
- addLogEntry(s) {
19045
- // We don't put the log in the page as user using
19046
- console.log(s);
19047
- }
19048
- }
19762
+ r
19763
+ // logger: {
19764
+ // addLogEntry (s) {
19765
+ // // We don't put the log in the page as user using
19766
+ // console.log(s);
19767
+ // }
19768
+ // }
19049
19769
  });
19050
19770
  // Don't return as user may continue working until installed (though
19051
19771
  // will get message to close tab)
@@ -19070,6 +19790,12 @@ class TextBrowser {
19070
19790
  Please wait for a short while as we work to update to a new version.
19071
19791
  `);
19072
19792
  respondToStateOfWorker();
19793
+ /**
19794
+ * @type {(
19795
+ * this: ServiceWorkerContainer,
19796
+ * ev: {data: string}
19797
+ * ) => any}
19798
+ */
19073
19799
  navigator.serviceWorker.onmessage({
19074
19800
  data: 'finishActivate'
19075
19801
  });
@@ -19084,13 +19810,13 @@ class TextBrowser {
19084
19810
  // May need to pass in arguments if new service worker appears and
19085
19811
  // it needs arguments for update
19086
19812
  listenForWorkerUpdate({
19087
- r,
19088
- logger: {
19089
- addLogEntry(s) {
19090
- // We don't put the log in the page as user using
19091
- console.log(s);
19092
- }
19093
- }
19813
+ r
19814
+ // logger: {
19815
+ // addLogEntry (s) {
19816
+ // // We don't put the log in the page as user using
19817
+ // console.log(s);
19818
+ // }
19819
+ // }
19094
19820
  });
19095
19821
  break;
19096
19822
  case 'redundant':
@@ -19112,7 +19838,7 @@ class TextBrowser {
19112
19838
  // Also could use siteI18n('chooselanguage'), but assumes locale
19113
19839
  // as with page title
19114
19840
  // $p.l10n = siteI18n; // Is this in use? No `params`, so not currently
19115
- document.title = siteI18n('languages-title');
19841
+ document.title = /** @type {string} */siteI18n('languages-title');
19116
19842
  Templates.languageSelect.main({
19117
19843
  langs,
19118
19844
  languages,
@@ -19151,8 +19877,8 @@ class TextBrowser {
19151
19877
  fallbackLanguages,
19152
19878
  languageParam,
19153
19879
  $p,
19154
- languages,
19155
- preferencesPlugin: this.preferencesPlugin
19880
+ languages
19881
+ // preferencesPlugin: this.preferencesPlugin
19156
19882
  });
19157
19883
  return true;
19158
19884
  }