textbrowser 0.50.0 → 0.52.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 (106) hide show
  1. package/.ncurc.cjs +3 -0
  2. package/CHANGES.md +13 -0
  3. package/dist/WorkInfo-es.js +655 -165
  4. package/dist/activateCallback-es.js +81 -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 +3449 -1848
  16. package/dist/index-es.min.js +4 -4
  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 +278 -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 +47 -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 +32 -19
  80. package/resources/activateCallback.js +81 -10
  81. package/resources/index.js +169 -58
  82. package/resources/resultsDisplay.js +520 -153
  83. package/resources/templates/index.js +39 -17
  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 -76
  89. package/resources/templates/workSelect.js +16 -3
  90. package/resources/user-sample.js +1 -0
  91. package/resources/utils/IntlURLSearchParams.js +46 -4
  92. package/resources/utils/Languages.js +71 -4
  93. package/resources/utils/Metadata.js +222 -23
  94. package/resources/utils/Params.js +70 -23
  95. package/resources/utils/Plugin.js +175 -1
  96. package/resources/utils/ServiceWorker.js +49 -21
  97. package/resources/utils/WorkInfo.js +256 -44
  98. package/resources/utils/dialogs.js +105 -7
  99. package/resources/utils/getLocaleFallbackResults.js +15 -3
  100. package/resources/utils/sanitize.js +4 -0
  101. package/resources/workDisplay.js +151 -25
  102. package/resources/workSelect.js +37 -17
  103. package/server/main.js +118 -20
  104. package/sw-sample.js +2 -1
  105. package/tsconfig.json +30 -0
  106. package/resources/user.js +0 -20
@@ -1,6 +1,17 @@
1
1
  import {jml, $} from 'jamilih';
2
+
3
+ // @ts-expect-error -- Missing TS
2
4
  import {deserialize as formDeserialize} from 'form-serialization';
3
5
 
6
+ /**
7
+ * @param {{
8
+ * groups: import('../utils/WorkInfo.js').FileGroup[]
9
+ * workI18n: import('intl-dom').I18NCallback
10
+ * getNextAlias: () => string|string[]|import('../../server/main.js').LocalizationStrings
11
+ * $p: import('../utils/IntlURLSearchParams.js').default
12
+ * followParams: (formSelector: string, cb: () => void) => void
13
+ * }} cfg
14
+ */
4
15
  const workSelect = function ({groups, workI18n, getNextAlias, $p, followParams}) {
5
16
  const form = jml(
6
17
  'form',
@@ -10,7 +21,7 @@ const workSelect = function ({groups, workI18n, getNextAlias, $p, followParams})
10
21
  }
11
22
  }},
12
23
  groups.map((group, i) => {
13
- return ['div', [
24
+ return /** @type {import('jamilih').JamilihArray} */ (['div', [
14
25
  i > 0 ? ['br', 'br', 'br'] : '',
15
26
  ['div', [
16
27
  workI18n(group.directions.localeKey)
@@ -23,7 +34,9 @@ const workSelect = function ({groups, workI18n, getNextAlias, $p, followParams})
23
34
  name: group.name.localeKey
24
35
  },
25
36
  $on: {
26
- change ({target: {value}}) {
37
+ change (e) {
38
+ // eslint-disable-next-line prefer-destructuring -- TS
39
+ const value = /** @type {HTMLSelectElement} */ (e.target).value;
27
40
  /*
28
41
  // If using click, but click doesn't always fire
29
42
  if (e.target.nodeName.toLowerCase() === 'select') {
@@ -45,7 +58,7 @@ const workSelect = function ({groups, workI18n, getNextAlias, $p, followParams})
45
58
  ]]
46
59
  // Todo: Add in Go button (with 'submitgo' localization string) to
47
60
  // avoid need for pull-down if using first selection?
48
- ]];
61
+ ]]);
49
62
  }),
50
63
  $('#main')
51
64
  );
@@ -1,3 +1,4 @@
1
+ // eslint-disable-next-line sonarjs/no-internal-api-use -- Demo
1
2
  import TextBrowser from '../node_modules/textbrowser/dist/index-es.js';
2
3
 
3
4
  const tb = new TextBrowser({
@@ -2,10 +2,10 @@
2
2
  * @file Note that this should be kept as a polyglot client-server file.
3
3
  */
4
4
  /**
5
- *
6
- * @param {string} param
7
- * @param {boolean} skip
8
5
  * @this {IntlURLSearchParams}
6
+ * @param {string} param
7
+ * @param {boolean} [skip]
8
+ * @throws {Error}
9
9
  * @returns {string}
10
10
  */
11
11
  function _prepareParam (param, skip) {
@@ -16,39 +16,81 @@ function _prepareParam (param, skip) {
16
16
  // start, end, toggle
17
17
  const endNums = /\d+(-\d+)?$/;
18
18
  const indexed = param.match(endNums);
19
+ if (!this.l10n) {
20
+ throw new Error('l10n is not defined');
21
+ }
19
22
  if (indexed) {
20
23
  // Todo: We could i18nize numbers as well
21
24
  return this.l10n(['params', 'indexed', param.replace(endNums, '')]) + indexed[0];
22
25
  }
23
- return this.l10n(['params', param]);
26
+ return /** @type {string} */ (this.l10n(['params', param]));
24
27
  }
25
28
 
26
29
  class IntlURLSearchParams {
30
+ /**
31
+ * @param {object} [options]
32
+ * @param {import('intl-dom').I18NCallback} [options.l10n]
33
+ * @param {URLSearchParams|string} [options.params]
34
+ */
27
35
  constructor ({l10n, params} = {}) {
28
36
  this.l10n = l10n;
37
+ this.localizeParamNames = false;
29
38
  if (!params) {
30
39
  params = location.hash.slice(1);
31
40
  }
32
41
  if (typeof params === 'string') {
33
42
  params = new URLSearchParams(params);
34
43
  }
44
+ /** @type {URLSearchParams} */
35
45
  this.params = params;
36
46
  }
47
+ /**
48
+ * @param {string} param
49
+ * @param {boolean} [skip]
50
+ * @returns {string|null}
51
+ */
37
52
  get (param, skip) {
38
53
  return this.params.get(_prepareParam.call(this, param, skip));
39
54
  }
55
+ /**
56
+ * @param {string} param
57
+ * @param {boolean} skip
58
+ * @returns {string[]}
59
+ */
40
60
  getAll (param, skip) {
41
61
  return this.params.getAll(_prepareParam.call(this, param, skip));
42
62
  }
63
+ /**
64
+ * @param {string} param
65
+ * @param {boolean} [skip]
66
+ * @returns {boolean}
67
+ */
43
68
  has (param, skip) {
44
69
  return this.params.has(_prepareParam.call(this, param, skip));
45
70
  }
71
+ /**
72
+ * @param {string} param
73
+ * @param {boolean} skip
74
+ * @returns {void}
75
+ */
46
76
  delete (param, skip) {
47
77
  return this.params.delete(_prepareParam.call(this, param, skip));
48
78
  }
79
+ /**
80
+ * @param {string} param
81
+ * @param {string} value
82
+ * @param {boolean} [skip]
83
+ * @returns {void}
84
+ */
49
85
  set (param, value, skip) {
50
86
  return this.params.set(_prepareParam.call(this, param, skip), value);
51
87
  }
88
+ /**
89
+ * @param {string} param
90
+ * @param {string} value
91
+ * @param {boolean} skip
92
+ * @returns {void}
93
+ */
52
94
  append (param, value, skip) {
53
95
  return this.params.append(_prepareParam.call(this, param, skip), value);
54
96
  }
@@ -1,10 +1,21 @@
1
1
  // Todo: remember this locales choice by cookie?
2
+
3
+ /**
4
+ * @param {{
5
+ * namespace: string,
6
+ * preferredLocale: string
7
+ * }} cfg
8
+ */
2
9
  export const getPreferredLanguages = ({namespace, preferredLocale}) => {
3
10
  // Todo: Add to this optionally with one-off tag input box
4
11
  // Todo: Switch to fallbackLanguages so can default to
5
12
  // navigator.languages?
6
13
  const langCodes = localStorage.getItem(namespace + '-langCodes');
7
- const lngs = (langCodes && JSON.parse(langCodes)) || [preferredLocale];
14
+ const lngs = /** @type {string[]} */ (
15
+ (langCodes && JSON.parse(langCodes)) || [preferredLocale]
16
+ );
17
+
18
+ /** @type {string[]} */
8
19
  const langArr = [];
9
20
  lngs.forEach((lng) => {
10
21
  // Todo: Check for multiple separate hyphenated
@@ -23,23 +34,66 @@ export const getPreferredLanguages = ({namespace, preferredLocale}) => {
23
34
  * @classdesc Note that this should be kept as a polyglot client-server class.
24
35
  */
25
36
  export class Languages {
37
+ /**
38
+ * @param {{
39
+ * langData: import('../../server/main.js').LanguagesData
40
+ * }} cfg
41
+ */
26
42
  constructor ({langData}) {
27
43
  this.langData = langData;
28
44
  }
45
+ /**
46
+ * @param {string} langCode
47
+ * @returns {{
48
+ * languages: {
49
+ * [key: string]: string
50
+ * }
51
+ * }}
52
+ */
29
53
  localeFromLangData (langCode) {
30
- return this.langData['localization-strings'][langCode];
54
+ return (
55
+ /**
56
+ * @type {{
57
+ * languages: {
58
+ * [key: string]: string
59
+ * }
60
+ * }}
61
+ */ (
62
+ this.langData['localization-strings'][langCode]
63
+ )
64
+ );
31
65
  }
66
+ /**
67
+ * @param {string} code
68
+ * @returns {string}
69
+ */
32
70
  getLanguageFromCode (code) {
33
71
  return this.localeFromLangData(code).languages[code];
34
72
  // Could add something like this in place or as fallback, though need to pass in locale
35
73
  // || new Intl.DisplayNames([locale], {type: 'language'}).of(code);
36
74
  }
75
+
76
+ /**
77
+ * @param {{
78
+ * pluginName: string,
79
+ * workI18n: import('intl-dom').I18NCallback,
80
+ * targetLanguage: string,
81
+ * applicableFieldI18N: string|string[],
82
+ * meta: {
83
+ * [key: string]: string
84
+ * },
85
+ * metaApplicableField: {
86
+ * [key: string]: string
87
+ * },
88
+ * }} cfg
89
+ * @returns {string}
90
+ */
37
91
  getFieldNameFromPluginNameAndLocales ({
38
92
  pluginName,
39
93
  // locales,
40
94
  workI18n, targetLanguage, applicableFieldI18N, meta, metaApplicableField
41
95
  }) {
42
- return workI18n(['plugins', pluginName, 'fieldname'], {
96
+ return /** @type {string} */ (workI18n(['plugins', pluginName, 'fieldname'], {
43
97
  ...meta,
44
98
  ...metaApplicableField,
45
99
  applicableField: applicableFieldI18N,
@@ -49,10 +103,23 @@ export class Languages {
49
103
  }, {
50
104
  // We provide more than may be desired by the plugin
51
105
  throwOnExtraSuppliedFormatters: false
52
- });
106
+ }));
53
107
  }
108
+
109
+ /**
110
+ * @param {{$p: import('./IntlURLSearchParams.js').default}} cfg
111
+ * @returns {{
112
+ * lang: string[],
113
+ * langs: import('../../server/main.js').LanguageInfo[],
114
+ * languageParam: string|null,
115
+ * fallbackLanguages: string[]
116
+ * }}
117
+ */
54
118
  getLanguageInfo ({$p}) {
55
119
  const langs = this.langData.languages;
120
+ /**
121
+ * @param {string} lcl
122
+ */
56
123
  const localePass = (lcl) => {
57
124
  return langs.some(({code}) => code === lcl) ? lcl : false;
58
125
  };
@@ -3,17 +3,56 @@ import {getPreferredLanguages} from './Languages.js';
3
3
  import JsonRefs from 'json-refs'; // // eslint-disable-line import/order
4
4
 
5
5
  const getCurrDir = () => {
6
- return window.location.href.replace(/(index\.html)?#.*$/, '');
6
+ return globalThis.location.href.replace(/(index\.html)?#.*$/, '');
7
7
  };
8
8
 
9
+ /**
10
+ * @typedef {{
11
+ * [key: string]: string|Integer|(string|Integer)[]|{
12
+ * [key: string]: string|Integer
13
+ * }
14
+ * }} FieldValueAliases
15
+ */
16
+
17
+ /**
18
+ * @typedef {{
19
+ * "localization-strings": import('../../server/main.js').LocalizationStrings
20
+ * table: {browse_fields: (string|{
21
+ * name?: string,
22
+ * set: string[],
23
+ * presort?: boolean
24
+ * })[]}
25
+ * fields: {
26
+ * [key: string]: {
27
+ * prefer_alias: boolean|string,
28
+ * name: string|{localeKey: string},
29
+ * alias: string|{localeKey: string},
30
+ * lang: string,
31
+ * 'fieldvalue-aliases': FieldValueAliases
32
+ * }
33
+ * }
34
+ * }} MetadataObj
35
+ */
36
+
37
+ /**
38
+ * @param {string[]} lang
39
+ * @param {MetadataObj} metadataObj
40
+ * @param {string|string[]} properties
41
+ * @param {boolean} [allowObjects]
42
+ * @returns {string|string[]|import('../../server/main.js').LocalizationStrings}
43
+ */
9
44
  export const getMetaProp = function getMetaProp (lang, metadataObj, properties, allowObjects) {
10
45
  let prop;
11
46
  properties = typeof properties === 'string' ? [properties] : properties;
12
- lang.some((lan) => {
47
+ for (const lan of lang) {
13
48
  const p = [...properties];
14
- let strings = metadataObj['localization-strings'][lan];
49
+ let strings = /** @type {string|string[]|import('../../server/main.js').LocalizationStrings} */ (
50
+ metadataObj['localization-strings'][lan]
51
+ );
15
52
  while (strings && p.length) {
16
- strings = strings[p.shift()];
53
+ strings = /** @type {import('../../server/main.js').LocalizationStrings} */ (
54
+ strings
55
+ )[/** @type {string} */ (p.shift())];
17
56
  }
18
57
  // Todo: Fix this allowance for allowObjects (as it does not properly
19
58
  // fallback if an object is returned from a language because
@@ -22,9 +61,13 @@ export const getMetaProp = function getMetaProp (lang, metadataObj, properties,
22
61
  prop = (allowObjects || typeof strings === 'string')
23
62
  ? strings
24
63
  : undefined;
25
- return prop;
26
- });
27
- return prop;
64
+ if (prop) {
65
+ break;
66
+ }
67
+ }
68
+ return /** @type {string|string[]|import('../../server/main.js').LocalizationStrings} */ (
69
+ prop
70
+ );
28
71
  };
29
72
 
30
73
  // Use the following to dynamically add specific file schema in place of
@@ -32,18 +75,46 @@ export const getMetaProp = function getMetaProp (lang, metadataObj, properties,
32
75
  // filesSchema.properties.groups.items.properties.files.items.properties.
33
76
  // file.anyOf.splice(1, 1, {$ref: schemaFile});
34
77
  // Todo: Allow use of dbs and fileGroup together in base directories?
78
+
79
+ /**
80
+ * @typedef {{
81
+ * items: {
82
+ * items: {
83
+ * title: string,
84
+ * type: string
85
+ * format?: string
86
+ * }[]
87
+ * }
88
+ * }} SchemaObj
89
+ */
90
+
91
+ /**
92
+ * @param {string} file
93
+ * @param {string} property
94
+ * @param {string} [basePath]
95
+ * @returns {Promise<MetadataObj|SchemaObj>}
96
+ */
35
97
  export const getMetadata = async (file, property, basePath) => {
36
98
  const url = new URL(basePath || getCurrDir());
37
99
  url.search = ''; // Clear out query string, e.g., `?fbclid` from Facebook
38
100
  url.pathname = file;
39
101
  url.hash = property ? '#/' + property : '';
40
102
 
41
- return (await JsonRefs.
103
+ return /** @type {MetadataObj} */ ((await JsonRefs.
42
104
  resolveRefsAt(
43
105
  url.toString(),
44
106
  {
45
107
  loaderOptions: {
108
+ /* eslint-disable jsdoc/reject-any-type -- How to resolve? */
109
+ /**
110
+ * @param {{
111
+ * text: string,
112
+ * body: any
113
+ * }} res
114
+ * @param {(err?: Error, cbValue: any) => void} callback
115
+ */
46
116
  processContent (res, callback) {
117
+ /* eslint-enable jsdoc/reject-any-type -- How to resolve? */
47
118
  callback(undefined, JSON.parse(
48
119
  res.text ||
49
120
  // `.metadata` not a recognized extension, so
@@ -53,9 +124,39 @@ export const getMetadata = async (file, property, basePath) => {
53
124
  }
54
125
  }
55
126
  }
56
- )).resolved;
127
+ )).resolved);
57
128
  };
58
129
 
130
+ /**
131
+ * @typedef {{
132
+ * field: string,
133
+ * schemaItems: {
134
+ * title: string,
135
+ * type: string,
136
+ * enum?: string[]
137
+ * }[],
138
+ * metadataObj: MetadataObj,
139
+ * getFieldAliasOrName: (field: string) => string|string[]|import('../../server/main.js').LocalizationStrings,
140
+ * lang: string[]
141
+ * }} GetFieldNameAndValueAliasesOptions
142
+ */
143
+
144
+ /**
145
+ * @param {GetFieldNameAndValueAliasesOptions} cfg
146
+ * @returns {{
147
+ * aliases: string[]|null,
148
+ * fieldValueAliasMap: FieldValueAliases|null,
149
+ * rawFieldValueAliasMap: FieldValueAliases|null,
150
+ * fieldName: string,
151
+ * fieldSchema: {
152
+ * title: string,
153
+ * type: string
154
+ * },
155
+ * fieldSchemaIndex: number,
156
+ * preferAlias: boolean|string,
157
+ * lang: string
158
+ * }}
159
+ */
59
160
  export const getFieldNameAndValueAliases = function ({
60
161
  field, schemaItems, metadataObj, getFieldAliasOrName, lang
61
162
  }) {
@@ -66,27 +167,46 @@ export const getFieldNameAndValueAliases = function ({
66
167
 
67
168
  const fieldInfo = metadataObj.fields[field];
68
169
 
170
+ /**
171
+ * @type {{
172
+ * aliases: string[]|null,
173
+ * fieldValueAliasMap: FieldValueAliases|null,
174
+ * rawFieldValueAliasMap: FieldValueAliases|null,
175
+ * fieldName: string,
176
+ * fieldSchema: {
177
+ * title: string,
178
+ * type: string
179
+ * },
180
+ * fieldSchemaIndex: number,
181
+ * preferAlias: boolean|string,
182
+ * lang: string
183
+ * }}
184
+ */
69
185
  const ret = {
70
186
  // field,
71
187
  aliases: null,
72
188
  fieldValueAliasMap: null,
73
189
  rawFieldValueAliasMap: null,
74
- fieldName: getFieldAliasOrName(field),
190
+ fieldName: /** @type {string} */ (getFieldAliasOrName(field)),
75
191
  fieldSchema,
76
192
  fieldSchemaIndex,
77
193
  preferAlias: fieldInfo.prefer_alias,
78
194
  lang: fieldInfo.lang
79
195
  };
80
196
 
197
+ /** @type {FieldValueAliases} */
81
198
  let fieldValueAliasMap = fieldInfo && fieldInfo['fieldvalue-aliases'];
82
199
 
83
200
  if (fieldValueAliasMap) {
84
201
  if (fieldValueAliasMap.localeKey) {
85
- fieldValueAliasMap = getMetaProp(
86
- lang,
87
- metadataObj,
88
- fieldValueAliasMap.localeKey.split('/'),
89
- true
202
+ fieldValueAliasMap = /** @type {FieldValueAliases} */ (
203
+ getMetaProp(
204
+ lang,
205
+ metadataObj,
206
+ /** @type {string} */
207
+ (fieldValueAliasMap.localeKey).split('/'),
208
+ true
209
+ )
90
210
  );
91
211
  }
92
212
  // eslint-disable-next-line unicorn/prefer-structured-clone -- Expecting JSON
@@ -96,14 +216,18 @@ export const getFieldNameAndValueAliases = function ({
96
216
  // needed cases
97
217
  if (fieldSchema.enum && fieldSchema.enum.length) {
98
218
  fieldSchema.enum.forEach((enm) => {
99
- ret.aliases.push(
100
- getMetaProp(lang, metadataObj, ['fieldvalue', field, enm], true)
219
+ /** @type {string[]} */
220
+ (ret.aliases).push(
221
+ /** @type {string} */ (
222
+ getMetaProp(lang, metadataObj, ['fieldvalue', field, enm], true)
223
+ )
101
224
  );
102
225
  if (enm in fieldValueAliasMap &&
103
226
  // Todo: We could allow numbers here too, but crowds
104
227
  // pull-down
105
228
  typeof fieldValueAliasMap[enm] === 'string') {
106
- ret.aliases.push(...fieldValueAliasMap[enm]);
229
+ /** @type {string[]} */
230
+ (ret.aliases).push(...fieldValueAliasMap[enm]);
107
231
  }
108
232
  });
109
233
  } else {
@@ -114,15 +238,24 @@ export const getFieldNameAndValueAliases = function ({
114
238
  // We'll preserve the numbers since probably more useful if
115
239
  // stored with data (as opposed to enums)
116
240
  if (!Array.isArray(aliases)) {
117
- aliases = Object.values(aliases);
241
+ aliases = /** @type {string[]} */ (
242
+ Object.values(/** @type {import('../../server/main.js').LocalizationStrings} */ (
243
+ aliases
244
+ ))
245
+ );
118
246
  }
119
247
  // We'll assume the longest version is best for auto-complete
120
- ret.aliases.push(
248
+ /** @type {string[]} */
249
+ (ret.aliases).push(
121
250
  ...(
122
251
  aliases.filter((v) => {
123
252
  return aliases.every((x) => {
124
253
  return x === v || !(
125
- x.toLowerCase().startsWith(v.toLowerCase())
254
+ /** @type {string} */
255
+ (x).toLowerCase().startsWith(
256
+ /** @type {string} */
257
+ (v).toLowerCase()
258
+ )
126
259
  );
127
260
  });
128
261
  }).map((v) => v + ' (' + key + ')') // Todo: i18nize
@@ -131,12 +264,55 @@ export const getFieldNameAndValueAliases = function ({
131
264
  });
132
265
  }
133
266
  // eslint-disable-next-line unicorn/prefer-structured-clone -- Expecting JSON
134
- ret.fieldValueAliasMap = JSON.parse(JSON.stringify(fieldValueAliasMap));
267
+ ret.fieldValueAliasMap = /** @type {FieldValueAliases} */ (JSON.parse(JSON.stringify(fieldValueAliasMap)));
135
268
  // ret.aliases.sort();
136
269
  }
137
270
  return ret;
138
271
  };
139
272
 
273
+ /**
274
+ * @typedef {number} Integer
275
+ */
276
+
277
+ /**
278
+ * @typedef {{
279
+ * aliases: string[]|null,
280
+ * fieldValueAliasMap: FieldValueAliases|null,
281
+ * rawFieldValueAliasMap: FieldValueAliases|null,
282
+ * fieldName: string,
283
+ * fieldSchema: {
284
+ * title: string,
285
+ * type: string,
286
+ * minimum?: Integer,
287
+ * maximum?: Integer
288
+ * },
289
+ * fieldSchemaIndex: number,
290
+ * preferAlias: boolean|string,
291
+ * lang: string
292
+ * }[]} BrowseFields
293
+ */
294
+
295
+ /**
296
+ * @typedef {{
297
+ * metadataObj: MetadataObj,
298
+ * schemaItems: {
299
+ * title: string,
300
+ * type: string
301
+ * }[],
302
+ * getFieldAliasOrName: (field: string) => string|string[]|import('../../server/main.js').LocalizationStrings,
303
+ * lang: string[],
304
+ * callback: (cfg: {
305
+ * setName: string,
306
+ * browseFields: BrowseFields,
307
+ * i: number,
308
+ * presort: boolean|undefined
309
+ * }) => void
310
+ * }} GetBrowseFieldDataOptions
311
+ */
312
+
313
+ /**
314
+ * @param {GetBrowseFieldDataOptions} cfg
315
+ */
140
316
  export const getBrowseFieldData = function ({
141
317
  metadataObj, schemaItems, getFieldAliasOrName, lang, callback
142
318
  }) {
@@ -167,16 +343,37 @@ export const getBrowseFieldData = function ({
167
343
 
168
344
  // Todo: Incorporate other methods into this class
169
345
  export class Metadata {
346
+ /**
347
+ * @param {{
348
+ * metadataObj: MetadataObj
349
+ * }} cfg
350
+ */
170
351
  constructor ({metadataObj}) {
171
352
  this.metadataObj = metadataObj;
172
353
  }
173
354
 
355
+ /**
356
+ * @param {string} field
357
+ * @returns {string|undefined}
358
+ */
174
359
  getFieldLang (field) {
175
360
  const {metadataObj} = this;
176
361
  const fields = metadataObj && metadataObj.fields;
177
362
  return fields && fields[field] && fields[field].lang;
178
363
  }
179
364
 
365
+ /**
366
+ * @param {{
367
+ * namespace: string,
368
+ * preferredLocale: string,
369
+ * schemaItems: {
370
+ * title: string,
371
+ * type: string
372
+ * }[],
373
+ * pluginsForWork: import('./Plugin.js').PluginsForWork
374
+ * }} cfg
375
+ * @returns {(field: string) => boolean}
376
+ */
180
377
  getFieldMatchesLocale ({
181
378
  namespace, preferredLocale, schemaItems,
182
379
  pluginsForWork
@@ -203,7 +400,9 @@ export class Metadata {
203
400
  const hasFieldValue = localeStrings &&
204
401
  Object.keys(localeStrings).some((lng) => {
205
402
  const fv = localeStrings[lng] &&
206
- localeStrings[lng].fieldvalue;
403
+ /** @type {import('../../server/main.js').LocalizationStrings} */
404
+ (/** @type {import('../../server/main.js').LocalizationStrings} */
405
+ (localeStrings[lng]).fieldvalue);
207
406
  return fv && fv[field];
208
407
  });
209
408