textbrowser 0.50.0 → 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.
- package/.ncurc.cjs +3 -0
- package/CHANGES.md +8 -0
- package/dist/WorkInfo-es.js +361 -111
- package/dist/activateCallback-es.js +72 -10
- package/dist/dist/WorkInfo-es.d.ts +331 -0
- package/dist/dist/WorkInfo-es.d.ts.map +1 -0
- package/dist/dist/activateCallback-es.d.ts +17 -0
- package/dist/dist/activateCallback-es.d.ts.map +1 -0
- package/dist/dist/index-es.d.ts +619 -0
- package/dist/dist/index-es.d.ts.map +1 -0
- package/dist/dist/sw-helper.d.ts +3 -0
- package/dist/dist/sw-helper.d.ts.map +1 -0
- package/dist/eslint.config.d.ts +126 -0
- package/dist/eslint.config.d.ts.map +1 -0
- package/dist/index-es.js +959 -195
- package/dist/index-es.min.js +2 -2
- package/dist/resources/activateCallback.d.ts +23 -0
- package/dist/resources/activateCallback.d.ts.map +1 -0
- package/dist/resources/index.d.ts +128 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/resultsDisplay.d.ts +110 -0
- package/dist/resources/resultsDisplay.d.ts.map +1 -0
- package/dist/resources/templates/index.d.ts +59 -0
- package/dist/resources/templates/index.d.ts.map +1 -0
- package/dist/resources/templates/languageSelect.d.ts +18 -0
- package/dist/resources/templates/languageSelect.d.ts.map +1 -0
- package/dist/resources/templates/resultsDisplayClient.d.ts +26 -0
- package/dist/resources/templates/resultsDisplayClient.d.ts.map +1 -0
- package/dist/resources/templates/resultsDisplayServerOrClient.d.ts +131 -0
- package/dist/resources/templates/resultsDisplayServerOrClient.d.ts.map +1 -0
- package/dist/resources/templates/utils/dom.d.ts +15 -0
- package/dist/resources/templates/utils/dom.d.ts.map +1 -0
- package/dist/resources/templates/utils/html.d.ts +3 -0
- package/dist/resources/templates/utils/html.d.ts.map +1 -0
- package/dist/resources/templates/workDisplay.d.ts +183 -0
- package/dist/resources/templates/workDisplay.d.ts.map +1 -0
- package/dist/resources/templates/workSelect.d.ts +18 -0
- package/dist/resources/templates/workSelect.d.ts.map +1 -0
- package/dist/resources/user-sample.d.ts +2 -0
- package/dist/resources/user-sample.d.ts.map +1 -0
- package/dist/resources/user.d.ts +2 -0
- package/dist/resources/user.d.ts.map +1 -0
- package/dist/resources/utils/IntlURLSearchParams.d.ts +56 -0
- package/dist/resources/utils/IntlURLSearchParams.d.ts.map +1 -0
- package/dist/resources/utils/Languages.d.ts +81 -0
- package/dist/resources/utils/Languages.d.ts.map +1 -0
- package/dist/resources/utils/Metadata.d.ts +133 -0
- package/dist/resources/utils/Metadata.d.ts.map +1 -0
- package/dist/resources/utils/Params.d.ts +30 -0
- package/dist/resources/utils/Params.d.ts.map +1 -0
- package/dist/resources/utils/Plugin.d.ts +274 -0
- package/dist/resources/utils/Plugin.d.ts.map +1 -0
- package/dist/resources/utils/ServiceWorker.d.ts +26 -0
- package/dist/resources/utils/ServiceWorker.d.ts.map +1 -0
- package/dist/resources/utils/WorkInfo.d.ts +104 -0
- package/dist/resources/utils/WorkInfo.d.ts.map +1 -0
- package/dist/resources/utils/dialogs.d.ts +155 -0
- package/dist/resources/utils/dialogs.d.ts.map +1 -0
- package/dist/resources/utils/getLocaleFallbackResults.d.ts +19 -0
- package/dist/resources/utils/getLocaleFallbackResults.d.ts.map +1 -0
- package/dist/resources/utils/sanitize.d.ts +6 -0
- package/dist/resources/utils/sanitize.d.ts.map +1 -0
- package/dist/resources/vendor/json-refs-min.d.ts +3 -0
- package/dist/resources/vendor/json-refs-min.d.ts.map +1 -0
- package/dist/resources/workDisplay.d.ts +81 -0
- package/dist/resources/workDisplay.d.ts.map +1 -0
- package/dist/resources/workSelect.d.ts +17 -0
- package/dist/resources/workSelect.d.ts.map +1 -0
- package/dist/rollup.config.d.ts +19 -0
- package/dist/rollup.config.d.ts.map +1 -0
- package/dist/server/main.d.ts +46 -0
- package/dist/server/main.d.ts.map +1 -0
- package/dist/sw-helper.d.ts +3 -0
- package/dist/sw-helper.d.ts.map +1 -0
- package/dist/sw-helper.js +52 -12
- package/dist/sw-sample.d.ts +2 -0
- package/dist/sw-sample.d.ts.map +1 -0
- package/general-schemas/files.jsonschema +6 -0
- package/package.json +21 -8
- package/resources/activateCallback.js +75 -10
- package/resources/index.js +161 -49
- package/resources/resultsDisplay.js +517 -152
- package/resources/templates/index.js +39 -16
- package/resources/templates/languageSelect.js +14 -1
- package/resources/templates/resultsDisplayClient.js +22 -3
- package/resources/templates/resultsDisplayServerOrClient.js +188 -49
- package/resources/templates/utils/dom.js +13 -2
- package/resources/templates/workDisplay.js +299 -75
- package/resources/templates/workSelect.js +16 -3
- package/resources/utils/IntlURLSearchParams.js +46 -4
- package/resources/utils/Languages.js +71 -4
- package/resources/utils/Metadata.js +219 -22
- package/resources/utils/Params.js +70 -23
- package/resources/utils/Plugin.js +169 -1
- package/resources/utils/ServiceWorker.js +48 -19
- package/resources/utils/WorkInfo.js +255 -43
- package/resources/utils/dialogs.js +105 -7
- package/resources/utils/getLocaleFallbackResults.js +12 -2
- package/resources/utils/sanitize.js +4 -0
- package/resources/workDisplay.js +151 -25
- package/resources/workSelect.js +37 -17
- package/server/main.js +111 -19
- package/tsconfig.json +30 -0
- package/resources/user.js +0 -20
package/dist/index-es.js
CHANGED
|
@@ -1,18 +1,41 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {JSONValue[]} JSONArray
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {null|boolean|number|string|JSONArray|{[key: string]: JSONValue}} JSONValue
|
|
6
|
+
*/
|
|
2
7
|
|
|
3
8
|
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
* @callback SimpleJSONCallback
|
|
10
|
+
* @param {...JSONValue} json
|
|
11
|
+
* @returns {void}
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @callback SimpleJSONErrback
|
|
16
|
+
* @param {Error} err
|
|
17
|
+
* @param {string|string[]} jsonURL
|
|
18
|
+
* @returns {JSONValue}
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {((
|
|
23
|
+
* jsonURL: string|string[],
|
|
24
|
+
* cb?: SimpleJSONCallback,
|
|
25
|
+
* errBack?: SimpleJSONErrback
|
|
26
|
+
* ) => Promise<JSONValue>) & {
|
|
27
|
+
* _fetch?: import('./index-polyglot.js').SimpleFetch,
|
|
28
|
+
* hasURLBasePath?: boolean,
|
|
29
|
+
* basePath?: string|false
|
|
30
|
+
* }} getJSONCallback
|
|
9
31
|
*/
|
|
10
32
|
|
|
11
33
|
/**
|
|
12
|
-
* @param {
|
|
13
|
-
* @param {
|
|
34
|
+
* @param {object} [cfg]
|
|
35
|
+
* @param {import('./index-polyglot.js').SimpleFetch} [cfg.fetch]
|
|
14
36
|
* @returns {getJSONCallback}
|
|
15
37
|
*/
|
|
38
|
+
|
|
16
39
|
function _await$2$1(value, then, direct) {
|
|
17
40
|
if (!value || !value.then) {
|
|
18
41
|
value = Promise.resolve(value);
|
|
@@ -38,22 +61,9 @@ function _catch$2(body, recover) {
|
|
|
38
61
|
return result;
|
|
39
62
|
}
|
|
40
63
|
function buildGetJSONWithFetch({
|
|
41
|
-
// eslint-disable-next-line no-shadow
|
|
64
|
+
// eslint-disable-next-line no-shadow, no-undef -- This is a polyfill
|
|
42
65
|
fetch = typeof window !== 'undefined' ? window.fetch : self.fetch
|
|
43
66
|
} = {}) {
|
|
44
|
-
/**
|
|
45
|
-
* @callback SimpleJSONCallback
|
|
46
|
-
* @param {JSON} json
|
|
47
|
-
* @returns {void}
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* @callback SimpleJSONErrback
|
|
52
|
-
* @param {Error} err
|
|
53
|
-
* @param {string|string[]} jsonURL
|
|
54
|
-
* @returns {void}
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
67
|
/**
|
|
58
68
|
* @type {getJSONCallback}
|
|
59
69
|
*/
|
|
@@ -64,10 +74,10 @@ function buildGetJSONWithFetch({
|
|
|
64
74
|
return _invoke$1(function () {
|
|
65
75
|
if (Array.isArray(jsonURL)) {
|
|
66
76
|
return _await$2$1(Promise.all(jsonURL.map(url => {
|
|
67
|
-
return getJSON(url);
|
|
77
|
+
return /** @type {getJSONCallback} */getJSON(url);
|
|
68
78
|
})), function (arrResult) {
|
|
69
79
|
if (cb) {
|
|
70
|
-
// eslint-disable-next-line
|
|
80
|
+
// eslint-disable-next-line promise/prefer-await-to-callbacks -- Old-style API
|
|
71
81
|
cb(...arrResult);
|
|
72
82
|
}
|
|
73
83
|
_exit = true;
|
|
@@ -77,20 +87,22 @@ function buildGetJSONWithFetch({
|
|
|
77
87
|
}, function (_result) {
|
|
78
88
|
return _exit ? _result : _await$2$1(fetch(jsonURL), function (resp) {
|
|
79
89
|
return _await$2$1(resp.json(), function (result) {
|
|
80
|
-
return typeof cb === 'function'
|
|
81
|
-
|
|
82
|
-
|
|
90
|
+
return typeof cb === 'function'
|
|
91
|
+
// eslint-disable-next-line promise/prefer-await-to-callbacks -- Old-style API
|
|
92
|
+
? cb(result) : result;
|
|
93
|
+
// https://github.com/bcoe/c8/issues/135
|
|
83
94
|
/* c8 ignore next */
|
|
84
95
|
});
|
|
85
96
|
});
|
|
86
97
|
});
|
|
87
|
-
}, function (
|
|
98
|
+
}, function (err) {
|
|
99
|
+
const e = /** @type {Error} */err;
|
|
88
100
|
e.message += ` (File: ${jsonURL})`;
|
|
89
101
|
if (errBack) {
|
|
90
102
|
return errBack(e, jsonURL);
|
|
91
103
|
}
|
|
92
|
-
throw e;
|
|
93
|
-
|
|
104
|
+
throw e;
|
|
105
|
+
// https://github.com/bcoe/c8/issues/135
|
|
94
106
|
/* c8 ignore next */
|
|
95
107
|
}));
|
|
96
108
|
/* c8 ignore next */
|
|
@@ -105,27 +117,33 @@ function _await$1$1(value, then, direct) {
|
|
|
105
117
|
}
|
|
106
118
|
return then ? value.then(then) : value;
|
|
107
119
|
}
|
|
120
|
+
/* globals process -- Node */
|
|
108
121
|
|
|
109
|
-
/* eslint-disable node/no-unsupported-features/node-builtins,
|
|
110
|
-
node/no-unsupported-features/es-syntax, compat/compat */
|
|
111
122
|
// Needed for polyglot support (no `path` in browser); even if
|
|
112
123
|
// polyglot using dynamic `import` not supported by Rollup (complaining
|
|
113
124
|
// of inability to do tree-shaking in UMD builds), still useful to delay
|
|
114
125
|
// path import for our testing, so that test can import this file in
|
|
115
126
|
// the browser without compilation without it choking
|
|
116
|
-
|
|
117
|
-
function _empty() {}
|
|
127
|
+
|
|
118
128
|
/**
|
|
119
|
-
* @
|
|
120
|
-
* @returns {string}
|
|
129
|
+
* @type {(directory: string) => string}
|
|
121
130
|
*/
|
|
131
|
+
let dirname;
|
|
132
|
+
|
|
133
|
+
/** @type {boolean} */
|
|
122
134
|
|
|
135
|
+
function _empty() {}
|
|
136
|
+
let isWindows;
|
|
123
137
|
function _invokeIgnored(body) {
|
|
124
138
|
var result = body();
|
|
125
139
|
if (result && result.then) {
|
|
126
140
|
return result.then(_empty);
|
|
127
141
|
}
|
|
128
|
-
}
|
|
142
|
+
} /**
|
|
143
|
+
* @param {string} path
|
|
144
|
+
* @returns {string}
|
|
145
|
+
*/
|
|
146
|
+
|
|
129
147
|
function _async$1$1(f) {
|
|
130
148
|
return function () {
|
|
131
149
|
for (var args = [], i = 0; i < arguments.length; i++) {
|
|
@@ -141,7 +159,7 @@ function _async$1$1(f) {
|
|
|
141
159
|
const setDirname = _async$1$1(function () {
|
|
142
160
|
return _invokeIgnored(function () {
|
|
143
161
|
if (!dirname) {
|
|
144
|
-
return _await$1$1(import('path'), function (_import) {
|
|
162
|
+
return _await$1$1(import('node:path'), function (_import) {
|
|
145
163
|
({
|
|
146
164
|
dirname
|
|
147
165
|
} = _import);
|
|
@@ -155,15 +173,14 @@ function fixWindowsPath(path) {
|
|
|
155
173
|
}
|
|
156
174
|
return path.slice(
|
|
157
175
|
// https://github.com/bcoe/c8/issues/135
|
|
158
|
-
|
|
159
176
|
/* c8 ignore next */
|
|
160
177
|
isWindows ? 1 : 0);
|
|
161
178
|
}
|
|
179
|
+
|
|
162
180
|
/**
|
|
163
181
|
* @param {string} url
|
|
164
182
|
* @returns {string}
|
|
165
183
|
*/
|
|
166
|
-
|
|
167
184
|
function getDirectoryForURL(url) {
|
|
168
185
|
// Node should be ok with this, but transpiling
|
|
169
186
|
// to `require` doesn't work, so detect Windows
|
|
@@ -172,7 +189,13 @@ function getDirectoryForURL(url) {
|
|
|
172
189
|
return fixWindowsPath(dirname(new URL(url).pathname));
|
|
173
190
|
}
|
|
174
191
|
|
|
175
|
-
/*
|
|
192
|
+
/* globals window, self -- Polyglot */
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @typedef {(url: string) => Promise<Response>} SimpleFetch
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
/** @type {{default: SimpleFetch}} */
|
|
176
199
|
|
|
177
200
|
function _await$3(value, then, direct) {
|
|
178
201
|
if (!value || !value.then) {
|
|
@@ -182,10 +205,10 @@ function _await$3(value, then, direct) {
|
|
|
182
205
|
}
|
|
183
206
|
let nodeFetch;
|
|
184
207
|
/**
|
|
185
|
-
* @param {
|
|
186
|
-
* @param {string} cfg.baseURL
|
|
187
|
-
* @param {string} cfg.cwd
|
|
188
|
-
* @returns {getJSONCallback}
|
|
208
|
+
* @param {object} [cfg]
|
|
209
|
+
* @param {string} [cfg.baseURL]
|
|
210
|
+
* @param {string|false} [cfg.cwd]
|
|
211
|
+
* @returns {import('./buildGetJSONWithFetch.js').getJSONCallback}
|
|
189
212
|
*/
|
|
190
213
|
|
|
191
214
|
function _invoke$2(body, then) {
|
|
@@ -219,18 +242,27 @@ function buildGetJSON({
|
|
|
219
242
|
baseURL,
|
|
220
243
|
cwd: basePath
|
|
221
244
|
} = {}) {
|
|
222
|
-
const _fetch = typeof window !== 'undefined' || typeof self !== 'undefined' ? typeof window !== 'undefined' ? window.fetch : self.fetch
|
|
245
|
+
const _fetch = typeof window !== 'undefined' || typeof self !== 'undefined' ? typeof window !== 'undefined' ? window.fetch : self.fetch
|
|
246
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- TS
|
|
247
|
+
:
|
|
248
|
+
/**
|
|
249
|
+
* @param {string} jsonURL
|
|
250
|
+
* @returns {Promise<Response>}
|
|
251
|
+
*/
|
|
252
|
+
_async$2(function (jsonURL) {
|
|
223
253
|
let _exit = false;
|
|
224
254
|
return _invoke$2(function () {
|
|
225
255
|
if (/^https?:/u.test(jsonURL)) {
|
|
226
256
|
return _invoke$2(function () {
|
|
227
257
|
if (!nodeFetch) {
|
|
228
|
-
return _await$3(import('node-fetch'), function (
|
|
258
|
+
return _await$3(import('node-fetch'), function (/** @type {{default: SimpleFetch}} */
|
|
259
|
+
/** @type {unknown} */
|
|
260
|
+
_import) {
|
|
229
261
|
nodeFetch = _import;
|
|
230
262
|
});
|
|
231
263
|
}
|
|
232
264
|
}, function () {
|
|
233
|
-
const _nodeFetch$default = nodeFetch.default(jsonURL);
|
|
265
|
+
const _nodeFetch$default = /** @type {SimpleFetch} */nodeFetch.default(jsonURL);
|
|
234
266
|
_exit = true;
|
|
235
267
|
return _nodeFetch$default;
|
|
236
268
|
});
|
|
@@ -246,40 +278,46 @@ function buildGetJSON({
|
|
|
246
278
|
// Filed https://github.com/bergos/file-fetch/issues/12 to see
|
|
247
279
|
// about getting relative basePaths in `file-fetch` and using
|
|
248
280
|
// that better-tested package instead
|
|
281
|
+
// @ts-expect-error Todo
|
|
282
|
+
// Don't change to an import as won't resolve for browser testing
|
|
283
|
+
// eslint-disable-next-line promise/avoid-new -- own API
|
|
284
|
+
/* c8 ignore next */
|
|
249
285
|
return _await$3(import('local-xmlhttprequest'), function (localXMLHttpRequest) {
|
|
250
|
-
|
|
251
|
-
|
|
286
|
+
const XMLHttpRequest = /* eslint-disable jsdoc/valid-types -- Bug */
|
|
287
|
+
/**
|
|
288
|
+
* @type {{
|
|
289
|
+
* prototype: XMLHttpRequest;
|
|
290
|
+
* new(): XMLHttpRequest
|
|
291
|
+
* }}
|
|
292
|
+
*/localXMLHttpRequest.default({
|
|
293
|
+
/* eslint-enable jsdoc/valid-types -- Bug */
|
|
252
294
|
basePath
|
|
253
|
-
});
|
|
254
|
-
// eslint-disable-next-line promise/avoid-new
|
|
255
|
-
|
|
295
|
+
});
|
|
256
296
|
return new Promise((resolve, reject) => {
|
|
257
297
|
const r = new XMLHttpRequest();
|
|
258
|
-
r.open('GET', jsonURL, true);
|
|
298
|
+
r.open('GET', jsonURL, true);
|
|
299
|
+
// r.responseType = 'json';
|
|
259
300
|
// eslint-disable-next-line unicorn/prefer-add-event-listener -- May not be available
|
|
260
|
-
|
|
261
301
|
r.onreadystatechange = function () {
|
|
262
302
|
// Not sure how to simulate `if`
|
|
263
|
-
|
|
264
|
-
/* c8 ignore next */
|
|
303
|
+
/* c8 ignore next 3 */
|
|
265
304
|
if (r.readyState !== 4) {
|
|
266
305
|
return;
|
|
267
306
|
}
|
|
268
307
|
if (r.status === 200) {
|
|
269
308
|
// var json = r.json;
|
|
270
309
|
const response = r.responseText;
|
|
271
|
-
resolve({
|
|
310
|
+
resolve(/** @type {Response} */{
|
|
272
311
|
json: () => JSON.parse(response)
|
|
273
312
|
});
|
|
274
313
|
return;
|
|
275
314
|
}
|
|
276
315
|
reject(new SyntaxError('Failed to fetch URL: ' + jsonURL + 'state: ' + r.readyState + '; status: ' + r.status));
|
|
277
316
|
};
|
|
278
|
-
r.send();
|
|
279
|
-
|
|
317
|
+
r.send();
|
|
318
|
+
// https://github.com/bcoe/c8/issues/135
|
|
280
319
|
/* c8 ignore next */
|
|
281
320
|
});
|
|
282
|
-
/* c8 ignore next */
|
|
283
321
|
});
|
|
284
322
|
});
|
|
285
323
|
});
|
|
@@ -3710,6 +3748,17 @@ function deserialize(form, hash) {
|
|
|
3710
3748
|
/**
|
|
3711
3749
|
* @file Note that this should be kept as a polyglot client-server file.
|
|
3712
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
|
+
*/
|
|
3713
3762
|
async function getLocaleFallbackResults(_ref) {
|
|
3714
3763
|
let {
|
|
3715
3764
|
$p,
|
|
@@ -3728,9 +3777,9 @@ async function getLocaleFallbackResults(_ref) {
|
|
|
3728
3777
|
// `$ref` (as with <https://github.com/whitlockjc/json-refs>) and
|
|
3729
3778
|
// replace `loadLocales` behavior with our own now resolved
|
|
3730
3779
|
// locales; see https://github.com/jdorn/json-editor/issues/132
|
|
3731
|
-
return basePath + langData.localeFileBasePath + langs.find(l => {
|
|
3780
|
+
return basePath + langData.localeFileBasePath + (langs.find(l => {
|
|
3732
3781
|
return l.code === code;
|
|
3733
|
-
})
|
|
3782
|
+
})?.locale?.$ref ?? '');
|
|
3734
3783
|
}
|
|
3735
3784
|
});
|
|
3736
3785
|
if (!$p.l10n) {
|
|
@@ -6061,13 +6110,35 @@ if (doc && doc.body) {
|
|
|
6061
6110
|
}
|
|
6062
6111
|
const nbsp = '\u00A0'; // Very commonly needed in templates
|
|
6063
6112
|
|
|
6113
|
+
/**
|
|
6114
|
+
* @param {string} sel
|
|
6115
|
+
*/
|
|
6064
6116
|
const $ = sel => document.querySelector(sel);
|
|
6117
|
+
|
|
6118
|
+
/**
|
|
6119
|
+
* @param {string|HTMLElement} el
|
|
6120
|
+
* @param {string} descendentsSel
|
|
6121
|
+
*/
|
|
6065
6122
|
const $e = (el, descendentsSel) => {
|
|
6066
|
-
|
|
6067
|
-
return
|
|
6123
|
+
const elem = typeof el === 'string' ? $(el) : el;
|
|
6124
|
+
return elem?.querySelector(descendentsSel);
|
|
6068
6125
|
};
|
|
6069
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
|
+
|
|
6070
6139
|
const defaultLocale = 'en';
|
|
6140
|
+
|
|
6141
|
+
/** @type {Locales} */
|
|
6071
6142
|
const localeStrings = {
|
|
6072
6143
|
en: {
|
|
6073
6144
|
submit: 'Submit',
|
|
@@ -6076,27 +6147,72 @@ const localeStrings = {
|
|
|
6076
6147
|
}
|
|
6077
6148
|
};
|
|
6078
6149
|
class Dialog {
|
|
6150
|
+
/**
|
|
6151
|
+
* @param {{
|
|
6152
|
+
* locale?: string,
|
|
6153
|
+
* localeObject?: LocaleObject
|
|
6154
|
+
* }} [cfg]
|
|
6155
|
+
*/
|
|
6079
6156
|
constructor() {
|
|
6080
6157
|
let {
|
|
6081
6158
|
locale,
|
|
6082
6159
|
localeObject
|
|
6083
6160
|
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
6161
|
+
this.localeStrings = localeStrings.en; // For types
|
|
6084
6162
|
this.setLocale({
|
|
6085
6163
|
locale,
|
|
6086
6164
|
localeObject
|
|
6087
6165
|
});
|
|
6088
6166
|
}
|
|
6167
|
+
/**
|
|
6168
|
+
* @param {{
|
|
6169
|
+
* locale?: string,
|
|
6170
|
+
* localeObject?: Partial<LocaleObject>
|
|
6171
|
+
* }} cfg
|
|
6172
|
+
* @returns {void}
|
|
6173
|
+
*/
|
|
6089
6174
|
setLocale(_ref) {
|
|
6090
6175
|
let {
|
|
6091
|
-
locale
|
|
6176
|
+
locale,
|
|
6092
6177
|
localeObject = {}
|
|
6093
6178
|
} = _ref;
|
|
6094
6179
|
this.localeStrings = {
|
|
6095
6180
|
...localeStrings[defaultLocale],
|
|
6096
|
-
...localeStrings[locale],
|
|
6181
|
+
...(locale ? localeStrings[locale] : {}),
|
|
6097
6182
|
...localeObject
|
|
6098
6183
|
};
|
|
6099
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
|
+
*/
|
|
6100
6216
|
makeDialog(_ref2) {
|
|
6101
6217
|
let {
|
|
6102
6218
|
atts = {
|
|
@@ -6114,7 +6230,8 @@ class Dialog {
|
|
|
6114
6230
|
atts.$on.close = close;
|
|
6115
6231
|
}
|
|
6116
6232
|
}
|
|
6117
|
-
const dialog = /** @type {HTMLDialogElement} */
|
|
6233
|
+
const dialog = /** @type {HTMLDialogElement} */
|
|
6234
|
+
jml('dialog', atts, children, $$1('#main'));
|
|
6118
6235
|
dialog.showModal();
|
|
6119
6236
|
if (remove) {
|
|
6120
6237
|
dialog.addEventListener('close', () => {
|
|
@@ -6123,6 +6240,10 @@ class Dialog {
|
|
|
6123
6240
|
}
|
|
6124
6241
|
return dialog;
|
|
6125
6242
|
}
|
|
6243
|
+
/**
|
|
6244
|
+
* @param {CancelDialogCfg} cfg
|
|
6245
|
+
* @returns {HTMLDialogElement}
|
|
6246
|
+
*/
|
|
6126
6247
|
makeSubmitDialog(_ref3) {
|
|
6127
6248
|
let {
|
|
6128
6249
|
submit,
|
|
@@ -6131,6 +6252,7 @@ class Dialog {
|
|
|
6131
6252
|
...args
|
|
6132
6253
|
} = _ref3;
|
|
6133
6254
|
const dialog = this.makeCancelDialog(args);
|
|
6255
|
+
/** @type {HTMLDialogElement} */
|
|
6134
6256
|
$e(dialog, `button.${args.cancelClass || 'cancel'}`).before(jml('button', {
|
|
6135
6257
|
class: submitClass,
|
|
6136
6258
|
$on: {
|
|
@@ -6146,6 +6268,11 @@ class Dialog {
|
|
|
6146
6268
|
}, [this.localeStrings.submit]), nbsp.repeat(2));
|
|
6147
6269
|
return dialog;
|
|
6148
6270
|
}
|
|
6271
|
+
|
|
6272
|
+
/**
|
|
6273
|
+
* @param {CancelDialogCfg} cfg
|
|
6274
|
+
* @returns {HTMLDialogElement}
|
|
6275
|
+
*/
|
|
6149
6276
|
makeCancelDialog(_ref4) {
|
|
6150
6277
|
let {
|
|
6151
6278
|
// eslint-disable-next-line no-unused-vars -- Discarding
|
|
@@ -6178,6 +6305,12 @@ class Dialog {
|
|
|
6178
6305
|
}, [this.localeStrings.cancel]]], dialog);
|
|
6179
6306
|
return dialog;
|
|
6180
6307
|
}
|
|
6308
|
+
|
|
6309
|
+
/**
|
|
6310
|
+
* @param {string|{message: string, ok?: boolean, submitClass?: string}} message
|
|
6311
|
+
* @param {boolean|{ok: boolean}} [ok]
|
|
6312
|
+
* @returns {Promise<void>}
|
|
6313
|
+
*/
|
|
6181
6314
|
alert(message, ok) {
|
|
6182
6315
|
message = typeof message === 'string' ? {
|
|
6183
6316
|
message
|
|
@@ -6188,7 +6321,7 @@ class Dialog {
|
|
|
6188
6321
|
submitClass = 'submit'
|
|
6189
6322
|
} = message;
|
|
6190
6323
|
return new Promise(resolve => {
|
|
6191
|
-
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', {
|
|
6192
6325
|
class: submitClass
|
|
6193
6326
|
}, [['button', {
|
|
6194
6327
|
$on: {
|
|
@@ -6197,10 +6330,16 @@ class Dialog {
|
|
|
6197
6330
|
resolve();
|
|
6198
6331
|
}
|
|
6199
6332
|
}
|
|
6200
|
-
}, [this.localeStrings.ok]]]]] : [])], $$1('#main'));
|
|
6333
|
+
}, [this.localeStrings.ok]]]]]) : [])], $$1('#main'));
|
|
6201
6334
|
dialog.showModal();
|
|
6202
6335
|
});
|
|
6203
6336
|
}
|
|
6337
|
+
/**
|
|
6338
|
+
* @param {string|Partial<CancelDialogCfg> & {
|
|
6339
|
+
* message: string
|
|
6340
|
+
* }} message
|
|
6341
|
+
* @returns {Promise<string>}
|
|
6342
|
+
*/
|
|
6204
6343
|
prompt(message) {
|
|
6205
6344
|
message = typeof message === 'string' ? {
|
|
6206
6345
|
message
|
|
@@ -6211,19 +6350,28 @@ class Dialog {
|
|
|
6211
6350
|
...submitArgs
|
|
6212
6351
|
} = message;
|
|
6213
6352
|
return new Promise((resolve, reject) => {
|
|
6353
|
+
/**
|
|
6354
|
+
* @param {{
|
|
6355
|
+
* e: Event,
|
|
6356
|
+
* dialog: HTMLDialogElement
|
|
6357
|
+
* }} args
|
|
6358
|
+
*/
|
|
6214
6359
|
const submit = function (_ref5) {
|
|
6215
6360
|
let {
|
|
6216
6361
|
e,
|
|
6217
6362
|
dialog
|
|
6218
6363
|
} = _ref5;
|
|
6219
6364
|
if (userSubmit) {
|
|
6220
|
-
userSubmit.call(
|
|
6365
|
+
userSubmit.call(
|
|
6366
|
+
// @ts-expect-error Ok
|
|
6367
|
+
/** @type {HTMLElement} */
|
|
6368
|
+
this, {
|
|
6221
6369
|
e,
|
|
6222
6370
|
dialog
|
|
6223
6371
|
});
|
|
6224
6372
|
}
|
|
6225
6373
|
dialog.close();
|
|
6226
|
-
resolve(
|
|
6374
|
+
resolve(/** @type {HTMLInputElement} */$e(dialog, 'input').value);
|
|
6227
6375
|
};
|
|
6228
6376
|
/* const dialog = */
|
|
6229
6377
|
this.makeSubmitDialog({
|
|
@@ -6236,6 +6384,10 @@ class Dialog {
|
|
|
6236
6384
|
});
|
|
6237
6385
|
});
|
|
6238
6386
|
}
|
|
6387
|
+
/**
|
|
6388
|
+
* @param {string|{message: string, submitClass?: string}} message
|
|
6389
|
+
* @returns {Promise<void>}
|
|
6390
|
+
*/
|
|
6239
6391
|
confirm(message) {
|
|
6240
6392
|
message = typeof message === 'string' ? {
|
|
6241
6393
|
message
|
|
@@ -6269,6 +6421,13 @@ class Dialog {
|
|
|
6269
6421
|
const dialogs = new Dialog();
|
|
6270
6422
|
|
|
6271
6423
|
// Todo: remember this locales choice by cookie?
|
|
6424
|
+
|
|
6425
|
+
/**
|
|
6426
|
+
* @param {{
|
|
6427
|
+
* namespace: string,
|
|
6428
|
+
* preferredLocale: string
|
|
6429
|
+
* }} cfg
|
|
6430
|
+
*/
|
|
6272
6431
|
const getPreferredLanguages = _ref => {
|
|
6273
6432
|
let {
|
|
6274
6433
|
namespace,
|
|
@@ -6278,7 +6437,10 @@ const getPreferredLanguages = _ref => {
|
|
|
6278
6437
|
// Todo: Switch to fallbackLanguages so can default to
|
|
6279
6438
|
// navigator.languages?
|
|
6280
6439
|
const langCodes = localStorage.getItem(namespace + '-langCodes');
|
|
6281
|
-
const lngs =
|
|
6440
|
+
const lngs = /** @type {string[]} */
|
|
6441
|
+
langCodes && JSON.parse(langCodes) || [preferredLocale];
|
|
6442
|
+
|
|
6443
|
+
/** @type {string[]} */
|
|
6282
6444
|
const langArr = [];
|
|
6283
6445
|
lngs.forEach(lng => {
|
|
6284
6446
|
// Todo: Check for multiple separate hyphenated
|
|
@@ -6297,20 +6459,62 @@ const getPreferredLanguages = _ref => {
|
|
|
6297
6459
|
* @classdesc Note that this should be kept as a polyglot client-server class.
|
|
6298
6460
|
*/
|
|
6299
6461
|
class Languages {
|
|
6462
|
+
/**
|
|
6463
|
+
* @param {{
|
|
6464
|
+
* langData: import('../../server/main.js').LanguagesData
|
|
6465
|
+
* }} cfg
|
|
6466
|
+
*/
|
|
6300
6467
|
constructor(_ref2) {
|
|
6301
6468
|
let {
|
|
6302
6469
|
langData
|
|
6303
6470
|
} = _ref2;
|
|
6304
6471
|
this.langData = langData;
|
|
6305
6472
|
}
|
|
6473
|
+
/**
|
|
6474
|
+
* @param {string} langCode
|
|
6475
|
+
* @returns {{
|
|
6476
|
+
* languages: {
|
|
6477
|
+
* [key: string]: string
|
|
6478
|
+
* }
|
|
6479
|
+
* }}
|
|
6480
|
+
*/
|
|
6306
6481
|
localeFromLangData(langCode) {
|
|
6307
|
-
return
|
|
6482
|
+
return (
|
|
6483
|
+
/**
|
|
6484
|
+
* @type {{
|
|
6485
|
+
* languages: {
|
|
6486
|
+
* [key: string]: string
|
|
6487
|
+
* }
|
|
6488
|
+
* }}
|
|
6489
|
+
*/
|
|
6490
|
+
this.langData['localization-strings'][langCode]
|
|
6491
|
+
);
|
|
6308
6492
|
}
|
|
6493
|
+
/**
|
|
6494
|
+
* @param {string} code
|
|
6495
|
+
* @returns {string}
|
|
6496
|
+
*/
|
|
6309
6497
|
getLanguageFromCode(code) {
|
|
6310
6498
|
return this.localeFromLangData(code).languages[code];
|
|
6311
6499
|
// Could add something like this in place or as fallback, though need to pass in locale
|
|
6312
6500
|
// || new Intl.DisplayNames([locale], {type: 'language'}).of(code);
|
|
6313
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
|
+
*/
|
|
6314
6518
|
getFieldNameFromPluginNameAndLocales(_ref3) {
|
|
6315
6519
|
let {
|
|
6316
6520
|
pluginName,
|
|
@@ -6321,7 +6525,7 @@ class Languages {
|
|
|
6321
6525
|
meta,
|
|
6322
6526
|
metaApplicableField
|
|
6323
6527
|
} = _ref3;
|
|
6324
|
-
return workI18n(['plugins', pluginName, 'fieldname'], {
|
|
6528
|
+
return /** @type {string} */workI18n(['plugins', pluginName, 'fieldname'], {
|
|
6325
6529
|
...meta,
|
|
6326
6530
|
...metaApplicableField,
|
|
6327
6531
|
applicableField: applicableFieldI18N,
|
|
@@ -6331,11 +6535,24 @@ class Languages {
|
|
|
6331
6535
|
throwOnExtraSuppliedFormatters: false
|
|
6332
6536
|
});
|
|
6333
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
|
+
*/
|
|
6334
6548
|
getLanguageInfo(_ref4) {
|
|
6335
6549
|
let {
|
|
6336
6550
|
$p
|
|
6337
6551
|
} = _ref4;
|
|
6338
6552
|
const langs = this.langData.languages;
|
|
6553
|
+
/**
|
|
6554
|
+
* @param {string} lcl
|
|
6555
|
+
*/
|
|
6339
6556
|
const localePass = lcl => {
|
|
6340
6557
|
return langs.some(_ref5 => {
|
|
6341
6558
|
let {
|
|
@@ -14285,23 +14502,57 @@ var JsonRefs = function (t) {
|
|
|
14285
14502
|
const getCurrDir = () => {
|
|
14286
14503
|
return window.location.href.replace(/(index\.html)?#.*$/, '');
|
|
14287
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
|
+
*/
|
|
14288
14534
|
const getMetaProp = function getMetaProp(lang, metadataObj, properties, allowObjects) {
|
|
14289
14535
|
let prop;
|
|
14290
14536
|
properties = typeof properties === 'string' ? [properties] : properties;
|
|
14291
|
-
|
|
14537
|
+
for (const lan of lang) {
|
|
14292
14538
|
const p = [...properties];
|
|
14293
|
-
let strings =
|
|
14539
|
+
let strings = /** @type {string | string[]|import('../../server/main.js').LocalizationStrings} */
|
|
14540
|
+
metadataObj['localization-strings'][lan];
|
|
14294
14541
|
while (strings && p.length) {
|
|
14295
|
-
strings = strings[p.shift()];
|
|
14542
|
+
strings = /** @type {import('../../server/main.js').LocalizationStrings} */strings[(/** @type {string} */p.shift())];
|
|
14296
14543
|
}
|
|
14297
14544
|
// Todo: Fix this allowance for allowObjects (as it does not properly
|
|
14298
14545
|
// fallback if an object is returned from a language because
|
|
14299
14546
|
// that language is missing content and is only thus returning
|
|
14300
14547
|
// an object)
|
|
14301
14548
|
prop = allowObjects || typeof strings === 'string' ? strings : undefined;
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14549
|
+
if (prop) {
|
|
14550
|
+
break;
|
|
14551
|
+
}
|
|
14552
|
+
}
|
|
14553
|
+
return /** @type {string|string[]|import('../../server/main.js').LocalizationStrings} */(
|
|
14554
|
+
prop
|
|
14555
|
+
);
|
|
14305
14556
|
};
|
|
14306
14557
|
|
|
14307
14558
|
// Use the following to dynamically add specific file schema in place of
|
|
@@ -14309,6 +14560,12 @@ const getMetaProp = function getMetaProp(lang, metadataObj, properties, allowObj
|
|
|
14309
14560
|
// filesSchema.properties.groups.items.properties.files.items.properties.
|
|
14310
14561
|
// file.anyOf.splice(1, 1, {$ref: schemaFile});
|
|
14311
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
|
+
*/
|
|
14312
14569
|
const getMetadata = async (file, property, basePath) => {
|
|
14313
14570
|
const url = new URL(basePath || getCurrDir());
|
|
14314
14571
|
url.search = ''; // Clear out query string, e.g., `?fbclid` from Facebook
|
|
@@ -14316,6 +14573,13 @@ const getMetadata = async (file, property, basePath) => {
|
|
|
14316
14573
|
url.hash = property ? '#/' + property : '';
|
|
14317
14574
|
return (await JsonRefs.resolveRefsAt(url.toString(), {
|
|
14318
14575
|
loaderOptions: {
|
|
14576
|
+
/**
|
|
14577
|
+
* @param {{
|
|
14578
|
+
* text: string,
|
|
14579
|
+
* body: any
|
|
14580
|
+
* }} res
|
|
14581
|
+
* @param {(err?: Error, cbValue: any) => void} callback
|
|
14582
|
+
*/
|
|
14319
14583
|
processContent(res, callback) {
|
|
14320
14584
|
callback(undefined, JSON.parse(res.text ||
|
|
14321
14585
|
// `.metadata` not a recognized extension, so
|
|
@@ -14325,6 +14589,37 @@ const getMetadata = async (file, property, basePath) => {
|
|
|
14325
14589
|
}
|
|
14326
14590
|
})).resolved;
|
|
14327
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
|
+
*/
|
|
14328
14623
|
const getFieldNameAndValueAliases = function (_ref) {
|
|
14329
14624
|
let {
|
|
14330
14625
|
field,
|
|
@@ -14338,6 +14633,22 @@ const getFieldNameAndValueAliases = function (_ref) {
|
|
|
14338
14633
|
});
|
|
14339
14634
|
const fieldSchema = schemaItems[fieldSchemaIndex];
|
|
14340
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
|
+
*/
|
|
14341
14652
|
const ret = {
|
|
14342
14653
|
// field,
|
|
14343
14654
|
aliases: null,
|
|
@@ -14349,10 +14660,14 @@ const getFieldNameAndValueAliases = function (_ref) {
|
|
|
14349
14660
|
preferAlias: fieldInfo.prefer_alias,
|
|
14350
14661
|
lang: fieldInfo.lang
|
|
14351
14662
|
};
|
|
14663
|
+
|
|
14664
|
+
/** @type {import('../../server/main.js').LocalizationStrings} */
|
|
14352
14665
|
let fieldValueAliasMap = fieldInfo && fieldInfo['fieldvalue-aliases'];
|
|
14353
14666
|
if (fieldValueAliasMap) {
|
|
14354
14667
|
if (fieldValueAliasMap.localeKey) {
|
|
14355
|
-
fieldValueAliasMap =
|
|
14668
|
+
fieldValueAliasMap = /** @type {import('../../server/main.js').LocalizationStrings} */
|
|
14669
|
+
getMetaProp(lang, metadataObj, /** @type {string} */
|
|
14670
|
+
fieldValueAliasMap.localeKey.split('/'), true);
|
|
14356
14671
|
}
|
|
14357
14672
|
// eslint-disable-next-line unicorn/prefer-structured-clone -- Expecting JSON
|
|
14358
14673
|
ret.rawFieldValueAliasMap = JSON.parse(JSON.stringify(fieldValueAliasMap));
|
|
@@ -14361,11 +14676,14 @@ const getFieldNameAndValueAliases = function (_ref) {
|
|
|
14361
14676
|
// needed cases
|
|
14362
14677
|
if (fieldSchema.enum && fieldSchema.enum.length) {
|
|
14363
14678
|
fieldSchema.enum.forEach(enm => {
|
|
14364
|
-
|
|
14679
|
+
/** @type {string[]} */
|
|
14680
|
+
ret.aliases.push(/** @type {string} */
|
|
14681
|
+
getMetaProp(lang, metadataObj, ['fieldvalue', field, enm], true));
|
|
14365
14682
|
if (enm in fieldValueAliasMap &&
|
|
14366
14683
|
// Todo: We could allow numbers here too, but crowds
|
|
14367
14684
|
// pull-down
|
|
14368
14685
|
typeof fieldValueAliasMap[enm] === 'string') {
|
|
14686
|
+
/** @type {string[]} */
|
|
14369
14687
|
ret.aliases.push(...fieldValueAliasMap[enm]);
|
|
14370
14688
|
}
|
|
14371
14689
|
});
|
|
@@ -14378,9 +14696,12 @@ const getFieldNameAndValueAliases = function (_ref) {
|
|
|
14378
14696
|
// We'll preserve the numbers since probably more useful if
|
|
14379
14697
|
// stored with data (as opposed to enums)
|
|
14380
14698
|
if (!Array.isArray(aliases)) {
|
|
14381
|
-
aliases =
|
|
14699
|
+
aliases = /** @type {string[]} */
|
|
14700
|
+
Object.values(/** @type {import('../../server/main.js').LocalizationStrings} */
|
|
14701
|
+
aliases);
|
|
14382
14702
|
}
|
|
14383
14703
|
// We'll assume the longest version is best for auto-complete
|
|
14704
|
+
/** @type {string[]} */
|
|
14384
14705
|
ret.aliases.push(...aliases.filter(v => {
|
|
14385
14706
|
return aliases.every(x => {
|
|
14386
14707
|
return x === v || !x.toLowerCase().startsWith(v.toLowerCase());
|
|
@@ -14395,6 +14716,40 @@ const getFieldNameAndValueAliases = function (_ref) {
|
|
|
14395
14716
|
}
|
|
14396
14717
|
return ret;
|
|
14397
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
|
+
*/
|
|
14398
14753
|
const getBrowseFieldData = function (_ref3) {
|
|
14399
14754
|
let {
|
|
14400
14755
|
metadataObj,
|
|
@@ -14440,12 +14795,22 @@ const getBrowseFieldData = function (_ref3) {
|
|
|
14440
14795
|
|
|
14441
14796
|
// Todo: Incorporate other methods into this class
|
|
14442
14797
|
class Metadata {
|
|
14798
|
+
/**
|
|
14799
|
+
* @param {{
|
|
14800
|
+
* metadataObj: MetadataObj
|
|
14801
|
+
* }} cfg
|
|
14802
|
+
*/
|
|
14443
14803
|
constructor(_ref4) {
|
|
14444
14804
|
let {
|
|
14445
14805
|
metadataObj
|
|
14446
14806
|
} = _ref4;
|
|
14447
14807
|
this.metadataObj = metadataObj;
|
|
14448
14808
|
}
|
|
14809
|
+
|
|
14810
|
+
/**
|
|
14811
|
+
* @param {string} field
|
|
14812
|
+
* @returns {string|undefined}
|
|
14813
|
+
*/
|
|
14449
14814
|
getFieldLang(field) {
|
|
14450
14815
|
const {
|
|
14451
14816
|
metadataObj
|
|
@@ -14453,6 +14818,19 @@ class Metadata {
|
|
|
14453
14818
|
const fields = metadataObj && metadataObj.fields;
|
|
14454
14819
|
return fields && fields[field] && fields[field].lang;
|
|
14455
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
|
+
*/
|
|
14456
14834
|
getFieldMatchesLocale(_ref5) {
|
|
14457
14835
|
let {
|
|
14458
14836
|
namespace,
|
|
@@ -14487,7 +14865,9 @@ class Metadata {
|
|
|
14487
14865
|
// If this is a localized field (e.g., enum), we don't want
|
|
14488
14866
|
// to avoid as may be translated (should check though)
|
|
14489
14867
|
const hasFieldValue = localeStrings && Object.keys(localeStrings).some(lng => {
|
|
14490
|
-
const fv = localeStrings[lng] &&
|
|
14868
|
+
const fv = localeStrings[lng] && (/** @type {import('../../server/main.js').LocalizationStrings} */
|
|
14869
|
+
/** @type {import('../../server/main.js').LocalizationStrings} */
|
|
14870
|
+
localeStrings[lng].fieldvalue);
|
|
14491
14871
|
return fv && fv[field];
|
|
14492
14872
|
});
|
|
14493
14873
|
return hasFieldValue || metaLang && preferredLanguages.includes(metaLang) || schemaItems.some(item => {
|
|
@@ -14497,11 +14877,18 @@ class Metadata {
|
|
|
14497
14877
|
}
|
|
14498
14878
|
}
|
|
14499
14879
|
|
|
14880
|
+
/**
|
|
14881
|
+
* @param {string} pluginName
|
|
14882
|
+
*/
|
|
14500
14883
|
const escapePluginComponent = pluginName => {
|
|
14501
14884
|
return pluginName.replaceAll('^', '^^').
|
|
14502
14885
|
// Escape our escape
|
|
14503
14886
|
replaceAll('-', '^0');
|
|
14504
14887
|
};
|
|
14888
|
+
|
|
14889
|
+
/**
|
|
14890
|
+
* @param {string|undefined} pluginName
|
|
14891
|
+
*/
|
|
14505
14892
|
const unescapePluginComponent = pluginName => {
|
|
14506
14893
|
if (!pluginName) {
|
|
14507
14894
|
return pluginName;
|
|
@@ -14510,6 +14897,14 @@ const unescapePluginComponent = pluginName => {
|
|
|
14510
14897
|
return esc.length % 2 ? esc.slice(1) + '-' : n0;
|
|
14511
14898
|
}).replaceAll('^^', '^');
|
|
14512
14899
|
};
|
|
14900
|
+
|
|
14901
|
+
/**
|
|
14902
|
+
* @param {{
|
|
14903
|
+
* pluginName: string,
|
|
14904
|
+
* applicableField: string,
|
|
14905
|
+
* targetLanguage: string
|
|
14906
|
+
* }} cfg
|
|
14907
|
+
*/
|
|
14513
14908
|
const escapePlugin = _ref => {
|
|
14514
14909
|
let {
|
|
14515
14910
|
pluginName,
|
|
@@ -14518,7 +14913,28 @@ const escapePlugin = _ref => {
|
|
|
14518
14913
|
} = _ref;
|
|
14519
14914
|
return escapePluginComponent(pluginName) + (applicableField ? '-' + escapePluginComponent(applicableField) : '-') + (targetLanguage ? '-' + escapePluginComponent(targetLanguage) : '');
|
|
14520
14915
|
};
|
|
14916
|
+
|
|
14917
|
+
/**
|
|
14918
|
+
* @todo Complete
|
|
14919
|
+
* @typedef {{}} PluginObject
|
|
14920
|
+
*/
|
|
14921
|
+
|
|
14521
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
|
+
*/
|
|
14522
14938
|
constructor(_ref2) {
|
|
14523
14939
|
let {
|
|
14524
14940
|
pluginsInWork,
|
|
@@ -14529,6 +14945,11 @@ class PluginsForWork {
|
|
|
14529
14945
|
this.pluginFieldMappings = pluginFieldMappings;
|
|
14530
14946
|
this.pluginObjects = pluginObjects;
|
|
14531
14947
|
}
|
|
14948
|
+
|
|
14949
|
+
/**
|
|
14950
|
+
* @param {string} pluginName
|
|
14951
|
+
* @returns {PluginObject}
|
|
14952
|
+
*/
|
|
14532
14953
|
getPluginObject(pluginName) {
|
|
14533
14954
|
const idx = this.pluginsInWork.findIndex(_ref3 => {
|
|
14534
14955
|
let [name] = _ref3;
|
|
@@ -14537,6 +14958,25 @@ class PluginsForWork {
|
|
|
14537
14958
|
const plugin = this.pluginObjects[idx];
|
|
14538
14959
|
return plugin;
|
|
14539
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
|
+
*/
|
|
14540
14980
|
iterateMappings(cb) {
|
|
14541
14981
|
this.pluginFieldMappings.forEach((_ref4, i) => {
|
|
14542
14982
|
let {
|
|
@@ -14566,6 +15006,25 @@ class PluginsForWork {
|
|
|
14566
15006
|
});
|
|
14567
15007
|
});
|
|
14568
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
|
+
*/
|
|
14569
15028
|
processTargetLanguages(applicableFields, cb) {
|
|
14570
15029
|
if (!applicableFields) {
|
|
14571
15030
|
return false;
|
|
@@ -14596,6 +15055,14 @@ class PluginsForWork {
|
|
|
14596
15055
|
});
|
|
14597
15056
|
return true;
|
|
14598
15057
|
}
|
|
15058
|
+
|
|
15059
|
+
/**
|
|
15060
|
+
* @param {{
|
|
15061
|
+
* namespace: string,
|
|
15062
|
+
* field: string
|
|
15063
|
+
* }} cfg
|
|
15064
|
+
* @returns {boolean}
|
|
15065
|
+
*/
|
|
14599
15066
|
isPluginField(_ref6) {
|
|
14600
15067
|
let {
|
|
14601
15068
|
namespace,
|
|
@@ -14603,6 +15070,14 @@ class PluginsForWork {
|
|
|
14603
15070
|
} = _ref6;
|
|
14604
15071
|
return field.startsWith(`${namespace}-plugin-`);
|
|
14605
15072
|
}
|
|
15073
|
+
|
|
15074
|
+
/**
|
|
15075
|
+
* @param {{
|
|
15076
|
+
* namespace: string,
|
|
15077
|
+
* field: string
|
|
15078
|
+
* }} cfg
|
|
15079
|
+
* @returns {[string, string|undefined, string|undefined]}
|
|
15080
|
+
*/
|
|
14606
15081
|
getPluginFieldParts(_ref7) {
|
|
14607
15082
|
let {
|
|
14608
15083
|
namespace,
|
|
@@ -14615,11 +15090,19 @@ class PluginsForWork {
|
|
|
14615
15090
|
} else {
|
|
14616
15091
|
pluginName = field;
|
|
14617
15092
|
}
|
|
14618
|
-
return [
|
|
15093
|
+
return /** @type {[string, string|undefined, string|undefined]} */(
|
|
15094
|
+
[pluginName, applicableField, targetLanguage].map(unescapePluginComponent)
|
|
15095
|
+
);
|
|
14619
15096
|
}
|
|
14620
15097
|
}
|
|
14621
15098
|
|
|
14622
15099
|
/* globals process -- Node polyglot */
|
|
15100
|
+
|
|
15101
|
+
/**
|
|
15102
|
+
* @param {FilesObject} filesObj
|
|
15103
|
+
* @param {FileGroup} fileGroup
|
|
15104
|
+
* @param {FileData} fileData
|
|
15105
|
+
*/
|
|
14623
15106
|
const getFilePaths = function getFilePaths(filesObj, fileGroup, fileData) {
|
|
14624
15107
|
const baseDir = (filesObj.baseDirectory || '') + (fileGroup.baseDirectory || '') + '/';
|
|
14625
15108
|
const schemaBaseDir = (filesObj.schemaBaseDirectory || '') + (fileGroup.schemaBaseDirectory || '') + '/';
|
|
@@ -14633,6 +15116,23 @@ const getFilePaths = function getFilePaths(filesObj, fileGroup, fileData) {
|
|
|
14633
15116
|
metadataFile
|
|
14634
15117
|
};
|
|
14635
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
|
+
*/
|
|
14636
15136
|
const getWorkData = async function (_ref) {
|
|
14637
15137
|
let {
|
|
14638
15138
|
lang,
|
|
@@ -14645,7 +15145,15 @@ const getWorkData = async function (_ref) {
|
|
|
14645
15145
|
preferredLocale
|
|
14646
15146
|
} = _ref;
|
|
14647
15147
|
const filesObj = await getJSON(files);
|
|
14648
|
-
const localizationStrings =
|
|
15148
|
+
const localizationStrings =
|
|
15149
|
+
/**
|
|
15150
|
+
* @type {{
|
|
15151
|
+
* "localization-strings": {
|
|
15152
|
+
* [key: string]: {}
|
|
15153
|
+
* }
|
|
15154
|
+
* }}
|
|
15155
|
+
*/
|
|
15156
|
+
filesObj?.['localization-strings'];
|
|
14649
15157
|
const workI18n = await i18n({
|
|
14650
15158
|
messageStyle: 'plainNested',
|
|
14651
15159
|
locales: lang,
|
|
@@ -14885,16 +15393,21 @@ const getWorkData = async function (_ref) {
|
|
|
14885
15393
|
// import {escapeHTML} from './sanitize.js';
|
|
14886
15394
|
|
|
14887
15395
|
/**
|
|
14888
|
-
*
|
|
14889
|
-
* @param {PlainObject} target
|
|
14890
|
-
* @param {PlainObject} source
|
|
14891
|
-
* @returns {{
|
|
15396
|
+
* @typedef {{
|
|
14892
15397
|
* userJSON: string,
|
|
14893
15398
|
* languages: string,
|
|
14894
15399
|
* serviceWorkerPath: string,
|
|
14895
15400
|
* files: string,
|
|
14896
|
-
* namespace: string
|
|
14897
|
-
*
|
|
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}
|
|
14898
15411
|
*/
|
|
14899
15412
|
const setServiceWorkerDefaults = (target, source) => {
|
|
14900
15413
|
target.userJSON = source.userJSON || 'resources/user.json';
|
|
@@ -14902,13 +15415,18 @@ const setServiceWorkerDefaults = (target, source) => {
|
|
|
14902
15415
|
target.serviceWorkerPath = source.serviceWorkerPath || `sw.js?pathToUserJSON=${encodeURIComponent(target.userJSON)}&stylesheets=${encodeURIComponent(JSON.stringify(target.stylesheets || []))}`;
|
|
14903
15416
|
target.files = source.files || 'files.json';
|
|
14904
15417
|
target.namespace = source.namespace || 'textbrowser';
|
|
14905
|
-
return target;
|
|
15418
|
+
return /** @type {ServiceWorkerConfig} */target;
|
|
14906
15419
|
};
|
|
14907
15420
|
|
|
14908
15421
|
// (Unless skipped in code, will wait between install
|
|
14909
15422
|
// of new and activation of new or existing if still
|
|
14910
15423
|
// some tabs open)
|
|
14911
15424
|
|
|
15425
|
+
/**
|
|
15426
|
+
* @param {{
|
|
15427
|
+
* r: ServiceWorkerRegistration
|
|
15428
|
+
* }} cfg
|
|
15429
|
+
*/
|
|
14912
15430
|
const listenForWorkerUpdate = _ref => {
|
|
14913
15431
|
let {
|
|
14914
15432
|
r
|
|
@@ -14919,7 +15437,7 @@ const listenForWorkerUpdate = _ref => {
|
|
|
14919
15437
|
// r.installing now available (though r.active is also,
|
|
14920
15438
|
// apparently due to prior activation; but not r.waiting)
|
|
14921
15439
|
console.log('update found', e);
|
|
14922
|
-
const newWorker = r.installing;
|
|
15440
|
+
const newWorker = /** @type {ServiceWorker} */r.installing;
|
|
14923
15441
|
|
|
14924
15442
|
// statechange won't catch this installing event as already installing
|
|
14925
15443
|
|
|
@@ -14975,6 +15493,19 @@ for offline installation.
|
|
|
14975
15493
|
});
|
|
14976
15494
|
});
|
|
14977
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
|
+
*/
|
|
14978
15509
|
const respondToState = async _ref2 => {
|
|
14979
15510
|
let {
|
|
14980
15511
|
r,
|
|
@@ -15045,20 +15576,20 @@ const respondToState = async _ref2 => {
|
|
|
15045
15576
|
text: message + `${errorType === 'dbError' ? `Database error ${name}` : ''}; trying again...`
|
|
15046
15577
|
});
|
|
15047
15578
|
/*
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15579
|
+
if (errorType === 'dbError') {
|
|
15580
|
+
logger.dbError({
|
|
15581
|
+
type: name || errorType,
|
|
15582
|
+
escapedErrorMessage: escapeHTML(message)
|
|
15583
|
+
});
|
|
15584
|
+
}
|
|
15585
|
+
*/
|
|
15055
15586
|
// Todo: auto-close any dbError dialog if retrying
|
|
15056
15587
|
// No longer rejecting as should auto-retry
|
|
15057
15588
|
/*
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15589
|
+
const err = new Error(message);
|
|
15590
|
+
err.type = type;
|
|
15591
|
+
reject(err);
|
|
15592
|
+
*/
|
|
15062
15593
|
break;
|
|
15063
15594
|
default:
|
|
15064
15595
|
console.error('Unexpected type', type);
|
|
@@ -15109,6 +15640,13 @@ any indication it is installing.
|
|
|
15109
15640
|
|
|
15110
15641
|
// Keep in this file as may wish to avoid using for server (while still
|
|
15111
15642
|
// doing other service worker work)
|
|
15643
|
+
|
|
15644
|
+
/**
|
|
15645
|
+
* @param {{
|
|
15646
|
+
* serviceWorkerPath: string,
|
|
15647
|
+
* logger: Logger
|
|
15648
|
+
* }} cfg
|
|
15649
|
+
*/
|
|
15112
15650
|
const registerServiceWorker = async _ref4 => {
|
|
15113
15651
|
let {
|
|
15114
15652
|
serviceWorkerPath,
|
|
@@ -15167,6 +15705,10 @@ Please refresh the page if you wish to reattempt.
|
|
|
15167
15705
|
});
|
|
15168
15706
|
};
|
|
15169
15707
|
|
|
15708
|
+
/**
|
|
15709
|
+
* Prevent XSS attacks.
|
|
15710
|
+
* @param {string} s - The string to sanitize
|
|
15711
|
+
*/
|
|
15170
15712
|
const escapeHTML = s => {
|
|
15171
15713
|
return !s ? '' : s.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');
|
|
15172
15714
|
};
|
|
@@ -16596,7 +17138,7 @@ const Templates = {
|
|
|
16596
17138
|
// We empty rather than `replaceWith` as our Jamilih `body`
|
|
16597
17139
|
// aliases expect the old instance
|
|
16598
17140
|
while (body.hasChildNodes()) {
|
|
16599
|
-
body.firstChild
|
|
17141
|
+
body.firstChild?.remove();
|
|
16600
17142
|
}
|
|
16601
17143
|
return jml('div', {
|
|
16602
17144
|
id: 'main',
|
|
@@ -16605,21 +17147,27 @@ const Templates = {
|
|
|
16605
17147
|
},
|
|
16606
17148
|
permissions: {
|
|
16607
17149
|
versionChange() {
|
|
16608
|
-
|
|
17150
|
+
/** @type {HTMLDialogElement} */
|
|
17151
|
+
$$1('#versionChange')?.showModal();
|
|
16609
17152
|
},
|
|
17153
|
+
/**
|
|
17154
|
+
* @param {{text: string}} cfg
|
|
17155
|
+
*/
|
|
16610
17156
|
addLogEntry(_ref) {
|
|
16611
17157
|
let {
|
|
16612
17158
|
text
|
|
16613
17159
|
} = _ref;
|
|
16614
17160
|
const installationDialog = $$1('#installationLogContainer');
|
|
16615
17161
|
try {
|
|
17162
|
+
/** @type {HTMLDialogElement} */
|
|
16616
17163
|
installationDialog.showModal();
|
|
16617
|
-
const container =
|
|
17164
|
+
const container = /** @type {HTMLElement} */$$1('#dialogContainer');
|
|
16618
17165
|
container.hidden = false;
|
|
16619
17166
|
// eslint-disable-next-line no-unused-vars -- Ok
|
|
16620
17167
|
} catch (err) {
|
|
16621
17168
|
// May already be open
|
|
16622
17169
|
}
|
|
17170
|
+
/** @type {HTMLElement} */
|
|
16623
17171
|
$$1('#installationLog').append(text + '\n');
|
|
16624
17172
|
},
|
|
16625
17173
|
exitDialogs() {
|
|
@@ -16628,6 +17176,12 @@ const Templates = {
|
|
|
16628
17176
|
container.hidden = true;
|
|
16629
17177
|
}
|
|
16630
17178
|
},
|
|
17179
|
+
/**
|
|
17180
|
+
* @param {{
|
|
17181
|
+
* type: string,
|
|
17182
|
+
* escapedErrorMessage: string
|
|
17183
|
+
* }} cfg
|
|
17184
|
+
*/
|
|
16631
17185
|
dbError(_ref2) {
|
|
16632
17186
|
let {
|
|
16633
17187
|
type,
|
|
@@ -16636,26 +17190,32 @@ const Templates = {
|
|
|
16636
17190
|
if (type) {
|
|
16637
17191
|
jml('span', [type, ' ', escapedErrorMessage], $$1('#dbError'));
|
|
16638
17192
|
}
|
|
17193
|
+
/** @type {HTMLDialogElement} */
|
|
16639
17194
|
$$1('#dbError').showModal();
|
|
16640
17195
|
},
|
|
17196
|
+
/**
|
|
17197
|
+
* @param {string} escapedErrorMessage
|
|
17198
|
+
*/
|
|
16641
17199
|
errorRegistering(escapedErrorMessage) {
|
|
16642
17200
|
if (escapedErrorMessage) {
|
|
16643
17201
|
jml('span', [escapedErrorMessage], $$1('#errorRegistering'));
|
|
16644
17202
|
}
|
|
17203
|
+
/** @type {HTMLDialogElement} */
|
|
16645
17204
|
$$1('#errorRegistering').showModal();
|
|
16646
17205
|
},
|
|
16647
17206
|
browserNotGrantingPersistence() {
|
|
17207
|
+
/** @type {HTMLDialogElement} */
|
|
16648
17208
|
$$1('#browserNotGrantingPersistence').showModal();
|
|
16649
17209
|
},
|
|
16650
17210
|
/**
|
|
16651
|
-
* @param {
|
|
16652
|
-
* @param {I18NCallback} cfg.siteI18n
|
|
16653
|
-
* @param {() => Promise<void>} cfg.ok
|
|
16654
|
-
* @param {() => void} cfg.refuse
|
|
16655
|
-
* @param {() => Promise<void>} cfg.close
|
|
16656
|
-
* @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]
|
|
16657
17217
|
* @returns {[
|
|
16658
|
-
* HTMLDialogElement, HTMLDialogElement, HTMLDialogElement,
|
|
17218
|
+
* HTMLDialogElement, HTMLDialogElement|"", HTMLDialogElement|"",
|
|
16659
17219
|
* HTMLDialogElement, HTMLDialogElement, HTMLDialogElement
|
|
16660
17220
|
* ]}
|
|
16661
17221
|
*/
|
|
@@ -16678,8 +17238,10 @@ const Templates = {
|
|
|
16678
17238
|
}, []]]]
|
|
16679
17239
|
// ['textarea', {readonly: true, style: 'width: 80%; height: 80%;'}]
|
|
16680
17240
|
]);
|
|
17241
|
+
|
|
17242
|
+
/** @type {""|HTMLDialogElement} */
|
|
16681
17243
|
let requestPermissionsDialog = '';
|
|
16682
|
-
if (ok) {
|
|
17244
|
+
if (ok && refuse && close) {
|
|
16683
17245
|
requestPermissionsDialog = jml('dialog', {
|
|
16684
17246
|
id: 'willRequestStoragePermissions',
|
|
16685
17247
|
$on: {
|
|
@@ -16700,6 +17262,8 @@ const Templates = {
|
|
|
16700
17262
|
const errorRegisteringNotice = jml('dialog', {
|
|
16701
17263
|
id: 'errorRegistering'
|
|
16702
17264
|
}, [['section', [siteI18n('errorRegistering')]]]);
|
|
17265
|
+
|
|
17266
|
+
/** @type {""|HTMLDialogElement} */
|
|
16703
17267
|
let browserNotGrantingPersistenceAlert = '';
|
|
16704
17268
|
if (closeBrowserNotGranting) {
|
|
16705
17269
|
browserNotGrantingPersistenceAlert = jml('dialog', {
|
|
@@ -16731,10 +17295,10 @@ const Templates = {
|
|
|
16731
17295
|
* @file Note that this should be kept as a polyglot client-server file.
|
|
16732
17296
|
*/
|
|
16733
17297
|
/**
|
|
16734
|
-
*
|
|
16735
|
-
* @param {string} param
|
|
16736
|
-
* @param {boolean} skip
|
|
16737
17298
|
* @this {IntlURLSearchParams}
|
|
17299
|
+
* @param {string} param
|
|
17300
|
+
* @param {boolean} [skip]
|
|
17301
|
+
* @throws {Error}
|
|
16738
17302
|
* @returns {string}
|
|
16739
17303
|
*/
|
|
16740
17304
|
function _prepareParam(param, skip) {
|
|
@@ -16746,42 +17310,84 @@ function _prepareParam(param, skip) {
|
|
|
16746
17310
|
// start, end, toggle
|
|
16747
17311
|
const endNums = /\d+(-\d+)?$/;
|
|
16748
17312
|
const indexed = param.match(endNums);
|
|
17313
|
+
if (!this.l10n) {
|
|
17314
|
+
throw new Error('l10n is not defined');
|
|
17315
|
+
}
|
|
16749
17316
|
if (indexed) {
|
|
16750
17317
|
// Todo: We could i18nize numbers as well
|
|
16751
17318
|
return this.l10n(['params', 'indexed', param.replace(endNums, '')]) + indexed[0];
|
|
16752
17319
|
}
|
|
16753
|
-
return this.l10n(['params', param]);
|
|
17320
|
+
return /** @type {string} */this.l10n(['params', param]);
|
|
16754
17321
|
}
|
|
16755
17322
|
class IntlURLSearchParams {
|
|
17323
|
+
/**
|
|
17324
|
+
* @param {object} [options]
|
|
17325
|
+
* @param {import('intl-dom').I18NCallback} [options.l10n]
|
|
17326
|
+
* @param {URLSearchParams|string} [options.params]
|
|
17327
|
+
*/
|
|
16756
17328
|
constructor() {
|
|
16757
17329
|
let {
|
|
16758
17330
|
l10n,
|
|
16759
17331
|
params
|
|
16760
17332
|
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
16761
17333
|
this.l10n = l10n;
|
|
17334
|
+
this.localizeParamNames = false;
|
|
16762
17335
|
if (!params) {
|
|
16763
17336
|
params = location.hash.slice(1);
|
|
16764
17337
|
}
|
|
16765
17338
|
if (typeof params === 'string') {
|
|
16766
17339
|
params = new URLSearchParams(params);
|
|
16767
17340
|
}
|
|
17341
|
+
/** @type {URLSearchParams} */
|
|
16768
17342
|
this.params = params;
|
|
16769
17343
|
}
|
|
17344
|
+
/**
|
|
17345
|
+
* @param {string} param
|
|
17346
|
+
* @param {boolean} [skip]
|
|
17347
|
+
* @returns {string|null}
|
|
17348
|
+
*/
|
|
16770
17349
|
get(param, skip) {
|
|
16771
17350
|
return this.params.get(_prepareParam.call(this, param, skip));
|
|
16772
17351
|
}
|
|
17352
|
+
/**
|
|
17353
|
+
* @param {string} param
|
|
17354
|
+
* @param {boolean} skip
|
|
17355
|
+
* @returns {string[]}
|
|
17356
|
+
*/
|
|
16773
17357
|
getAll(param, skip) {
|
|
16774
17358
|
return this.params.getAll(_prepareParam.call(this, param, skip));
|
|
16775
17359
|
}
|
|
17360
|
+
/**
|
|
17361
|
+
* @param {string} param
|
|
17362
|
+
* @param {boolean} skip
|
|
17363
|
+
* @returns {boolean}
|
|
17364
|
+
*/
|
|
16776
17365
|
has(param, skip) {
|
|
16777
17366
|
return this.params.has(_prepareParam.call(this, param, skip));
|
|
16778
17367
|
}
|
|
17368
|
+
/**
|
|
17369
|
+
* @param {string} param
|
|
17370
|
+
* @param {boolean} skip
|
|
17371
|
+
* @returns {void}
|
|
17372
|
+
*/
|
|
16779
17373
|
delete(param, skip) {
|
|
16780
17374
|
return this.params.delete(_prepareParam.call(this, param, skip));
|
|
16781
17375
|
}
|
|
17376
|
+
/**
|
|
17377
|
+
* @param {string} param
|
|
17378
|
+
* @param {string} value
|
|
17379
|
+
* @param {boolean} skip
|
|
17380
|
+
* @returns {void}
|
|
17381
|
+
*/
|
|
16782
17382
|
set(param, value, skip) {
|
|
16783
17383
|
return this.params.set(_prepareParam.call(this, param, skip), value);
|
|
16784
17384
|
}
|
|
17385
|
+
/**
|
|
17386
|
+
* @param {string} param
|
|
17387
|
+
* @param {string} value
|
|
17388
|
+
* @param {boolean} skip
|
|
17389
|
+
* @returns {void}
|
|
17390
|
+
*/
|
|
16785
17391
|
append(param, value, skip) {
|
|
16786
17392
|
return this.params.append(_prepareParam.call(this, param, skip), value);
|
|
16787
17393
|
}
|
|
@@ -16790,6 +17396,15 @@ class IntlURLSearchParams {
|
|
|
16790
17396
|
}
|
|
16791
17397
|
}
|
|
16792
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
|
+
*/
|
|
16793
17408
|
async function workSelect(_ref) {
|
|
16794
17409
|
let {
|
|
16795
17410
|
files,
|
|
@@ -16830,7 +17445,7 @@ async function workSelect(_ref) {
|
|
|
16830
17445
|
};
|
|
16831
17446
|
}
|
|
16832
17447
|
});
|
|
16833
|
-
document.title = workI18n('browserfile-workselect');
|
|
17448
|
+
document.title = /** @type {string} */workI18n('browserfile-workselect');
|
|
16834
17449
|
/*
|
|
16835
17450
|
// Would need adapting now that not using IMF
|
|
16836
17451
|
function lDirectional (key, substitutions, formats) {
|
|
@@ -16866,22 +17481,63 @@ async function workSelect(_ref) {
|
|
|
16866
17481
|
}
|
|
16867
17482
|
|
|
16868
17483
|
// Todo: Reimplement this with `formSerialize.deserialize` as possible
|
|
17484
|
+
|
|
17485
|
+
|
|
17486
|
+
/**
|
|
17487
|
+
* @param {URLSearchParams} paramsCopy
|
|
17488
|
+
*/
|
|
16869
17489
|
const replaceHash = paramsCopy => {
|
|
16870
17490
|
return location.href.replace(/#.*$/, '') + '#' + paramsCopy.toString();
|
|
16871
17491
|
};
|
|
16872
|
-
|
|
16873
|
-
|
|
16874
|
-
|
|
16875
|
-
|
|
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);
|
|
16876
17514
|
return replaceHash(paramsCopy);
|
|
16877
17515
|
};
|
|
16878
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
|
+
*/
|
|
16879
17525
|
const getParamsSetter = function (_ref) {
|
|
16880
17526
|
let {
|
|
16881
17527
|
l,
|
|
16882
17528
|
lParam,
|
|
16883
17529
|
$p
|
|
16884
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
|
+
*/
|
|
16885
17541
|
return function (_ref2) {
|
|
16886
17542
|
let {
|
|
16887
17543
|
form,
|
|
@@ -16904,7 +17560,8 @@ const getParamsSetter = function (_ref) {
|
|
|
16904
17560
|
|
|
16905
17561
|
// Follow the same style (and order) for checkboxes
|
|
16906
17562
|
paramsCopy.delete(lParam('rand'));
|
|
16907
|
-
paramsCopy.set(lParam('rand'),
|
|
17563
|
+
paramsCopy.set(lParam('rand'), /** @type {string} */
|
|
17564
|
+
random.checked ? l('yes') : l('no'));
|
|
16908
17565
|
|
|
16909
17566
|
// We want checkboxes to typically show by default, so we cannot use the
|
|
16910
17567
|
// standard serialization
|
|
@@ -16913,7 +17570,8 @@ const getParamsSetter = function (_ref) {
|
|
|
16913
17570
|
paramsCopy.delete(checkbox.name);
|
|
16914
17571
|
if (checkbox.name) {
|
|
16915
17572
|
// We don't want, e.g., preference controls added to URL
|
|
16916
|
-
paramsCopy.set(checkbox.name,
|
|
17573
|
+
paramsCopy.set(checkbox.name, /** @type {string} */
|
|
17574
|
+
checkbox.checked ? l('yes') : l('no'));
|
|
16917
17575
|
}
|
|
16918
17576
|
});
|
|
16919
17577
|
|
|
@@ -16924,11 +17582,11 @@ const getParamsSetter = function (_ref) {
|
|
|
16924
17582
|
function removeStartsEndsAndAnchors() {
|
|
16925
17583
|
let num = 1;
|
|
16926
17584
|
let num2 = 1;
|
|
16927
|
-
while (paramsCopy.has(`${workName}-start${num}-${num2}
|
|
16928
|
-
while (paramsCopy.has(`${workName}-start${num}-${num2}
|
|
16929
|
-
paramsCopy.delete(`${workName}-start${num}-${num2}
|
|
16930
|
-
paramsCopy.delete(`${workName}-end${num}-${num2}
|
|
16931
|
-
paramsCopy.delete(`${workName}-anchor${num}-${num2}
|
|
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}`);
|
|
16932
17590
|
num2++;
|
|
16933
17591
|
}
|
|
16934
17592
|
num2 = 1;
|
|
@@ -16947,28 +17605,28 @@ const getParamsSetter = function (_ref) {
|
|
|
16947
17605
|
{
|
|
16948
17606
|
paramsCopy.delete(lParam('rand'));
|
|
16949
17607
|
let num = 1;
|
|
16950
|
-
while (paramsCopy.has(`anchorfield${num}
|
|
16951
|
-
paramsCopy.delete(`anchorfield${num}
|
|
17608
|
+
while (paramsCopy.has(`anchorfield${num}`)) {
|
|
17609
|
+
paramsCopy.delete(`anchorfield${num}`);
|
|
16952
17610
|
num++;
|
|
16953
17611
|
}
|
|
16954
17612
|
removeStartsEndsAndAnchors();
|
|
16955
17613
|
num = 1;
|
|
16956
17614
|
// Delete field-specific so we can add our own
|
|
16957
|
-
while (paramsCopy.has(`field${num}
|
|
16958
|
-
paramsCopy.delete(`field${num}
|
|
16959
|
-
paramsCopy.delete(`checked${num}
|
|
16960
|
-
paramsCopy.delete(`interlin${num}
|
|
16961
|
-
paramsCopy.delete(`css${num}
|
|
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}`);
|
|
16962
17620
|
num++;
|
|
16963
17621
|
}
|
|
16964
17622
|
fieldAliasOrNames.forEach((fieldAliasOrName, i) => {
|
|
16965
|
-
paramsCopy.set(`field${i + 1}`, fieldAliasOrName
|
|
17623
|
+
paramsCopy.set(`field${i + 1}`, fieldAliasOrName);
|
|
16966
17624
|
// Todo: Restrict by content locale?
|
|
16967
|
-
paramsCopy.set(`checked${i + 1}`, l('yes')
|
|
17625
|
+
paramsCopy.set(`checked${i + 1}`, /** @type {string} */l('yes'));
|
|
16968
17626
|
paramsCopy.set(`interlin${i + 1}`, '');
|
|
16969
17627
|
paramsCopy.set(`css${i + 1}`, '');
|
|
16970
17628
|
});
|
|
16971
|
-
paramsCopy.delete('work'
|
|
17629
|
+
paramsCopy.delete('work');
|
|
16972
17630
|
}
|
|
16973
17631
|
// Fallthrough
|
|
16974
17632
|
case 'startEndResult':
|
|
@@ -16982,9 +17640,9 @@ const getParamsSetter = function (_ref) {
|
|
|
16982
17640
|
// let's put random again toward the end.
|
|
16983
17641
|
if (type === 'randomResult' || random.checked) {
|
|
16984
17642
|
paramsCopy.delete(lParam('rand'));
|
|
16985
|
-
paramsCopy.set(lParam('rand'), l('yes'));
|
|
17643
|
+
paramsCopy.set(lParam('rand'), /** @type {string} */l('yes'));
|
|
16986
17644
|
}
|
|
16987
|
-
paramsCopy.set(lParam('result'), l('yes'));
|
|
17645
|
+
paramsCopy.set(lParam('result'), /** @type {string} */l('yes'));
|
|
16988
17646
|
break;
|
|
16989
17647
|
}
|
|
16990
17648
|
default:
|
|
@@ -16996,6 +17654,18 @@ const getParamsSetter = function (_ref) {
|
|
|
16996
17654
|
};
|
|
16997
17655
|
};
|
|
16998
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
|
+
*/
|
|
16999
17669
|
async function workDisplay(_ref) {
|
|
17000
17670
|
let {
|
|
17001
17671
|
l,
|
|
@@ -17187,7 +17857,7 @@ async function workDisplay(_ref) {
|
|
|
17187
17857
|
fallbackLanguages,
|
|
17188
17858
|
preferredLocale,
|
|
17189
17859
|
languages,
|
|
17190
|
-
work:
|
|
17860
|
+
work: (/** @type {string} */$p.get('work'))
|
|
17191
17861
|
});
|
|
17192
17862
|
document.title = workI18n('browserfile-workdisplay', {
|
|
17193
17863
|
work: fileData ? getMetaProp(lang, metadataObj, 'alias') : ''
|
|
@@ -17634,6 +18304,9 @@ Locale._BIDI_RTL_LANGS = [
|
|
|
17634
18304
|
'zdj' // Comorian, Ngazidja
|
|
17635
18305
|
];
|
|
17636
18306
|
|
|
18307
|
+
/**
|
|
18308
|
+
* @param {string} locale
|
|
18309
|
+
*/
|
|
17637
18310
|
const getLangDir = locale => {
|
|
17638
18311
|
const {
|
|
17639
18312
|
direction
|
|
@@ -17847,7 +18520,7 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
|
|
|
17847
18520
|
tr,
|
|
17848
18521
|
foundState
|
|
17849
18522
|
} = _ref9;
|
|
17850
|
-
const rowIDPartsPreferred = [];
|
|
18523
|
+
const rowIDPartsPreferred = /** @type {string[]} */[];
|
|
17851
18524
|
const rowIDParts = applicableBrowseFieldNames.map(fieldName => {
|
|
17852
18525
|
const idx = localizedFieldNames.indexOf(fieldName);
|
|
17853
18526
|
// This works to put alias in anchor but this includes
|
|
@@ -18082,7 +18755,7 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
|
|
|
18082
18755
|
const p = $p.get(param, true);
|
|
18083
18756
|
/**
|
|
18084
18757
|
*
|
|
18085
|
-
* @param {GenericArray|
|
|
18758
|
+
* @param {GenericArray|object} locale
|
|
18086
18759
|
* @returns {boolean}
|
|
18087
18760
|
*/
|
|
18088
18761
|
function reverseLocaleLookup(locale) {
|
|
@@ -18602,7 +19275,16 @@ const resultsDisplayServerOrClient = async function resultsDisplayServerOrClient
|
|
|
18602
19275
|
};
|
|
18603
19276
|
|
|
18604
19277
|
/**
|
|
18605
|
-
*
|
|
19278
|
+
* @typedef {{
|
|
19279
|
+
* 'localization-strings': {
|
|
19280
|
+
* [locale: string]: {
|
|
19281
|
+
* [key: string]: string
|
|
19282
|
+
* }
|
|
19283
|
+
* }
|
|
19284
|
+
* }} SiteData
|
|
19285
|
+
*/
|
|
19286
|
+
/**
|
|
19287
|
+
* @this {TextBrowser}
|
|
18606
19288
|
* @returns {Promise<void>}
|
|
18607
19289
|
*/
|
|
18608
19290
|
async function prepareForServiceWorker() {
|
|
@@ -18629,32 +19311,29 @@ async function prepareForServiceWorker() {
|
|
|
18629
19311
|
} catch (err) {
|
|
18630
19312
|
console.log('err', err);
|
|
18631
19313
|
if (err && typeof err === 'object') {
|
|
18632
|
-
|
|
18633
|
-
errorType
|
|
18634
|
-
} = err;
|
|
18635
|
-
if (errorType === 'versionChange') {
|
|
19314
|
+
if ('errorType' in err && err.errorType === 'versionChange') {
|
|
18636
19315
|
Templates.permissions.versionChange();
|
|
18637
19316
|
return;
|
|
18638
19317
|
}
|
|
18639
19318
|
}
|
|
18640
|
-
Templates.permissions.errorRegistering(escapeHTML(
|
|
19319
|
+
Templates.permissions.errorRegistering(escapeHTML(/** @type {Error} */err?.message));
|
|
18641
19320
|
}
|
|
18642
19321
|
}
|
|
18643
19322
|
|
|
18644
19323
|
/**
|
|
18645
|
-
* @typedef {
|
|
19324
|
+
* @typedef {object} Langs
|
|
18646
19325
|
* @property {string} code
|
|
18647
19326
|
* @property {string} direction
|
|
18648
|
-
* @property {
|
|
19327
|
+
* @property {object} locale
|
|
18649
19328
|
*/
|
|
18650
19329
|
|
|
18651
19330
|
/**
|
|
18652
|
-
*
|
|
18653
|
-
* @param {
|
|
18654
|
-
* @param {
|
|
19331
|
+
* @this {TextBrowser}
|
|
19332
|
+
* @param {import('../server/main.js').LanguageInfo[]} _langs
|
|
19333
|
+
* @param {import('intl-dom').I18NCallback} siteI18n
|
|
18655
19334
|
* @returns {Promise<void>}
|
|
18656
19335
|
*/
|
|
18657
|
-
async function requestPermissions(
|
|
19336
|
+
async function requestPermissions(_langs, siteI18n) {
|
|
18658
19337
|
return await new Promise(resolve => {
|
|
18659
19338
|
// Todo: We could run the dialog code below for every page if
|
|
18660
19339
|
// `Notification.permission === 'default'` (i.e., not choice
|
|
@@ -18678,18 +19357,19 @@ async function requestPermissions(langs, l) {
|
|
|
18678
19357
|
*
|
|
18679
19358
|
* @returns {void}
|
|
18680
19359
|
*/
|
|
18681
|
-
|
|
19360
|
+
const rememberRefusal = () => {
|
|
18682
19361
|
// Todo: We could go forward with worker, caching files, and
|
|
18683
19362
|
// indexedDB regardless of permissions, but this way
|
|
18684
19363
|
// we can continue to gauge performance differences for now
|
|
18685
19364
|
localStorage.setItem(this.namespace + '-refused', 'true');
|
|
18686
|
-
}
|
|
19365
|
+
};
|
|
18687
19366
|
try {
|
|
18688
19367
|
if (!requestPermissionsDialog.returnValue) {
|
|
18689
19368
|
rememberRefusal();
|
|
18690
19369
|
return;
|
|
18691
19370
|
}
|
|
18692
|
-
} catch (
|
|
19371
|
+
} catch (error) {
|
|
19372
|
+
const err = /** @type {Error} */error;
|
|
18693
19373
|
console.log('err', err);
|
|
18694
19374
|
Templates.permissions.errorRegistering(escapeHTML(err && err.message));
|
|
18695
19375
|
}
|
|
@@ -18720,19 +19400,48 @@ async function requestPermissions(langs, l) {
|
|
|
18720
19400
|
break;
|
|
18721
19401
|
}
|
|
18722
19402
|
};
|
|
18723
|
-
const
|
|
19403
|
+
const permissionsInfo =
|
|
18724
19404
|
// , errorRegisteringNotice
|
|
18725
19405
|
Templates.permissions.main({
|
|
18726
|
-
|
|
19406
|
+
siteI18n,
|
|
18727
19407
|
ok,
|
|
18728
19408
|
refuse,
|
|
18729
19409
|
close,
|
|
18730
19410
|
closeBrowserNotGranting
|
|
18731
19411
|
});
|
|
19412
|
+
const requestPermissionsDialog = /** @type {HTMLDialogElement} */permissionsInfo[1];
|
|
19413
|
+
const browserNotGrantingPersistenceAlert = /** @type {HTMLDialogElement} */
|
|
19414
|
+
permissionsInfo[2];
|
|
18732
19415
|
requestPermissionsDialog.showModal();
|
|
18733
19416
|
});
|
|
18734
19417
|
}
|
|
19418
|
+
|
|
19419
|
+
/**
|
|
19420
|
+
* @typedef {import('./utils/ServiceWorker.js').ServiceWorkerConfig} ServiceWorkerConfig
|
|
19421
|
+
*/
|
|
19422
|
+
|
|
19423
|
+
/**
|
|
19424
|
+
* @implements {ServiceWorkerConfig}
|
|
19425
|
+
*/
|
|
18735
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
|
+
*/
|
|
18736
19445
|
constructor(options) {
|
|
18737
19446
|
this.site = options.site || 'site.json';
|
|
18738
19447
|
const stylesheets = options.stylesheets || ['@builtin'];
|
|
@@ -18741,6 +19450,25 @@ class TextBrowser {
|
|
|
18741
19450
|
stylesheets.splice(builtinIndex, 1, new URL(new URL('assets/index-D_XVedS3.css', import.meta.url).href, import.meta.url).href);
|
|
18742
19451
|
}
|
|
18743
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 = '';
|
|
18744
19472
|
setServiceWorkerDefaults(this, options);
|
|
18745
19473
|
this.allowPlugins = options.allowPlugins;
|
|
18746
19474
|
this.dynamicBasePath = options.dynamicBasePath;
|
|
@@ -18761,9 +19489,16 @@ class TextBrowser {
|
|
|
18761
19489
|
|
|
18762
19490
|
// We use getJSON instead of JsonRefs as we do not need to resolve the locales here
|
|
18763
19491
|
try {
|
|
18764
|
-
const
|
|
18765
|
-
|
|
18766
|
-
|
|
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];
|
|
18767
19502
|
const p = this.paramChange();
|
|
18768
19503
|
|
|
18769
19504
|
// INIT/ADD EVENTS
|
|
@@ -18771,11 +19506,16 @@ class TextBrowser {
|
|
|
18771
19506
|
// and just check `history.state`
|
|
18772
19507
|
window.addEventListener('hashchange', () => this.paramChange());
|
|
18773
19508
|
return p;
|
|
18774
|
-
} catch (
|
|
19509
|
+
} catch (error) {
|
|
19510
|
+
const err = /** @type {Error} */error;
|
|
18775
19511
|
console.log('err', err);
|
|
18776
19512
|
dialogs.alert(err);
|
|
18777
19513
|
}
|
|
18778
19514
|
}
|
|
19515
|
+
|
|
19516
|
+
/**
|
|
19517
|
+
* @param {import('./utils/WorkInfo.js').GetWorkDataOptions} opts
|
|
19518
|
+
*/
|
|
18779
19519
|
getWorkData(opts) {
|
|
18780
19520
|
try {
|
|
18781
19521
|
return getWorkData.call(this, {
|
|
@@ -18792,6 +19532,10 @@ class TextBrowser {
|
|
|
18792
19532
|
// Need for directionality even if language specified (and we don't want
|
|
18793
19533
|
// to require it as a param)
|
|
18794
19534
|
// Todo: Use intl-locale-textinfo-polyfill (already included)
|
|
19535
|
+
|
|
19536
|
+
/**
|
|
19537
|
+
* @param {string} code
|
|
19538
|
+
*/
|
|
18795
19539
|
getDirectionForLanguageCode(code) {
|
|
18796
19540
|
const langs = this.langData.languages;
|
|
18797
19541
|
const exactMatch = langs.find(lang => {
|
|
@@ -18801,12 +19545,21 @@ class TextBrowser {
|
|
|
18801
19545
|
return lang.code.startsWith(code + '-');
|
|
18802
19546
|
});
|
|
18803
19547
|
}
|
|
19548
|
+
|
|
19549
|
+
/**
|
|
19550
|
+
* @param {import('./utils/Metadata.js').GetFieldNameAndValueAliasesOptions} args
|
|
19551
|
+
*/
|
|
18804
19552
|
getFieldNameAndValueAliases(args) {
|
|
18805
19553
|
return getFieldNameAndValueAliases({
|
|
18806
19554
|
...args,
|
|
18807
19555
|
lang: this.lang
|
|
18808
19556
|
});
|
|
18809
19557
|
}
|
|
19558
|
+
|
|
19559
|
+
/**
|
|
19560
|
+
* @param {import('./utils/Metadata.js').GetBrowseFieldDataOptions} args
|
|
19561
|
+
* @returns {void}
|
|
19562
|
+
*/
|
|
18810
19563
|
getBrowseFieldData(args) {
|
|
18811
19564
|
return getBrowseFieldData({
|
|
18812
19565
|
...args,
|
|
@@ -18821,6 +19574,10 @@ class TextBrowser {
|
|
|
18821
19574
|
params: history.state
|
|
18822
19575
|
}) : new IntlURLSearchParams(); // Uses URL hash for params
|
|
18823
19576
|
|
|
19577
|
+
/**
|
|
19578
|
+
* @param {string} formSelector
|
|
19579
|
+
* @param {() => void} cb
|
|
19580
|
+
*/
|
|
18824
19581
|
const followParams = (formSelector, cb) => {
|
|
18825
19582
|
const form = document.querySelector(formSelector);
|
|
18826
19583
|
// Record current URL along with state
|
|
@@ -18848,25 +19605,26 @@ class TextBrowser {
|
|
|
18848
19605
|
const [preferredLocale] = lang;
|
|
18849
19606
|
const direction = this.getDirectionForLanguageCode(preferredLocale);
|
|
18850
19607
|
document.documentElement.lang = preferredLocale;
|
|
18851
|
-
document.dir = direction;
|
|
19608
|
+
document.dir = /** @type {string} */direction;
|
|
18852
19609
|
const localizationStrings = this.siteData['localization-strings'];
|
|
18853
19610
|
const siteI18n = await i18n({
|
|
18854
19611
|
messageStyle: 'plainNested',
|
|
18855
19612
|
locales: lang,
|
|
18856
19613
|
defaultLocales: fallbackLanguages,
|
|
18857
|
-
localeStringFinder(
|
|
19614
|
+
async localeStringFinder() {
|
|
18858
19615
|
let {
|
|
18859
19616
|
locales,
|
|
18860
19617
|
defaultLocales
|
|
18861
|
-
} =
|
|
18862
|
-
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 => {
|
|
18863
19620
|
return language in localizationStrings;
|
|
18864
19621
|
});
|
|
18865
19622
|
return {
|
|
18866
|
-
|
|
19623
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
19624
|
+
locale: (/** @type {string} */locale),
|
|
18867
19625
|
strings: {
|
|
18868
19626
|
head: {},
|
|
18869
|
-
body: localizationStrings[locale]
|
|
19627
|
+
body: localizationStrings[(/** @type {string} */locale)]
|
|
18870
19628
|
}
|
|
18871
19629
|
};
|
|
18872
19630
|
}
|
|
@@ -18874,7 +19632,7 @@ class TextBrowser {
|
|
|
18874
19632
|
|
|
18875
19633
|
// Even if individual pages may end up changing, we need a
|
|
18876
19634
|
// title now for accessibility
|
|
18877
|
-
document.title = siteI18n('browser-title');
|
|
19635
|
+
document.title = /** @type {string} */siteI18n('browser-title');
|
|
18878
19636
|
const refusedIndexedDB =
|
|
18879
19637
|
// User may have persistence via bookmarks, etc. but just not
|
|
18880
19638
|
// want commital on notification
|
|
@@ -18971,8 +19729,8 @@ class TextBrowser {
|
|
|
18971
19729
|
try {
|
|
18972
19730
|
return respondToState({
|
|
18973
19731
|
r,
|
|
18974
|
-
langs,
|
|
18975
|
-
languages: this.languages,
|
|
19732
|
+
// langs,
|
|
19733
|
+
// languages: this.languages,
|
|
18976
19734
|
logger: Templates.permissions
|
|
18977
19735
|
});
|
|
18978
19736
|
} catch (err) {
|
|
@@ -19001,13 +19759,13 @@ class TextBrowser {
|
|
|
19001
19759
|
// We don't await the fulfillment of this promise
|
|
19002
19760
|
respondToStateOfWorker();
|
|
19003
19761
|
listenForWorkerUpdate({
|
|
19004
|
-
r
|
|
19005
|
-
logger: {
|
|
19006
|
-
|
|
19007
|
-
|
|
19008
|
-
|
|
19009
|
-
|
|
19010
|
-
}
|
|
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
|
+
// }
|
|
19011
19769
|
});
|
|
19012
19770
|
// Don't return as user may continue working until installed (though
|
|
19013
19771
|
// will get message to close tab)
|
|
@@ -19032,6 +19790,12 @@ class TextBrowser {
|
|
|
19032
19790
|
Please wait for a short while as we work to update to a new version.
|
|
19033
19791
|
`);
|
|
19034
19792
|
respondToStateOfWorker();
|
|
19793
|
+
/**
|
|
19794
|
+
* @type {(
|
|
19795
|
+
* this: ServiceWorkerContainer,
|
|
19796
|
+
* ev: {data: string}
|
|
19797
|
+
* ) => any}
|
|
19798
|
+
*/
|
|
19035
19799
|
navigator.serviceWorker.onmessage({
|
|
19036
19800
|
data: 'finishActivate'
|
|
19037
19801
|
});
|
|
@@ -19046,13 +19810,13 @@ class TextBrowser {
|
|
|
19046
19810
|
// May need to pass in arguments if new service worker appears and
|
|
19047
19811
|
// it needs arguments for update
|
|
19048
19812
|
listenForWorkerUpdate({
|
|
19049
|
-
r
|
|
19050
|
-
logger: {
|
|
19051
|
-
|
|
19052
|
-
|
|
19053
|
-
|
|
19054
|
-
|
|
19055
|
-
}
|
|
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
|
+
// }
|
|
19056
19820
|
});
|
|
19057
19821
|
break;
|
|
19058
19822
|
case 'redundant':
|
|
@@ -19074,7 +19838,7 @@ class TextBrowser {
|
|
|
19074
19838
|
// Also could use siteI18n('chooselanguage'), but assumes locale
|
|
19075
19839
|
// as with page title
|
|
19076
19840
|
// $p.l10n = siteI18n; // Is this in use? No `params`, so not currently
|
|
19077
|
-
document.title = siteI18n('languages-title');
|
|
19841
|
+
document.title = /** @type {string} */siteI18n('languages-title');
|
|
19078
19842
|
Templates.languageSelect.main({
|
|
19079
19843
|
langs,
|
|
19080
19844
|
languages,
|
|
@@ -19113,8 +19877,8 @@ class TextBrowser {
|
|
|
19113
19877
|
fallbackLanguages,
|
|
19114
19878
|
languageParam,
|
|
19115
19879
|
$p,
|
|
19116
|
-
languages
|
|
19117
|
-
preferencesPlugin: this.preferencesPlugin
|
|
19880
|
+
languages
|
|
19881
|
+
// preferencesPlugin: this.preferencesPlugin
|
|
19118
19882
|
});
|
|
19119
19883
|
return true;
|
|
19120
19884
|
}
|