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
@@ -4,14 +4,92 @@ import {i18n} from 'intl-dom';
4
4
  import {getMetaProp, getMetadata, Metadata} from './Metadata.js';
5
5
  import {PluginsForWork, escapePlugin} from './Plugin.js';
6
6
 
7
+ /**
8
+ * @typedef {number} Integer
9
+ */
10
+
11
+ /**
12
+ * @typedef {{
13
+ * field: string,
14
+ * fieldAliasOrName: string | string[] | import('../../server/main.js').LocalizationStrings,
15
+ * onByDefault?: boolean,
16
+ * applicableField?: string,
17
+ * metaApplicableField?: {
18
+ * [key: string]: string
19
+ * },
20
+ * fieldLang?: string
21
+ * }[]} FieldInfo
22
+ */
23
+
24
+ /**
25
+ * @typedef {{
26
+ * schema: {$ref: string},
27
+ * metadata: {$ref: string},
28
+ * data: (Integer|string)[]
29
+ * }} WorkTableContainer
30
+ */
31
+
32
+ /**
33
+ * @typedef {{
34
+ * file: {
35
+ * $ref: string
36
+ * },
37
+ * schemaFile: string,
38
+ * metadataFile: string,
39
+ * name: string,
40
+ * shortcut: string
41
+ * }} FileData
42
+ */
43
+
44
+ /**
45
+ * @typedef {{
46
+ * id: string,
47
+ * name: {
48
+ * localeKey: "string"
49
+ * },
50
+ * files: FileData[],
51
+ * baseDirectory?: string,
52
+ * schemaBaseDirectory?: string,
53
+ * metadataBaseDirectory?: string,
54
+ * directions: {
55
+ * localeKey: "string"
56
+ * }
57
+ * }} FileGroup
58
+ */
59
+
60
+ /**
61
+ * INCOMPLETE typing.
62
+ * @typedef {{
63
+ * "localization-strings": {
64
+ * [key: string]: {}
65
+ * }
66
+ * groups: FileGroup[],
67
+ * plugins: {[key: string]: import('./Plugin.js').PluginInfo},
68
+ * baseDirectory?: string,
69
+ * schemaBaseDirectory?: string,
70
+ * metadataBaseDirectory?: string,
71
+ * 'plugin-field-mapping': PluginFieldMapping
72
+ * }} FilesObject
73
+ */
74
+
75
+ /**
76
+ * @typedef {{
77
+ * [groups: string]: {
78
+ * [works: string]: {
79
+ * [fields: string]: import('./Plugin.js').PluginFieldMappingForWork
80
+ * }
81
+ * }
82
+ * }} PluginFieldMapping
83
+ */
84
+
7
85
  /**
8
86
  * Imported by the `dist/sw-helper.js`
9
87
  * @param {string} files The files.json file path
10
- * @returns {PlainObject}
88
+ * @returns {Promise<string[]>}
11
89
  */
12
90
  export const getWorkFiles = async function getWorkFiles (files) {
13
- const filesObj = await getJSON(files);
14
- const dataFiles = [];
91
+ const filesObj = /** @type {FilesObject} */ (await getJSON(files));
92
+ const dataFiles = /** @type {string[]} */ ([]);
15
93
  filesObj.groups.forEach((fileGroup) => {
16
94
  fileGroup.files.forEach((fileData) => {
17
95
  const {file, schemaFile, metadataFile} =
@@ -25,6 +103,11 @@ export const getWorkFiles = async function getWorkFiles (files) {
25
103
  return dataFiles;
26
104
  };
27
105
 
106
+ /**
107
+ * @param {FilesObject} filesObj
108
+ * @param {FileGroup} fileGroup
109
+ * @param {FileData} fileData
110
+ */
28
111
  export const getFilePaths = function getFilePaths (filesObj, fileGroup, fileData) {
29
112
  const baseDir = (filesObj.baseDirectory || '') + (fileGroup.baseDirectory || '') + '/';
30
113
  const schemaBaseDir = (filesObj.schemaBaseDirectory || '') +
@@ -38,41 +121,92 @@ export const getFilePaths = function getFilePaths (filesObj, fileGroup, fileData
38
121
  return {file, schemaFile, metadataFile};
39
122
  };
40
123
 
124
+ /**
125
+ * @typedef {{
126
+ * lang: string[],
127
+ * fallbackLanguages: string[]|undefined,
128
+ * work: string,
129
+ * files: string,
130
+ * allowPlugins: boolean|undefined,
131
+ * basePath?: string,
132
+ * languages: import('./Languages.js').Languages,
133
+ * preferredLocale: string
134
+ * }} GetWorkDataOptions
135
+ */
136
+
137
+ /**
138
+ * @typedef {{
139
+ * fileData: FileData,
140
+ * workI18n: import('intl-dom').I18NCallback,
141
+ * getFieldAliasOrName: (field: string) => string|string[]|import('../../server/main.js').LocalizationStrings,
142
+ * metadataObj: import('./Metadata.js').MetadataObj,
143
+ * schemaObj: import('./Metadata.js').SchemaObj,
144
+ * schemaItems: { title: string, type: string }[],
145
+ * fieldInfo: FieldInfo,
146
+ * pluginsForWork: PluginsForWork|null,
147
+ * groupsToWorks: {
148
+ * name: string | Text | DocumentFragment,
149
+ * workNames: (string | Text | DocumentFragment)[],
150
+ * shortcuts: string[]
151
+ * }[],
152
+ * metadata: Metadata
153
+ * }} GetWorkDataReturn
154
+ */
155
+
156
+ /**
157
+ * @this {import('../index.js').default}
158
+ * @param {GetWorkDataOptions} cfg
159
+ * @returns {Promise<GetWorkDataReturn>}
160
+ */
41
161
  export const getWorkData = async function ({
42
162
  lang, fallbackLanguages, work, files, allowPlugins, basePath,
43
163
  languages, preferredLocale
44
164
  }) {
45
- const filesObj = await getJSON(files);
46
- const localizationStrings = filesObj['localization-strings'];
165
+ const filesObj = /** @type {FilesObject} */ (await getJSON(files));
166
+ const localizationStrings =
167
+ /**
168
+ * @type {{
169
+ * "localization-strings": {
170
+ * [key: string]: {}
171
+ * }
172
+ * }}
173
+ */ (
174
+ filesObj
175
+ )?.['localization-strings'];
47
176
 
48
177
  const workI18n = await i18n({
49
178
  messageStyle: 'plainNested',
50
179
  locales: lang,
51
180
  defaultLocales: fallbackLanguages,
52
181
  // Todo: Could at least share this with `index.js`
53
- localeStringFinder ({
182
+ async localeStringFinder ({
54
183
  locales, defaultLocales
55
- }) {
56
- const locale = [...locales, ...defaultLocales].find((language) => {
184
+ } = {}) {
185
+ const locale = [
186
+ ...(/** @type {string[]} */ (locales)),
187
+ ...(/** @type {string[]} */ (defaultLocales))
188
+ ].find((language) => {
57
189
  return language in localizationStrings;
58
190
  });
59
191
  return {
60
- locale,
192
+ // eslint-disable-next-line object-shorthand -- TS
193
+ locale: /** @type {string} */ (locale),
61
194
  strings: {
62
195
  head: {},
63
- body: localizationStrings[locale]
196
+ body: localizationStrings[/** @type {string} */ (locale)]
64
197
  }
65
198
  };
66
199
  }
67
200
  });
68
201
 
202
+ /** @type {FileData} */
69
203
  let fileData;
70
- const fileGroup = filesObj.groups.find((fg) => {
71
- fileData = fg.files.find((file) => {
204
+ const fileGroup = /** @type {FileGroup} */ (filesObj.groups.find((fg) => {
205
+ fileData = /** @type {FileData} */ (fg.files.find((file) => {
72
206
  return work === workI18n(['workNames', fg.id, file.name]);
73
- });
207
+ }));
74
208
  return Boolean(fileData);
75
- });
209
+ }));
76
210
  // This is not specific to the work, but we export it anyways
77
211
  const groupsToWorks = filesObj.groups.map((fg) => {
78
212
  return {
@@ -84,6 +218,7 @@ export const getWorkData = async function ({
84
218
  };
85
219
  });
86
220
 
221
+ // @ts-expect-error Ok
87
222
  const fp = getFilePaths(filesObj, fileGroup, fileData);
88
223
  const {file} = fp;
89
224
  let {schemaFile, metadataFile} = fp;
@@ -99,12 +234,28 @@ export const getWorkData = async function ({
99
234
  metadataProperty = 'metadata';
100
235
  }
101
236
 
102
- let getPlugins, pluginsInWork, pluginFieldsForWork,
103
- pluginPaths, pluginFieldMappingForWork = [];
237
+ let getPlugins;
238
+ /**
239
+ * @type {[string, import('./Plugin.js').PluginInfo][]}
240
+ */
241
+ let pluginsInWork;
242
+
243
+ /** @type {string[]} */
244
+ let pluginPaths = [];
245
+ /** @type {string[]} */
246
+ let pluginFieldsForWork;
247
+
248
+ /**
249
+ * @type {import('./Plugin.js').PluginFieldMappingForWork[]}
250
+ */
251
+ let pluginFieldMappingForWork = [];
104
252
  if (allowPlugins) {
105
253
  const pluginFieldMapping = filesObj['plugin-field-mapping'];
106
254
  const pluginFieldMappingID = pluginFieldMapping[fileGroup.id];
107
- const possiblePluginFieldMappingForWork = pluginFieldMappingID[fileData.name];
255
+ const possiblePluginFieldMappingForWork = pluginFieldMappingID[
256
+ // @ts-expect-error Ok
257
+ (fileData).name
258
+ ];
108
259
  if (possiblePluginFieldMappingForWork) {
109
260
  pluginFieldsForWork = Object.keys(possiblePluginFieldMappingForWork);
110
261
  pluginsInWork = Object.entries(filesObj.plugins).filter(([p]) => {
@@ -117,7 +268,12 @@ export const getWorkData = async function ({
117
268
  getPlugins = pluginsInWork;
118
269
  }
119
270
  }
120
- const metadataObj = await getMetadata(metadataFile, metadataProperty, basePath);
271
+ const metadataObj = /** @type {import('./Metadata.js').MetadataObj} */ (
272
+ await getMetadata(metadataFile, metadataProperty, basePath)
273
+ );
274
+ /**
275
+ * @param {string} field
276
+ */
121
277
  const getFieldAliasOrName = function getFieldAliasOrName (field) {
122
278
  const fieldObj = metadataObj.fields && metadataObj.fields[field];
123
279
  let fieldName;
@@ -148,24 +304,37 @@ export const getWorkData = async function ({
148
304
  : process.cwd() + '/'
149
305
  );
150
306
 
151
- const [schemaObj, pluginObjects] = await Promise.all([
307
+ const schemaAndPluginObjects = await Promise.all([
152
308
  getMetadata(schemaFile, schemaProperty, basePath),
153
309
  getPlugins
154
310
  ? Promise.all(
155
- pluginPaths.map((pluginPath) => {
311
+ pluginPaths.map(async (pluginPath) => {
156
312
  // // eslint-disable-next-line no-unsanitized/method
157
- return import(
313
+ return /** @type {import('./Plugin.js').PluginObject} */ await (import(
158
314
  cwd +
159
315
  pluginPath
160
- );
316
+ ));
161
317
  })
162
318
  )
163
319
  : null
164
320
  ]);
165
- const pluginsForWork = new PluginsForWork({
166
- pluginsInWork, pluginFieldMappings, pluginObjects
167
- });
321
+
322
+ const schemaObj = /** @type {import('./Metadata.js').SchemaObj} */ (
323
+ schemaAndPluginObjects[0]
324
+ );
325
+ const pluginObjects = schemaAndPluginObjects[1];
326
+
327
+ const pluginsForWork = pluginObjects
328
+ ? new PluginsForWork({
329
+ // @ts-expect-error Ok
330
+ pluginsInWork,
331
+ pluginFieldMappings,
332
+ pluginObjects
333
+ })
334
+ : null;
168
335
  const schemaItems = schemaObj.items.items;
336
+
337
+ /** @type {FieldInfo} */
169
338
  const fieldInfo = schemaItems.map(({title: field}) => {
170
339
  return {
171
340
  field,
@@ -184,51 +353,91 @@ export const getWorkData = async function ({
184
353
  onByDefaultDefault,
185
354
  placement, applicableFields, meta
186
355
  }) => {
187
- const processField = ({applicableField, targetLanguage, onByDefault, metaApplicableField} = {}) => {
356
+ /**
357
+ * @param {{
358
+ * applicableField?: string,
359
+ * targetLanguage?: string,
360
+ * onByDefault?: boolean,
361
+ * metaApplicableField?: {
362
+ * [key: string]: string
363
+ * }
364
+ * }} [cfg]
365
+ */
366
+ const processField = ({
367
+ applicableField, targetLanguage, onByDefault, metaApplicableField
368
+ } = {}) => {
188
369
  const plugin = pluginsForWork.getPluginObject(pluginName) || {};
189
- const applicableFieldLang = metadata.getFieldLang(applicableField);
370
+ const applicableFieldLang = metadata.getFieldLang(
371
+ /** @type {string} */
372
+ (applicableField)
373
+ );
190
374
  if (plugin.getTargetLanguage) {
191
375
  targetLanguage = plugin.getTargetLanguage({
192
- applicableField,
193
- targetLanguage,
376
+ // eslint-disable-next-line object-shorthand -- TS
377
+ applicableField: /** @type {string} */ (applicableField),
378
+ // eslint-disable-next-line object-shorthand -- TS
379
+ targetLanguage: /** @type {string} */ (targetLanguage),
194
380
  // Default lang for plug-in (from files.json)
195
381
  pluginLang,
196
382
  // Default lang when no target language or
197
383
  // plugin lang; using the lang of the applicable
198
384
  // field
199
- applicableFieldLang
385
+ // eslint-disable-next-line object-shorthand -- TS
386
+ applicableFieldLang: /** @type {string} */ (applicableFieldLang)
200
387
  });
201
388
  }
202
389
  const field = escapePlugin({
203
390
  pluginName,
204
- applicableField,
205
- targetLanguage: targetLanguage || pluginLang ||
206
- applicableFieldLang
391
+ // eslint-disable-next-line object-shorthand -- TS
392
+ applicableField: /** @type {string} */ (applicableField),
393
+ targetLanguage: /** @type {string} */ (targetLanguage || pluginLang ||
394
+ applicableFieldLang)
207
395
  });
208
396
  if (targetLanguage === '{locale}') {
209
397
  targetLanguage = preferredLocale;
210
398
  }
211
- const applicableFieldI18N = getMetaProp(lang, metadataObj, ['fieldnames', applicableField]);
399
+ const applicableFieldI18N = getMetaProp(
400
+ lang, metadataObj, ['fieldnames', /** @type {string} */ (applicableField)]
401
+ );
212
402
  const fieldAliasOrName = plugin.getFieldAliasOrName
213
403
  ? plugin.getFieldAliasOrName({
214
404
  locales: lang,
215
405
  workI18n,
216
- targetLanguage,
217
- applicableField,
406
+ // eslint-disable-next-line object-shorthand -- TS
407
+ targetLanguage: /** @type {string} */ (targetLanguage),
408
+ // eslint-disable-next-line object-shorthand -- TS
409
+ applicableField: /** @type {string} */ (applicableField),
218
410
  applicableFieldI18N,
219
411
  meta,
220
- metaApplicableField,
221
- targetLanguageI18N: languages.getLanguageFromCode(targetLanguage)
412
+ // eslint-disable-next-line object-shorthand -- TS
413
+ metaApplicableField:
414
+ /**
415
+ * @type {{
416
+ * [key: string]: string
417
+ * }}
418
+ */ (metaApplicableField),
419
+ targetLanguageI18N: languages.getLanguageFromCode(
420
+ /** @type {string} */
421
+ (targetLanguage)
422
+ )
222
423
  })
223
424
  : languages.getFieldNameFromPluginNameAndLocales({
224
425
  pluginName,
225
- locales: lang,
426
+ // locales: lang,
226
427
  workI18n,
227
- targetLanguage,
228
- applicableFieldI18N,
428
+ // eslint-disable-next-line object-shorthand -- TS
429
+ targetLanguage: /** @type {string} */ (targetLanguage),
430
+ // eslint-disable-next-line object-shorthand -- TS
431
+ applicableFieldI18N: /** @type {string|string[]} */ (applicableFieldI18N),
229
432
  // Todo: Should have formal way to i18nize meta
230
433
  meta,
231
- metaApplicableField
434
+ // eslint-disable-next-line object-shorthand -- TS
435
+ metaApplicableField:
436
+ /**
437
+ * @type {{
438
+ * [key: string]: string
439
+ * }}
440
+ */ (metaApplicableField)
232
441
  });
233
442
  fieldInfo.splice(
234
443
  // Todo: Allow default placement overriding for
@@ -260,7 +469,10 @@ export const getWorkData = async function ({
260
469
  });
261
470
  }
262
471
  return {
263
- fileData, workI18n, getFieldAliasOrName, metadataObj,
472
+ // @ts-expect-error Ok
473
+ // eslint-disable-next-line object-shorthand -- TS
474
+ fileData: /** @type {FileData} */ (fileData),
475
+ workI18n, getFieldAliasOrName, metadataObj,
264
476
  schemaObj, schemaItems, fieldInfo,
265
477
  pluginsForWork, groupsToWorks, metadata
266
478
  };
@@ -1,7 +1,21 @@
1
1
  import {jml, nbsp, $} from 'jamilih';
2
2
  import {$e} from '../templates/utils/dom.js';
3
3
 
4
+ /**
5
+ * @typedef {{
6
+ * submit: string,
7
+ * cancel: string,
8
+ * ok: string
9
+ * }} LocaleObject
10
+ */
11
+
12
+ /**
13
+ * @typedef {{[locale: string]: LocaleObject}} Locales
14
+ */
15
+
4
16
  const defaultLocale = 'en';
17
+
18
+ /** @type {Locales} */
5
19
  const localeStrings = {
6
20
  en: {
7
21
  submit: 'Submit',
@@ -11,16 +25,61 @@ const localeStrings = {
11
25
  };
12
26
 
13
27
  class Dialog {
28
+ /**
29
+ * @param {{
30
+ * locale?: string,
31
+ * localeObject?: LocaleObject
32
+ * }} [cfg]
33
+ */
14
34
  constructor ({locale, localeObject} = {}) {
35
+ this.localeStrings = localeStrings.en; // For types
15
36
  this.setLocale({locale, localeObject});
16
37
  }
17
- setLocale ({locale = {}, localeObject = {}}) {
38
+ /**
39
+ * @param {{
40
+ * locale?: string,
41
+ * localeObject?: Partial<LocaleObject>
42
+ * }} cfg
43
+ * @returns {void}
44
+ */
45
+ setLocale ({locale, localeObject = {}}) {
18
46
  this.localeStrings = {
19
47
  ...localeStrings[defaultLocale],
20
- ...localeStrings[locale],
48
+ ...(locale ? localeStrings[locale] : {}),
21
49
  ...localeObject
22
50
  };
23
51
  }
52
+
53
+ /**
54
+ * @typedef {{
55
+ * atts?: import('jamilih').JamilihAttributes,
56
+ * children?: import('jamilih').JamilihChildren,
57
+ * close?: () => void,
58
+ * remove?: boolean
59
+ * }} MakeDialogCfg
60
+ */
61
+
62
+ /**
63
+ * @typedef {MakeDialogCfg & {
64
+ * submit?: (
65
+ * this: HTMLElement, args: {e: Event, dialog: HTMLDialogElement}
66
+ * ) => void,
67
+ * cancel: (
68
+ * this: HTMLElement,
69
+ * args: {
70
+ * e: Event,
71
+ * dialog: HTMLDialogElement
72
+ * }
73
+ * ) => boolean|void,
74
+ * cancelClass?: string,
75
+ * submitClass?: string
76
+ * }} CancelDialogCfg
77
+ */
78
+
79
+ /**
80
+ * @param {MakeDialogCfg} cfg
81
+ * @returns {HTMLDialogElement}
82
+ */
24
83
  makeDialog ({atts = {
25
84
  $on: null
26
85
  }, children = [], close, remove = true}) {
@@ -32,7 +91,9 @@ class Dialog {
32
91
  atts.$on.close = close;
33
92
  }
34
93
  }
35
- const dialog = /** @type {HTMLDialogElement} */ (jml('dialog', atts, children, $('#main')));
94
+ const dialog = /** @type {HTMLDialogElement} */ (
95
+ jml('dialog', atts, children, $('#main'))
96
+ );
36
97
  dialog.showModal();
37
98
  if (remove) {
38
99
  dialog.addEventListener('close', () => {
@@ -41,13 +102,19 @@ class Dialog {
41
102
  }
42
103
  return dialog;
43
104
  }
105
+ /**
106
+ * @param {CancelDialogCfg} cfg
107
+ * @returns {HTMLDialogElement}
108
+ */
44
109
  makeSubmitDialog ({
45
110
  submit, // Don't pass this on to `args` if present
46
111
  submitClass = 'submit',
47
112
  ...args
48
113
  }) {
49
114
  const dialog = this.makeCancelDialog(args);
50
- $e(dialog, `button.${args.cancelClass || 'cancel'}`).before(
115
+ /** @type {HTMLDialogElement} */ (
116
+ $e(dialog, `button.${args.cancelClass || 'cancel'}`)
117
+ ).before(
51
118
  jml('button', {
52
119
  class: submitClass,
53
120
  $on: {
@@ -62,6 +129,11 @@ class Dialog {
62
129
  );
63
130
  return dialog;
64
131
  }
132
+
133
+ /**
134
+ * @param {CancelDialogCfg} cfg
135
+ * @returns {HTMLDialogElement}
136
+ */
65
137
  makeCancelDialog ({
66
138
  // eslint-disable-next-line no-unused-vars -- Discarding
67
139
  submit, // Don't pass this on to `args` if present
@@ -86,6 +158,12 @@ class Dialog {
86
158
  ], dialog);
87
159
  return dialog;
88
160
  }
161
+
162
+ /**
163
+ * @param {string|{message: string, ok?: boolean, submitClass?: string}} message
164
+ * @param {boolean|{ok: boolean}} [ok]
165
+ * @returns {Promise<void>}
166
+ */
89
167
  alert (message, ok) {
90
168
  message = typeof message === 'string' ? {message} : message;
91
169
  const {
@@ -99,7 +177,7 @@ class Dialog {
99
177
  const dialog = /** @type {HTMLDialogElement} */ (jml('dialog', [
100
178
  msg,
101
179
  ...(includeOk
102
- ? ([
180
+ ? /** @type {import('jamilih').JamilihChildren} */ ([
103
181
  ['br'], ['br'],
104
182
  ['div', {class: submitClass}, [
105
183
  ['button', {$on: {click () {
@@ -113,16 +191,32 @@ class Dialog {
113
191
  dialog.showModal();
114
192
  });
115
193
  }
194
+ /**
195
+ * @param {string|Partial<CancelDialogCfg> & {
196
+ * message: string
197
+ * }} message
198
+ * @returns {Promise<string>}
199
+ */
116
200
  prompt (message) {
117
201
  message = typeof message === 'string' ? {message} : message;
118
202
  const {message: msg, submit: userSubmit, ...submitArgs} = message;
119
203
  return new Promise((resolve, reject) => {
204
+ /**
205
+ * @param {{
206
+ * e: Event,
207
+ * dialog: HTMLDialogElement
208
+ * }} args
209
+ */
120
210
  const submit = function ({e, dialog}) {
121
211
  if (userSubmit) {
122
- userSubmit.call(this, {e, dialog});
212
+ userSubmit.call(
213
+ // @ts-expect-error Ok
214
+ /** @type {HTMLElement} */ (this),
215
+ {e, dialog}
216
+ );
123
217
  }
124
218
  dialog.close();
125
- resolve($e(dialog, 'input').value);
219
+ resolve(/** @type {HTMLInputElement} */ ($e(dialog, 'input')).value);
126
220
  };
127
221
  /* const dialog = */ this.makeSubmitDialog({
128
222
  ...submitArgs,
@@ -140,6 +234,10 @@ class Dialog {
140
234
  });
141
235
  });
142
236
  }
237
+ /**
238
+ * @param {string|{message: string, submitClass?: string}} message
239
+ * @returns {Promise<void>}
240
+ */
143
241
  confirm (message) {
144
242
  message = typeof message === 'string' ? {message} : message;
145
243
  const {message: msg, submitClass = 'submit'} = message;
@@ -3,6 +3,16 @@
3
3
  */
4
4
  import {i18n} from 'intl-dom';
5
5
 
6
+ /**
7
+ * @param {{
8
+ * $p: import('./IntlURLSearchParams').default,
9
+ * lang: string[],
10
+ * langs: import('../../server/main.js').LanguageInfo[],
11
+ * langData: import('../../server/main.js').LanguagesData,
12
+ * fallbackLanguages?: string[],
13
+ * basePath?: string
14
+ * }} options
15
+ */
6
16
  export default async function getLocaleFallbackResults ({
7
17
  $p,
8
18
  lang, langs, langData, fallbackLanguages,
@@ -17,9 +27,9 @@ export default async function getLocaleFallbackResults ({
17
27
  // `$ref` (as with <https://github.com/whitlockjc/json-refs>) and
18
28
  // replace `loadLocales` behavior with our own now resolved
19
29
  // locales; see https://github.com/jdorn/json-editor/issues/132
20
- return basePath + (langData.localeFileBasePath) + langs.find((l) => {
30
+ return basePath + (langData.localeFileBasePath) + (langs.find((l) => {
21
31
  return l.code === code;
22
- }).locale.$ref;
32
+ })?.locale?.$ref ?? '');
23
33
  }
24
34
  });
25
35
  if (!$p.l10n) {
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Prevent XSS attacks.
3
+ * @param {string} s - The string to sanitize
4
+ */
1
5
  const escapeHTML = (s) => {
2
6
  return !s
3
7
  ? ''