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
@@ -16,7 +16,7 @@ const Templates = {
16
16
  // We empty rather than `replaceWith` as our Jamilih `body`
17
17
  // aliases expect the old instance
18
18
  while (body.hasChildNodes()) {
19
- body.firstChild.remove();
19
+ body.firstChild?.remove();
20
20
  }
21
21
  return jml('div', {
22
22
  id: 'main', role: 'main'
@@ -24,19 +24,25 @@ const Templates = {
24
24
  },
25
25
  permissions: {
26
26
  versionChange () {
27
- $('#versionChange').showModal();
27
+ /** @type {HTMLDialogElement} */
28
+ ($('#versionChange'))?.showModal();
28
29
  },
30
+
31
+ /**
32
+ * @param {{text: string}} cfg
33
+ */
29
34
  addLogEntry ({text}) {
30
35
  const installationDialog = $('#installationLogContainer');
31
36
  try {
32
- installationDialog.showModal();
33
- const container = $('#dialogContainer');
37
+ /** @type {HTMLDialogElement} */
38
+ (installationDialog).showModal();
39
+ const container = /** @type {HTMLElement} */ ($('#dialogContainer'));
34
40
  container.hidden = false;
35
41
  // eslint-disable-next-line no-unused-vars -- Ok
36
42
  } catch (err) {
37
43
  // May already be open
38
44
  }
39
- $('#installationLog').append(text + '\n');
45
+ /** @type {HTMLElement} */ ($('#installationLog')).append(text + '\n');
40
46
  },
41
47
  exitDialogs () {
42
48
  const container = $('#dialogContainer');
@@ -44,6 +50,12 @@ const Templates = {
44
50
  container.hidden = true;
45
51
  }
46
52
  },
53
+ /**
54
+ * @param {{
55
+ * type: string,
56
+ * escapedErrorMessage: string
57
+ * }} cfg
58
+ */
47
59
  dbError ({type, escapedErrorMessage}) {
48
60
  if (type) {
49
61
  jml('span', [
@@ -51,26 +63,33 @@ const Templates = {
51
63
  escapedErrorMessage
52
64
  ], $('#dbError'));
53
65
  }
54
- $('#dbError').showModal();
66
+ /** @type {HTMLDialogElement} */
67
+ ($('#dbError')).showModal();
55
68
  },
69
+
70
+ /**
71
+ * @param {string} escapedErrorMessage
72
+ */
56
73
  errorRegistering (escapedErrorMessage) {
57
74
  if (escapedErrorMessage) {
58
75
  jml('span', [escapedErrorMessage], $('#errorRegistering'));
59
76
  }
60
- $('#errorRegistering').showModal();
77
+ /** @type {HTMLDialogElement} */
78
+ ($('#errorRegistering')).showModal();
61
79
  },
62
80
  browserNotGrantingPersistence () {
63
- $('#browserNotGrantingPersistence').showModal();
81
+ /** @type {HTMLDialogElement} */
82
+ ($('#browserNotGrantingPersistence')).showModal();
64
83
  },
65
84
  /**
66
- * @param {PlainObject} cfg
67
- * @param {I18NCallback} cfg.siteI18n
68
- * @param {() => Promise<void>} cfg.ok
69
- * @param {() => void} cfg.refuse
70
- * @param {() => Promise<void>} cfg.close
71
- * @param {() => void} cfg.closeBrowserNotGranting
85
+ * @param {object} cfg
86
+ * @param {import('intl-dom').I18NCallback} cfg.siteI18n
87
+ * @param {() => Promise<void>} [cfg.ok]
88
+ * @param {() => void} [cfg.refuse]
89
+ * @param {() => Promise<void>} [cfg.close]
90
+ * @param {() => void} [cfg.closeBrowserNotGranting]
72
91
  * @returns {[
73
- * HTMLDialogElement, HTMLDialogElement, HTMLDialogElement,
92
+ * HTMLDialogElement, HTMLDialogElement|"", HTMLDialogElement|"",
74
93
  * HTMLDialogElement, HTMLDialogElement, HTMLDialogElement
75
94
  * ]}
76
95
  */
@@ -89,8 +108,10 @@ const Templates = {
89
108
  ]]
90
109
  // ['textarea', {readonly: true, style: 'width: 80%; height: 80%;'}]
91
110
  ]);
111
+
112
+ /** @type {""|HTMLDialogElement} */
92
113
  let requestPermissionsDialog = '';
93
- if (ok) {
114
+ if (ok && refuse && close) {
94
115
  requestPermissionsDialog = jml(
95
116
  'dialog', {
96
117
  id: 'willRequestStoragePermissions',
@@ -121,6 +142,8 @@ const Templates = {
121
142
  ]]
122
143
  ]
123
144
  );
145
+
146
+ /** @type {""|HTMLDialogElement} */
124
147
  let browserNotGrantingPersistenceAlert = '';
125
148
  if (closeBrowserNotGranting) {
126
149
  browserNotGrantingPersistenceAlert = jml(
@@ -1,7 +1,17 @@
1
1
  import {jml, $} from 'jamilih';
2
+
3
+ // @ts-expect-error Missing TS types
2
4
  import {deserialize as formDeserialize} from 'form-serialization';
3
5
 
4
6
  export default {
7
+ /**
8
+ * @param {{
9
+ * langs: import('../../server/main.js').LanguageInfo[]
10
+ * languages: import('../utils/Languages.js').Languages
11
+ * followParams: (formSelector: string, cb: () => void) => void
12
+ * $p: import('../utils/IntlURLSearchParams.js').default
13
+ * }} cfg
14
+ */
5
15
  main ({langs, languages, followParams, $p}) {
6
16
  jml('form', {class: 'focus', id: 'languageSelectionContainer', $on: {
7
17
  submit (e) {
@@ -12,7 +22,10 @@ export default {
12
22
  name: 'lang',
13
23
  size: langs.length,
14
24
  $on: {
15
- click ({target: {parentNode: {selectedOptions}}}) {
25
+ click ({target: {parentNode: {
26
+ // @ts-expect-error Ok
27
+ selectedOptions
28
+ }}}) {
16
29
  followParams('#languageSelectionContainer', () => {
17
30
  $p.set('lang', selectedOptions[0].value, true);
18
31
  });
@@ -3,9 +3,20 @@ import Templates from './index.js';
3
3
  import {dialogs} from '../utils/dialogs.js';
4
4
 
5
5
  export default {
6
+ /**
7
+ * @param {{
8
+ * anchorRowCol: string
9
+ * }} cfg
10
+ */
6
11
  anchorRowCol ({anchorRowCol}) {
7
12
  return $('#' + anchorRowCol);
8
13
  },
14
+ /**
15
+ * @param {{
16
+ * escapedRow: string
17
+ * escapedCol: string|undefined
18
+ * }} cfg
19
+ */
9
20
  anchors ({escapedRow, escapedCol}) {
10
21
  const sel = 'tr[data-row="' + escapedRow + '"]' +
11
22
  (escapedCol
@@ -13,16 +24,24 @@ export default {
13
24
  : '');
14
25
  return $(sel);
15
26
  },
16
- main (...args) {
27
+
28
+ /**
29
+ * @param {import('./resultsDisplayServerOrClient.js').ResultsDisplayServerOrClientArgs} args
30
+ */
31
+ main (args) {
17
32
  let html;
18
33
  try {
19
- html = Templates.resultsDisplayServerOrClient.main(...args);
20
- } catch (err) {
34
+ html = /** @type {import('jamilih').JamilihArray} */ (
35
+ Templates.resultsDisplayServerOrClient.main(args)
36
+ );
37
+ } catch (error) {
38
+ const err = /** @type {Error} */ (error);
21
39
  if (err.message === 'JSON support is currently not available') {
22
40
  dialogs.alert(err.message);
23
41
  } else {
24
42
  console.error(err);
25
43
  }
44
+ return;
26
45
  }
27
46
  jml(...html, $('#main'));
28
47
  }
@@ -1,26 +1,96 @@
1
1
  import Templates from './index.js';
2
2
 
3
+ /**
4
+ * @typedef {number} Integer
5
+ */
6
+ /**
7
+ * @typedef {{
8
+ * interlinearSeparator?: string,
9
+ * showEmptyInterlinear?: boolean,
10
+ * showTitleOnSingleInterlinear?: boolean,
11
+ * tableData: (string|Integer)[][],
12
+ * $p: import('../utils/IntlURLSearchParams.js').default,
13
+ * $pRaw: (key: string, avoidLog?: boolean) => string,
14
+ * $pRawEsc: (str: string) => string,
15
+ * $pEscArbitrary: (str: string) => string,
16
+ * escapeQuotedCSS: (str: string) => string,
17
+ * escapeCSS: (str: string) => string,
18
+ * escapeHTML: (str: string) => string,
19
+ * l: import('intl-dom').I18NCallback,
20
+ * localizedFieldNames: (string|string[]|import('../../server/main.js').LocalizationStrings)[],
21
+ * fieldLangs: (string|null)[],
22
+ * fieldDirs: (string | null)[],
23
+ * caption?: string,
24
+ * hasCaption: boolean,
25
+ * showInterlinTitles: boolean,
26
+ * determineEnd: import('../resultsDisplay.js').DetermineEnd,
27
+ * getCanonicalID: import('../resultsDisplay.js').GetCanonicalID,
28
+ * canonicalBrowseFieldSetName: string,
29
+ * getCellValue: import('../resultsDisplay.js').GetCellValue,
30
+ * checkedAndInterlinearFieldInfo: [string[], number[], ("" | number[] | null)[]]
31
+ * }} ResultsDisplayServerOrClientArgs
32
+ */
33
+
3
34
  export default {
35
+ /**
36
+ * @param {{
37
+ * heading: string,
38
+ * ranges: string
39
+ * }} cfg
40
+ */
4
41
  caption ({heading, ranges}) {
5
42
  return heading + ' ' + ranges;
6
43
  },
44
+ /**
45
+ * @param {{
46
+ * l: import('intl-dom').I18NCallback
47
+ * }} cfg
48
+ * @returns {string}
49
+ */
7
50
  startSeparator ({l}) {
8
- return l('colon');
51
+ return /** @type {string} */ (l('colon'));
9
52
  },
53
+
54
+ /**
55
+ * @param {{
56
+ * l: import('intl-dom').I18NCallback
57
+ * }} cfg
58
+ */
10
59
  innerBrowseFieldSeparator ({l}) {
11
- return l('comma-space');
60
+ return /** @type {string} */ (l('comma-space'));
12
61
  },
62
+ /**
63
+ * @param {{
64
+ * l: import('intl-dom').I18NCallback,
65
+ * startRange: string,
66
+ * endVals: string[],
67
+ * rangeNames: string
68
+ * }} cfg
69
+ */
13
70
  ranges ({l, startRange, endVals, rangeNames}) {
14
71
  return startRange +
15
- // l('to').toLowerCase() + ' ' +
16
- '-' +
17
- endVals.join(
18
- Templates.resultsDisplayServerOrClient.startSeparator({l})
19
- ) + ' (' + rangeNames + ')';
72
+ // l('to').toLowerCase() + ' ' +
73
+ '-' +
74
+ endVals.join(
75
+ Templates.resultsDisplayServerOrClient.startSeparator({l})
76
+ ) + ' (' + rangeNames + ')';
20
77
  },
78
+ /**
79
+ * @param {{
80
+ * key: string,
81
+ * value: string|number
82
+ * }} cfg
83
+ */
21
84
  fieldValueAlias ({key, value}) {
22
85
  return value + ' (' + key + ')';
23
86
  },
87
+ /**
88
+ * @param {{
89
+ * lang?: string|null,
90
+ * dir?: string|null,
91
+ * html: string
92
+ * }} cfg
93
+ */
24
94
  interlinearSegment ({lang, dir, html}) {
25
95
  return `<span${
26
96
  lang ? ` lang="${lang}"` : ''
@@ -28,10 +98,30 @@ export default {
28
98
  dir ? ` dir="${dir}"` : ''
29
99
  }>${html}</span>`;
30
100
  },
101
+
102
+ /**
103
+ * @param {{
104
+ * l: import('intl-dom').I18NCallback,
105
+ * val: string
106
+ * }} cfg
107
+ */
31
108
  interlinearTitle ({l, val}) {
32
109
  const colonSpace = l('colon-space');
33
110
  return `<span class="interlintitle">${val}</span>${colonSpace}`;
34
111
  },
112
+ /**
113
+ * @param {{
114
+ * $p: import('../utils/IntlURLSearchParams.js').default,
115
+ * $pRaw: (key: string, avoidLog?: boolean) => string,
116
+ * $pRawEsc: (str: string) => string,
117
+ * $pEscArbitrary: (str: string) => string,
118
+ * escapeCSS: (str: string) => string,
119
+ * tableWithFixedHeaderAndFooter: boolean,
120
+ * checkedFieldIndexes: number[],
121
+ * hasCaption: boolean
122
+ * }} cfg
123
+ * @returns {import('jamilih').JamilihArray}
124
+ */
35
125
  styles ({
36
126
  $p, $pRaw, $pRawEsc, $pEscArbitrary, // escapeQuotedCSS,
37
127
  escapeCSS,
@@ -176,16 +266,32 @@ body {
176
266
  : '')
177
267
  ]];
178
268
  },
269
+
270
+ /**
271
+ * @param {ResultsDisplayServerOrClientArgs} args
272
+ * @returns {import('jamilih').JamilihArray}
273
+ */
179
274
  main ({
180
275
  tableData, $p, $pRaw, $pRawEsc, $pEscArbitrary,
181
276
  // Todo: escaping should be done in business logic!
182
- escapeQuotedCSS, escapeCSS, escapeHTML,
277
+ // escapeQuotedCSS,
278
+ escapeCSS, escapeHTML,
183
279
  l, localizedFieldNames, fieldLangs, fieldDirs,
184
280
  caption, hasCaption, showInterlinTitles,
185
281
  determineEnd, getCanonicalID, canonicalBrowseFieldSetName,
186
282
  getCellValue, checkedAndInterlinearFieldInfo,
283
+ showEmptyInterlinear,
284
+ showTitleOnSingleInterlinear,
187
285
  interlinearSeparator = '<br /><br />'
188
286
  }) {
287
+ /**
288
+ * @type {{
289
+ * table: [string, (import('jamilih').JamilihAttributes | undefined)?][],
290
+ * div: [string, (import('jamilih').JamilihAttributes | undefined)?][],
291
+ * "json-array": "json",
292
+ * "json-object": "json"
293
+ * }}
294
+ */
189
295
  const tableOptions = {
190
296
  table: [
191
297
  ['table', {class: 'table', border: $pRaw('border') || '0'}],
@@ -214,7 +320,7 @@ body {
214
320
  'json-array': 'json',
215
321
  'json-object': 'json'
216
322
  };
217
- const outputmode = $p.get('outputmode', true); // Why not $pRaw?
323
+ const outputmode = /** @type {"json-object"|"json-array"|"table"|"div"} */ ($p.get('outputmode', true)); // Why not $pRaw?
218
324
 
219
325
  switch (outputmode) {
220
326
  case 'json-object': // Can later fall through if supporting
@@ -227,7 +333,7 @@ body {
227
333
  }
228
334
 
229
335
  const tableElems = tableOptions[
230
- Object.prototype.hasOwnProperty.call(tableOptions, outputmode)
336
+ Object.hasOwn(tableOptions, outputmode) && outputmode
231
337
  ? outputmode
232
338
  : 'table' // Default
233
339
  ];
@@ -236,9 +342,13 @@ body {
236
342
  ] = tableElems; // colgroupElem, colElem
237
343
 
238
344
  const [checkedFields, checkedFieldIndexes, allInterlinearColIndexes] =
239
- checkedAndInterlinearFieldInfo;
345
+ checkedAndInterlinearFieldInfo;
240
346
 
241
347
  const tableWithFixedHeaderAndFooter = $pRaw('headerfooterfixed') === 'yes';
348
+
349
+ /**
350
+ * @param {import('jamilih').JamilihChildren} children
351
+ */
242
352
  const tableWrap = (children) => {
243
353
  return tableWithFixedHeaderAndFooter
244
354
  ? ['div', {class: 'table-responsive anchor-table-header zupa'}, [
@@ -247,30 +357,44 @@ body {
247
357
  : ['div', {class: 'table-responsive'}, children];
248
358
  };
249
359
 
360
+ /**
361
+ * @param {import('jamilih').JamilihArray} el
362
+ * @param {import('jamilih').JamilihChildren} children
363
+ */
250
364
  const addChildren = (el, children) => {
251
365
  // eslint-disable-next-line unicorn/prefer-structured-clone -- Need JSON
252
366
  el = JSON.parse(JSON.stringify(el));
253
367
  el.push(children);
254
368
  return el;
255
369
  };
370
+
371
+ /**
372
+ * @param {[string, import('jamilih').JamilihAttributes?]} elAtts
373
+ * @param {import('jamilih').JamilihAttributes} newAtts
374
+ * @returns {import('jamilih').JamilihArray}
375
+ */
256
376
  const addAtts = ([el, atts], newAtts) => [el, {...atts, ...newAtts}];
257
377
 
258
378
  const foundState = {
259
379
  start: false,
260
380
  end: false
261
381
  };
262
- const outArr = [];
263
382
 
264
- const {showEmptyInterlinear, showTitleOnSingleInterlinear} = this;
383
+ /** @type {import('jamilih').JamilihArray[]} */
384
+ const outArr = [];
265
385
 
386
+ /**
387
+ * @param {string} tdVal
388
+ * @param {boolean} [htmlEscaped]
389
+ */
266
390
  const checkEmpty = (tdVal, htmlEscaped) => {
267
391
  if (!showEmptyInterlinear) {
268
392
  if (!htmlEscaped) {
269
- tdVal = new DOMParser().parseFromString(tdVal, 'text/html').body;
270
- [...tdVal.querySelectorAll('br')].forEach((br) => {
393
+ const tdValElem = new DOMParser().parseFromString(tdVal, 'text/html').body;
394
+ [...tdValElem.querySelectorAll('br')].forEach((br) => {
271
395
  br.remove();
272
396
  });
273
- tdVal = tdVal.innerHTML;
397
+ tdVal = tdValElem.innerHTML;
274
398
  }
275
399
  if (!tdVal.trim()) {
276
400
  return true;
@@ -302,7 +426,11 @@ body {
302
426
  // Need to get a new one
303
427
  const {tdVal, htmlEscaped} = getCellValue({tr, idx});
304
428
  console.log('showEmptyInterlinear', showEmptyInterlinear, htmlEscaped);
305
- const isEmpty = checkEmpty(tdVal, htmlEscaped);
429
+ const isEmpty = checkEmpty(
430
+ /** @type {string} */
431
+ (tdVal),
432
+ htmlEscaped
433
+ );
306
434
  if (isEmpty) {
307
435
  return '';
308
436
  }
@@ -313,7 +441,7 @@ body {
313
441
  dir: fieldDirs[idx],
314
442
  html: (showInterlinTitles
315
443
  ? Templates.resultsDisplayServerOrClient.interlinearTitle({
316
- l, val: localizedFieldNames[idx]
444
+ l, val: /** @type {string} */ (localizedFieldNames[idx])
317
445
  })
318
446
  : '') + tdVal
319
447
  })
@@ -327,36 +455,41 @@ body {
327
455
  lang: fieldLangs[idx],
328
456
  dir: fieldDirs[idx],
329
457
  dataset: {
330
- col: localizedFieldNames[idx]
458
+ col: /** @type {string} */ (localizedFieldNames[idx])
331
459
  },
332
460
  innerHTML:
333
- (showInterlins && !checkEmpty(tdVal, htmlEscaped) &&
334
- (showTitleOnSingleInterlinear || interlins.length)
335
- ? Templates.resultsDisplayServerOrClient.interlinearSegment({
336
- lang: fieldLangs[idx],
337
- html: (showInterlinTitles
338
- ? Templates.resultsDisplayServerOrClient.interlinearTitle({
339
- l, val: localizedFieldNames[idx]
340
- })
341
- : '') + tdVal
342
- })
343
- : tdVal
344
- ) +
345
- (interlinearColIndexes && interlins.length
346
- ? interlinearSeparator +
347
- interlins.join(interlinearSeparator)
348
- : ''
349
- )
461
+ (showInterlins && !checkEmpty(
462
+ /** @type {string} */
463
+ (tdVal),
464
+ htmlEscaped
465
+ ) &&
466
+ (showTitleOnSingleInterlinear || interlins?.length)
467
+ ? Templates.resultsDisplayServerOrClient.interlinearSegment({
468
+ lang: fieldLangs[idx],
469
+ html: (showInterlinTitles
470
+ ? Templates.resultsDisplayServerOrClient.interlinearTitle({
471
+ l, val: /** @type {string} */ (localizedFieldNames[idx])
472
+ })
473
+ : '') + tdVal
474
+ })
475
+ : tdVal
476
+ ) +
477
+ (interlinearColIndexes && interlins && interlins.length
478
+ ? interlinearSeparator +
479
+ interlins.join(interlinearSeparator)
480
+ : ''
481
+ )
350
482
  });
351
483
  })
352
484
  ));
353
485
  return false;
354
486
  });
355
487
 
356
- return ['div', [
488
+ return /** @type {import('jamilih').JamilihArray} */ (['div', [
357
489
  Templates.resultsDisplayServerOrClient.styles({
358
490
  $p, $pRaw, $pRawEsc, $pEscArbitrary,
359
- escapeQuotedCSS, escapeCSS, tableWithFixedHeaderAndFooter,
491
+ // escapeQuotedCSS,
492
+ escapeCSS, tableWithFixedHeaderAndFooter,
360
493
  checkedFieldIndexes, hasCaption
361
494
  }),
362
495
  tableWrap([
@@ -374,14 +507,14 @@ body {
374
507
  ])
375
508
  : ''),
376
509
  /*
377
- // Works but quirky, e.g., `color` doesn't work (as also
378
- // confirmed per https://quirksmode.org/css/css2/columns.html)
379
- addChildren(colgroupElem,
380
- checkedFieldIndexes.map((idx, i) =>
381
- addAtts(colElem, {style: $pRaw('css' + (idx + 1))})
382
- )
383
- ),
384
- */
510
+ // Works but quirky, e.g., `color` doesn't work (as also
511
+ // confirmed per https://quirksmode.org/css/css2/columns.html)
512
+ addChildren(colgroupElem,
513
+ checkedFieldIndexes.map((idx, i) =>
514
+ addAtts(colElem, {style: $pRaw('css' + (idx + 1))})
515
+ )
516
+ ),
517
+ */
385
518
  ($pRaw('header') !== '0'
386
519
  ? addChildren(theadElem, [
387
520
  addChildren(
@@ -391,7 +524,10 @@ body {
391
524
  cf = escapeHTML(cf) + (interlinearColIndexes
392
525
  ? l('comma-space') + interlinearColIndexes.map((idx) => {
393
526
  return localizedFieldNames[idx];
394
- }).join(l('comma-space'))
527
+ }).join(
528
+ /** @type {string} */
529
+ (l('comma-space'))
530
+ )
395
531
  : ''
396
532
  );
397
533
  return addChildren(thElem, [
@@ -418,7 +554,10 @@ body {
418
554
  cf = escapeHTML(cf) + (interlinearColIndexes
419
555
  ? l('comma-space') + interlinearColIndexes.map((idx) => {
420
556
  return localizedFieldNames[idx];
421
- }).join(l('comma-space'))
557
+ }).join(
558
+ /** @type {string} */
559
+ (l('comma-space'))
560
+ )
422
561
  : ''
423
562
  );
424
563
  return addChildren(thElem, [
@@ -439,6 +578,6 @@ body {
439
578
  addChildren(tbodyElem, outArr)
440
579
  ])
441
580
  ])
442
- ]];
581
+ ]]);
443
582
  }
444
583
  };
@@ -1,10 +1,21 @@
1
1
  const nbsp = '\u00A0';
2
+
3
+ /**
4
+ * @param {string} sel
5
+ */
2
6
  const $ = (sel) => document.querySelector(sel);
7
+ /**
8
+ * @param {string} sel
9
+ */
3
10
  const $$ = (sel) => [...document.querySelectorAll(sel)];
4
11
 
12
+ /**
13
+ * @param {string|HTMLElement} el
14
+ * @param {string} descendentsSel
15
+ */
5
16
  const $e = (el, descendentsSel) => {
6
- el = typeof el === 'string' ? $(el) : el;
7
- return el.querySelector(descendentsSel);
17
+ const elem = typeof el === 'string' ? $(el) : el;
18
+ return elem?.querySelector(descendentsSel);
8
19
  };
9
20
 
10
21
  export {nbsp, $, $$, $e};