textbrowser 0.47.0 → 0.48.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/.eslintignore +2 -1
- package/CHANGES.md +4 -0
- package/dist/WorkInfo-es.js +6 -1
- package/dist/activateCallback-es.js +4 -0
- package/dist/assets/index-c987c995.css +9 -0
- package/dist/assets/languages-fcf1c836.json +67 -0
- package/dist/index-es.js +26 -30
- package/dist/index-es.min.js +1 -1
- package/dist/sw-helper.js +310 -0
- package/package.json +15 -14
- package/resources/activateCallback.js +4 -0
- package/resources/index.js +2 -10
- package/resources/resultsDisplay.js +5 -1
- package/resources/utils/IntlURLSearchParams.js +3 -0
- package/resources/utils/Languages.js +3 -0
- package/resources/utils/ServiceWorker.js +14 -3
- package/resources/utils/WorkInfo.js +6 -1
- package/resources/utils/getLocaleFallbackResults.js +3 -0
- package/server/main.js +0 -1
- package/sw-sample.js +5 -307
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import activateCallback from './activateCallback-es.js';
|
|
2
|
+
import {getWorkFiles} from './WorkInfo-es.js';
|
|
3
|
+
|
|
4
|
+
// VERSION 0.1.0
|
|
5
|
+
|
|
6
|
+
const CURRENT_CACHES = {
|
|
7
|
+
prefetch: 'prefetch-cache-v'
|
|
8
|
+
};
|
|
9
|
+
const minutes = 60 * 1000;
|
|
10
|
+
|
|
11
|
+
// UTILITIES
|
|
12
|
+
|
|
13
|
+
async function getJSON (url) {
|
|
14
|
+
const resp = await fetch(url);
|
|
15
|
+
return await resp.json();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function swHelper (self) {
|
|
19
|
+
// These could be made configurable by argument too
|
|
20
|
+
const defaultUserStaticFiles = [
|
|
21
|
+
'/', // Needs a separate entry from `index.html` (at least in Chrome)
|
|
22
|
+
'index.html',
|
|
23
|
+
'files.json',
|
|
24
|
+
'site.json',
|
|
25
|
+
'resources/user.js'
|
|
26
|
+
// We do not put the user.json here as that is obtained live with this
|
|
27
|
+
// service worker via `pathToUserJSON`
|
|
28
|
+
];
|
|
29
|
+
// Todo: We could supply `new URL(fileName, moduleURL).href` to
|
|
30
|
+
// get these as reliable full paths without hard-coding or needing to
|
|
31
|
+
// actually be in `node_modules/textbrowser`; see `resources/index.js`
|
|
32
|
+
const textbrowserStaticResourceFiles = [
|
|
33
|
+
'node_modules/textbrowser/appdata/languages.json',
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
// Only needed atm for browser validation
|
|
37
|
+
'node_modules/textbrowser/general-schemas/files.jsonschema',
|
|
38
|
+
'node_modules/textbrowser/general-schemas/languages.jsonschema',
|
|
39
|
+
'node_modules/textbrowser-data-schemas/schemas/locale.jsonschema',
|
|
40
|
+
'node_modules/textbrowser-data-schemas/schemas/metadata.jsonschema',
|
|
41
|
+
'node_modules/textbrowser-data-schemas/schemas/table.jsonschema', // Not currently using for validation or meta-data
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
'node_modules/textbrowser/dist/index-es.js'
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @typedef {PlainObject} ConfigObject
|
|
49
|
+
* @property {string} namespace
|
|
50
|
+
* @property {string} basePath
|
|
51
|
+
* @property {string} languages
|
|
52
|
+
* @property {string} files
|
|
53
|
+
* @property {string[]} userStaticFiles
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
*
|
|
58
|
+
* @param {ConfigObject} args
|
|
59
|
+
* @returns {ConfigObject}
|
|
60
|
+
* @todo Since some of these reused, move to external file (or
|
|
61
|
+
* use `setServiceWorkerDefaults`?)
|
|
62
|
+
*/
|
|
63
|
+
function getConfigDefaults (args) {
|
|
64
|
+
return {
|
|
65
|
+
namespace: 'textbrowser',
|
|
66
|
+
basePath: '',
|
|
67
|
+
languages: new URL('../appdata/languages.json', import.meta.url).href,
|
|
68
|
+
files: 'files.json',
|
|
69
|
+
userStaticFiles: defaultUserStaticFiles,
|
|
70
|
+
// Opportunity to override
|
|
71
|
+
...args
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
*
|
|
77
|
+
* @param {string[]} messages
|
|
78
|
+
* @returns {Promise<void>}
|
|
79
|
+
*/
|
|
80
|
+
function log (...messages) {
|
|
81
|
+
const message = messages.join(' ');
|
|
82
|
+
console.log(message);
|
|
83
|
+
return post({message, type: 'log'});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {Error} error
|
|
89
|
+
* @param {string[]} messages
|
|
90
|
+
* @returns {Promise<void>} Resolves to `undefined`
|
|
91
|
+
*/
|
|
92
|
+
function logError (error, ...messages) {
|
|
93
|
+
const message = messages.join(' ');
|
|
94
|
+
console.error(error, message);
|
|
95
|
+
return post({message, errorType: error.type, name: error.name, type: 'error'});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @callback DelayCallback
|
|
100
|
+
* @param {Float} time
|
|
101
|
+
* @returns {void}
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
*
|
|
106
|
+
* @param {DelayCallback} cb
|
|
107
|
+
* @param {PositiveInteger} timeout
|
|
108
|
+
* @param {string} errMessage
|
|
109
|
+
* @param {PositiveInteger} [time=0]
|
|
110
|
+
* @returns {Promise<void>}
|
|
111
|
+
*/
|
|
112
|
+
async function tryAndRetry (cb, timeout, errMessage, time = 0) {
|
|
113
|
+
time++;
|
|
114
|
+
try {
|
|
115
|
+
await cb(time); // eslint-disable-line n/callback-return -- Needed for retries
|
|
116
|
+
return undefined;
|
|
117
|
+
} catch (err) {
|
|
118
|
+
console.log('errrr', err);
|
|
119
|
+
logError(err, err.message || errMessage);
|
|
120
|
+
return new Promise((resolve, reject) => {
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
resolve(tryAndRetry(cb, timeout, errMessage, time));
|
|
123
|
+
}, timeout);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
*
|
|
130
|
+
* @param {PlainObject} args
|
|
131
|
+
* @param {"log"|"error"|"beginInstall"|"finishedInstall"|"beginActivate"|"finishedActivate"} args.type
|
|
132
|
+
* @param {string} [args.message=type]
|
|
133
|
+
* @returns {Promise<void>}
|
|
134
|
+
*/
|
|
135
|
+
async function post ({type, message = type}) {
|
|
136
|
+
const clients = await self.clients.matchAll({
|
|
137
|
+
// Are there any uncontrolled within activate anyways?
|
|
138
|
+
includeUncontrolled: true,
|
|
139
|
+
type: 'window'
|
|
140
|
+
}) || [];
|
|
141
|
+
if (message.includes('Posting finished')) {
|
|
142
|
+
message += ` (count: ${clients.length})`;
|
|
143
|
+
}
|
|
144
|
+
clients.forEach((client) => {
|
|
145
|
+
// Although we only need one client to which to send
|
|
146
|
+
// arguments, we want to signal phase complete to all
|
|
147
|
+
// eslint-disable-next-line unicorn/require-post-message-target-origin -- In worker
|
|
148
|
+
client.postMessage({message, type});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
*
|
|
154
|
+
* @param {PositiveInteger} time
|
|
155
|
+
* @throws {Error}
|
|
156
|
+
* @returns {Promise<void>}
|
|
157
|
+
*/
|
|
158
|
+
async function install (time) {
|
|
159
|
+
post({type: 'beginInstall'});
|
|
160
|
+
log(`Install: Trying, attempt ${time}`);
|
|
161
|
+
const now = Date.now();
|
|
162
|
+
const json = await getJSON(pathToUserJSON);
|
|
163
|
+
|
|
164
|
+
const {
|
|
165
|
+
namespace, languages, files, userStaticFiles
|
|
166
|
+
} = getConfigDefaults(json);
|
|
167
|
+
|
|
168
|
+
const {version} = await getJSON('./package.json');
|
|
169
|
+
|
|
170
|
+
console.log('opening cache', namespace + CURRENT_CACHES.prefetch + version);
|
|
171
|
+
const [
|
|
172
|
+
cache,
|
|
173
|
+
userDataFiles,
|
|
174
|
+
{languages: langs}
|
|
175
|
+
] = await Promise.all([
|
|
176
|
+
caches.open(namespace + CURRENT_CACHES.prefetch + version),
|
|
177
|
+
getWorkFiles(files),
|
|
178
|
+
getJSON(languages)
|
|
179
|
+
]);
|
|
180
|
+
log('Install: Retrieved dependency values');
|
|
181
|
+
|
|
182
|
+
const langPathParts = languages.split('/');
|
|
183
|
+
|
|
184
|
+
// Todo: Ought to make these locales only conditionally required and
|
|
185
|
+
// then only show those specified in languages menu or go directly
|
|
186
|
+
// to work selection
|
|
187
|
+
// Todo: We might give option to only download
|
|
188
|
+
// one locale and avoid language splash page
|
|
189
|
+
const localeFiles = langs.map(
|
|
190
|
+
({locale: {$ref}}) => {
|
|
191
|
+
return (langPathParts.length > 1
|
|
192
|
+
? langPathParts.slice(0, -1).join('/') + '/'
|
|
193
|
+
: ''
|
|
194
|
+
) + $ref;
|
|
195
|
+
}
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
const urlsToPrefetch = [
|
|
199
|
+
...textbrowserStaticResourceFiles,
|
|
200
|
+
...localeFiles,
|
|
201
|
+
...userStaticFiles,
|
|
202
|
+
...userDataFiles,
|
|
203
|
+
...stylesheets
|
|
204
|
+
];
|
|
205
|
+
// .map((url) => url === 'index.html' ? new Request(url, {cache: 'reload'}) : url)
|
|
206
|
+
try {
|
|
207
|
+
const cachePromises = urlsToPrefetch.map(async (urlToPrefetch) => {
|
|
208
|
+
// This constructs a new URL object using the service worker's script location as the base
|
|
209
|
+
// for relative URLs.
|
|
210
|
+
const url = new URL(urlToPrefetch, location.href);
|
|
211
|
+
url.search += (url.search ? '&' : '?') + 'cache-bust=' + now;
|
|
212
|
+
const request = new Request(url, {mode: 'no-cors'});
|
|
213
|
+
try {
|
|
214
|
+
const response = await fetch(request);
|
|
215
|
+
if (response.status >= 400) {
|
|
216
|
+
throw new Error('request for ' + urlToPrefetch +
|
|
217
|
+
' failed with status ' + response.statusText);
|
|
218
|
+
}
|
|
219
|
+
return cache.put(urlToPrefetch, response);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
logError(error, 'Not caching ' + urlToPrefetch + ' due to ' + error);
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
await Promise.all(cachePromises);
|
|
226
|
+
log('Install: Pre-fetching complete.');
|
|
227
|
+
} catch (error) {
|
|
228
|
+
logError(error, `Install: Pre-fetching failed: ${error}`);
|
|
229
|
+
// Failing gives chance for a new client to re-trigger install?
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// An install update event will not be reported until controlled,
|
|
234
|
+
// so we need to inform the clients
|
|
235
|
+
log(`Install: Posting finished message to clients`);
|
|
236
|
+
|
|
237
|
+
// Although we only need one client to which to send
|
|
238
|
+
// arguments, we want to signal phase complete to all
|
|
239
|
+
post({type: 'finishedInstall'});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
*
|
|
244
|
+
* @param {PositiveInteger} time
|
|
245
|
+
* @returns {Promise<void>}
|
|
246
|
+
*/
|
|
247
|
+
async function activate (time) {
|
|
248
|
+
post({type: 'beginActivate'});
|
|
249
|
+
log(`Activate: Trying, attempt ${time}`);
|
|
250
|
+
const [json, cacheNames] = await Promise.all([
|
|
251
|
+
getJSON(pathToUserJSON),
|
|
252
|
+
caches.keys()
|
|
253
|
+
]);
|
|
254
|
+
const {namespace, files, basePath} = getConfigDefaults(json);
|
|
255
|
+
const {version} = await getJSON('./package.json');
|
|
256
|
+
|
|
257
|
+
const expectedCacheNames = Object.values(CURRENT_CACHES).map((n) => namespace + n + version);
|
|
258
|
+
cacheNames.map(async (cacheName) => {
|
|
259
|
+
if (!expectedCacheNames.includes(cacheName)) {
|
|
260
|
+
log('Activate: Deleting out of date cache:', cacheName);
|
|
261
|
+
await caches.delete(cacheName);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
await activateCallback({namespace, files, basePath, log});
|
|
266
|
+
log('Activate: Database changes completed');
|
|
267
|
+
|
|
268
|
+
log(`Activate: Posting finished message to clients`);
|
|
269
|
+
// Signal phase complete to all clients
|
|
270
|
+
post({type: 'finishedActivate'});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const params = new URL(location).searchParams;
|
|
274
|
+
const pathToUserJSON = params.get('pathToUserJSON');
|
|
275
|
+
const stylesheets = JSON.parse(params.get('stylesheets') || []);
|
|
276
|
+
|
|
277
|
+
console.log('sw info', pathToUserJSON);
|
|
278
|
+
console.log('sw stylesheets', stylesheets);
|
|
279
|
+
|
|
280
|
+
self.addEventListener('install', (e) => {
|
|
281
|
+
e.waitUntil(tryAndRetry(install, 5 * minutes, 'Error installing'));
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
self.addEventListener('activate', (e) => {
|
|
285
|
+
// Erring is of no present use here:
|
|
286
|
+
// https://github.com/w3c/ServiceWorker/issues/659#issuecomment-384919053
|
|
287
|
+
e.waitUntil(tryAndRetry(activate, 5 * minutes, 'Error activating'));
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// We cannot make this async as `e.respondWith` must be called synchronously
|
|
291
|
+
self.addEventListener('fetch', (e) => {
|
|
292
|
+
// DevTools opening will trigger these o-i-c requests
|
|
293
|
+
const {request} = e;
|
|
294
|
+
const {cache, mode, url} = request;
|
|
295
|
+
if (cache === 'only-if-cached' &&
|
|
296
|
+
mode !== 'same-origin') {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
console.log('fetching', url);
|
|
300
|
+
e.respondWith((async () => {
|
|
301
|
+
const cached = await caches.match(request);
|
|
302
|
+
if (!cached) {
|
|
303
|
+
console.log('no cached found', url);
|
|
304
|
+
}
|
|
305
|
+
return cached || fetch(request);
|
|
306
|
+
})());
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export default swHelper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "textbrowser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.0",
|
|
4
4
|
"description": "Multilinear text browser",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index-es.min.js",
|
|
@@ -9,18 +9,6 @@
|
|
|
9
9
|
"bin": {
|
|
10
10
|
"textbrowser": "./server/main.js"
|
|
11
11
|
},
|
|
12
|
-
"scripts": {
|
|
13
|
-
"server": "./server/main.js --allowPlugins --namespace=test",
|
|
14
|
-
"start": "static -p 8081",
|
|
15
|
-
"rollup": "rollup -c",
|
|
16
|
-
"lint": "npm run eslint",
|
|
17
|
-
"eslint": "eslint --ext=js,md,html .",
|
|
18
|
-
"mocha": "mocha --require test/bootstrap/node.js --require chai/register-assert.js test/textbrowserTests.js",
|
|
19
|
-
"node": "npm run eslint && npm run rollup && npm run mocha",
|
|
20
|
-
"open-test": "open-cli http://127.0.0.1:8081/test/",
|
|
21
|
-
"start-open-test": "run-p start open-test",
|
|
22
|
-
"test": "npm run eslint && npm run rollup && npm run start-open-test"
|
|
23
|
-
},
|
|
24
12
|
"browserslist": [
|
|
25
13
|
"cover 100%"
|
|
26
14
|
],
|
|
@@ -69,6 +57,7 @@
|
|
|
69
57
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
70
58
|
"@rollup/plugin-terser": "^0.1.0",
|
|
71
59
|
"@stadtlandnetz/rollup-plugin-postprocess": "^1.1.0",
|
|
60
|
+
"@web/rollup-plugin-import-meta-assets": "^1.0.7",
|
|
72
61
|
"ajv": "8.11.2",
|
|
73
62
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
74
63
|
"chai": "^4.3.7",
|
|
@@ -96,5 +85,17 @@
|
|
|
96
85
|
"rollup": "^3.4.0",
|
|
97
86
|
"rollup-plugin-re": "^1.0.7",
|
|
98
87
|
"textbrowser-data-schemas": "^0.2.0"
|
|
88
|
+
},
|
|
89
|
+
"scripts": {
|
|
90
|
+
"server": "./server/main.js --allowPlugins --namespace=test",
|
|
91
|
+
"start": "static -p 8081",
|
|
92
|
+
"rollup": "rollup -c",
|
|
93
|
+
"lint": "npm run eslint",
|
|
94
|
+
"eslint": "eslint --ext=js,md,html .",
|
|
95
|
+
"mocha": "mocha --require test/bootstrap/node.js --require chai/register-assert.js test/textbrowserTests.js",
|
|
96
|
+
"node": "npm run eslint && npm run rollup && npm run mocha",
|
|
97
|
+
"open-test": "open-cli http://127.0.0.1:8081/test/",
|
|
98
|
+
"start-open-test": "run-p start open-test",
|
|
99
|
+
"test": "npm run eslint && npm run rollup && npm run start-open-test"
|
|
99
100
|
}
|
|
100
|
-
}
|
|
101
|
+
}
|
package/resources/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {serialize as formSerialize} from 'form-serialization';
|
|
|
8
8
|
import getLocaleFallbackResults from './utils/getLocaleFallbackResults.js';
|
|
9
9
|
import {dialogs} from './utils/dialogs.js';
|
|
10
10
|
import {getFieldNameAndValueAliases, getBrowseFieldData} from './utils/Metadata.js';
|
|
11
|
-
import {
|
|
11
|
+
import {getWorkData} from './utils/WorkInfo.js';
|
|
12
12
|
import {
|
|
13
13
|
respondToState, listenForWorkerUpdate, registerServiceWorker, setServiceWorkerDefaults
|
|
14
14
|
} from './utils/ServiceWorker.js';
|
|
@@ -165,10 +165,6 @@ async function requestPermissions (langs, l) {
|
|
|
165
165
|
|
|
166
166
|
class TextBrowser {
|
|
167
167
|
constructor (options) {
|
|
168
|
-
// Todo: Replace the `languages` default with `import.meta.url`
|
|
169
|
-
// (`new URL('../appdata/languages.json', import.meta.url).href`?)
|
|
170
|
-
// https://github.com/tc39/proposal-import-meta
|
|
171
|
-
const moduleURL = new URL('node_modules/textbrowser/resources/index.js', location);
|
|
172
168
|
this.site = options.site || 'site.json';
|
|
173
169
|
const stylesheets = options.stylesheets || ['@builtin'];
|
|
174
170
|
const builtinIndex = stylesheets.indexOf('@builtin');
|
|
@@ -176,7 +172,7 @@ class TextBrowser {
|
|
|
176
172
|
stylesheets.splice(
|
|
177
173
|
builtinIndex,
|
|
178
174
|
1,
|
|
179
|
-
new URL('index.css',
|
|
175
|
+
new URL('index.css', import.meta.url).href
|
|
180
176
|
);
|
|
181
177
|
}
|
|
182
178
|
this.stylesheets = stylesheets;
|
|
@@ -203,10 +199,7 @@ class TextBrowser {
|
|
|
203
199
|
|
|
204
200
|
async init () {
|
|
205
201
|
this._stylesheetElements = await loadStylesheets(this.stylesheets);
|
|
206
|
-
return this.displayLanguages();
|
|
207
|
-
}
|
|
208
202
|
|
|
209
|
-
async displayLanguages () {
|
|
210
203
|
// We use getJSON instead of JsonRefs as we do not need to resolve the locales here
|
|
211
204
|
try {
|
|
212
205
|
const [langData, siteData] = await getJSON([this.languages, this.site]);
|
|
@@ -587,6 +580,5 @@ class TextBrowser {
|
|
|
587
580
|
// Todo: Definable as public fields?
|
|
588
581
|
TextBrowser.prototype.workDisplay = workDisplay;
|
|
589
582
|
TextBrowser.prototype.resultsDisplayClient = resultsDisplayClient;
|
|
590
|
-
TextBrowser.prototype.getWorkFiles = getWorkFiles;
|
|
591
583
|
|
|
592
584
|
export default TextBrowser;
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
} from './utils/Metadata.js';
|
|
11
11
|
import {Languages} from './utils/Languages.js';
|
|
12
12
|
import {getWorkData} from './utils/WorkInfo.js';
|
|
13
|
-
// Keep this as the last import for Rollup
|
|
14
13
|
|
|
15
14
|
const {getLangDir} = rtlDetect;
|
|
16
15
|
const fieldValueAliasRegex = /^.* \((.*?)\)$/;
|
|
@@ -117,6 +116,11 @@ export const resultsDisplayClient = async function resultsDisplayClient (args) {
|
|
|
117
116
|
});
|
|
118
117
|
};
|
|
119
118
|
|
|
119
|
+
/**
|
|
120
|
+
* This is server-only code, but kept here as the function is similar.
|
|
121
|
+
* @param {{serverOutput: "jamilih"|"html"|"json"}} args
|
|
122
|
+
* @returns {Promise<Array|string>}
|
|
123
|
+
*/
|
|
120
124
|
export const resultsDisplayServer = async function resultsDisplayServer (args) {
|
|
121
125
|
const {
|
|
122
126
|
templateArgs
|
|
@@ -20,6 +20,9 @@ export const getPreferredLanguages = ({namespace, preferredLocale}) => {
|
|
|
20
20
|
return langArr;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* @classdesc Note that this should be kept as a polyglot client-server class.
|
|
25
|
+
*/
|
|
23
26
|
export class Languages {
|
|
24
27
|
constructor ({langData}) {
|
|
25
28
|
this.langData = langData;
|
|
@@ -2,12 +2,23 @@
|
|
|
2
2
|
// import {escapeHTML} from './sanitize.js';
|
|
3
3
|
import {dialogs} from './dialogs.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Note that this function be kept as a polyglot client-server file.
|
|
7
|
+
* @param {PlainObject} target
|
|
8
|
+
* @param {PlainObject} source
|
|
9
|
+
* @returns {{
|
|
10
|
+
* userJSON: string,
|
|
11
|
+
* languages: string,
|
|
12
|
+
* serviceWorkerPath: string,
|
|
13
|
+
* files: string,
|
|
14
|
+
* namespace: string
|
|
15
|
+
* }}
|
|
16
|
+
*/
|
|
5
17
|
export const setServiceWorkerDefaults = (target, source) => {
|
|
6
18
|
target.userJSON = source.userJSON || 'resources/user.json';
|
|
7
19
|
target.languages = source.languages || new URL(
|
|
8
|
-
'
|
|
9
|
-
|
|
10
|
-
new URL('node_modules/textbrowser/resources/index.js', location)
|
|
20
|
+
'../../appdata/languages.json',
|
|
21
|
+
import.meta.url
|
|
11
22
|
).href;
|
|
12
23
|
target.serviceWorkerPath = source.serviceWorkerPath ||
|
|
13
24
|
`sw.js?pathToUserJSON=${
|
|
@@ -3,7 +3,12 @@ import {i18n} from 'intl-dom';
|
|
|
3
3
|
import {getMetaProp, getMetadata, Metadata} from './Metadata.js';
|
|
4
4
|
import {PluginsForWork, escapePlugin} from './Plugin.js';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Imported by the `dist/sw-helper.js`
|
|
8
|
+
* @param {string} files The files.json file path
|
|
9
|
+
* @returns {PlainObject}
|
|
10
|
+
*/
|
|
11
|
+
export const getWorkFiles = async function getWorkFiles (files) {
|
|
7
12
|
const filesObj = await getJSON(files);
|
|
8
13
|
const dataFiles = [];
|
|
9
14
|
filesObj.groups.forEach((fileGroup) => {
|
package/server/main.js
CHANGED
|
@@ -15,7 +15,6 @@ import IntlURLSearchParams from '../resources/utils/IntlURLSearchParams.js';
|
|
|
15
15
|
import {resultsDisplayServer} from '../resources/resultsDisplay.js';
|
|
16
16
|
import getLocaleFallbackResults from '../resources/utils/getLocaleFallbackResults.js';
|
|
17
17
|
import {setServiceWorkerDefaults} from '../resources/utils/ServiceWorker.js';
|
|
18
|
-
// import setGlobalVars from 'indexeddbshim/src/node-UnicodeIdentifiers.js';
|
|
19
18
|
import {Languages} from '../resources/utils/Languages.js';
|
|
20
19
|
import activateCallback from '../resources/activateCallback.js';
|
|
21
20
|
|