textbrowser 0.50.0 → 0.52.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ncurc.cjs +3 -0
- package/CHANGES.md +13 -0
- package/dist/WorkInfo-es.js +655 -165
- package/dist/activateCallback-es.js +81 -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 +3449 -1848
- package/dist/index-es.min.js +4 -4
- 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 +278 -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 +47 -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 +32 -19
- package/resources/activateCallback.js +81 -10
- package/resources/index.js +169 -58
- package/resources/resultsDisplay.js +520 -153
- package/resources/templates/index.js +39 -17
- 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 -76
- package/resources/templates/workSelect.js +16 -3
- package/resources/user-sample.js +1 -0
- package/resources/utils/IntlURLSearchParams.js +46 -4
- package/resources/utils/Languages.js +71 -4
- package/resources/utils/Metadata.js +222 -23
- package/resources/utils/Params.js +70 -23
- package/resources/utils/Plugin.js +175 -1
- package/resources/utils/ServiceWorker.js +49 -21
- package/resources/utils/WorkInfo.js +256 -44
- package/resources/utils/dialogs.js +105 -7
- package/resources/utils/getLocaleFallbackResults.js +15 -3
- package/resources/utils/sanitize.js +4 -0
- package/resources/workDisplay.js +151 -25
- package/resources/workSelect.js +37 -17
- package/server/main.js +118 -20
- package/sw-sample.js +2 -1
- package/tsconfig.json +30 -0
- package/resources/user.js +0 -20
package/resources/workDisplay.js
CHANGED
|
@@ -6,6 +6,61 @@ import {dialogs} from './utils/dialogs.js';
|
|
|
6
6
|
|
|
7
7
|
import Templates from './templates/index.js';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {() => Promise<{
|
|
11
|
+
* groupName: string | Text | DocumentFragment,
|
|
12
|
+
* worksToFields: {
|
|
13
|
+
* workName: string | Text | DocumentFragment,
|
|
14
|
+
* shortcut: string,
|
|
15
|
+
* fieldAliasOrNames: (
|
|
16
|
+
* string|string[]|import('../server/main.js').LocalizationStrings
|
|
17
|
+
* )[]|undefined
|
|
18
|
+
* }[]
|
|
19
|
+
* }[]>} GetFieldAliasOrNames
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @typedef {(innerArg: {
|
|
24
|
+
* form: HTMLFormElement,
|
|
25
|
+
* random: {
|
|
26
|
+
* checked: boolean
|
|
27
|
+
* },
|
|
28
|
+
* checkboxes: HTMLInputElement[],
|
|
29
|
+
* type: string,
|
|
30
|
+
* fieldAliasOrNames?: string[],
|
|
31
|
+
* workName?: string,
|
|
32
|
+
* }) => string} SerializeParamsAsURL
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {(
|
|
37
|
+
* key: string|string[],
|
|
38
|
+
* substitutions?: Record<string, string>
|
|
39
|
+
* ) => string|Text|DocumentFragment} LDirectional
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {(
|
|
44
|
+
* key: string,
|
|
45
|
+
* tag: string,
|
|
46
|
+
* attr: string,
|
|
47
|
+
* atts: import('jamilih').JamilihAttributes,
|
|
48
|
+
* children?: import('jamilih').JamilihChildren
|
|
49
|
+
* ) => import('jamilih').JamilihArray} LElement
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @this {import('./index.js').default}
|
|
54
|
+
* @param {{
|
|
55
|
+
* l: import('intl-dom').I18NCallback,
|
|
56
|
+
* languageParam: string,
|
|
57
|
+
* lang: string[],
|
|
58
|
+
* preferredLocale: string,
|
|
59
|
+
* languages: import('./utils/Languages.js').Languages,
|
|
60
|
+
* fallbackLanguages: string[],
|
|
61
|
+
* $p: import('./utils/IntlURLSearchParams.js').default
|
|
62
|
+
* }} cfg
|
|
63
|
+
*/
|
|
9
64
|
export default async function workDisplay ({
|
|
10
65
|
l, languageParam,
|
|
11
66
|
lang, preferredLocale, languages, fallbackLanguages, $p
|
|
@@ -13,7 +68,7 @@ export default async function workDisplay ({
|
|
|
13
68
|
const {preferencesPlugin} = this;
|
|
14
69
|
const langs = this.langData.languages;
|
|
15
70
|
|
|
16
|
-
const fallbackDirection = this.getDirectionForLanguageCode(fallbackLanguages[0]);
|
|
71
|
+
// const fallbackDirection = this.getDirectionForLanguageCode(fallbackLanguages[0]);
|
|
17
72
|
|
|
18
73
|
const prefI18n = localStorage.getItem(this.namespace + '-localizeParamNames');
|
|
19
74
|
const localizeParamNames = $p.localizeParamNames = $p.has('i18n', true)
|
|
@@ -29,19 +84,63 @@ export default async function workDisplay ({
|
|
|
29
84
|
prefFormatting !== 'false' && this.hideFormattingSection
|
|
30
85
|
);
|
|
31
86
|
|
|
87
|
+
/**
|
|
88
|
+
* @this {import('./index.js').default}
|
|
89
|
+
* @param {{
|
|
90
|
+
* workI18n: import('intl-dom').I18NCallback,
|
|
91
|
+
* metadataObj: import('./utils/Metadata.js').MetadataObj,
|
|
92
|
+
* getFieldAliasOrName: (field: string) => string|string[]|import('../server/main.js').LocalizationStrings,
|
|
93
|
+
* schemaItems: {title: string, type: string}[],
|
|
94
|
+
* fieldInfo: import('./utils/WorkInfo.js').FieldInfo,
|
|
95
|
+
* metadata: import('./utils/Metadata.js').Metadata,
|
|
96
|
+
* pluginsForWork: import('./utils/Plugin.js').PluginsForWork|null,
|
|
97
|
+
* groupsToWorks: {
|
|
98
|
+
* name: string | Text | DocumentFragment,
|
|
99
|
+
* workNames: (string | Text | DocumentFragment)[],
|
|
100
|
+
* shortcuts: string[]
|
|
101
|
+
* }[]
|
|
102
|
+
* }} cfg
|
|
103
|
+
* @returns {Promise<void>}
|
|
104
|
+
*/
|
|
32
105
|
async function _displayWork ({
|
|
33
106
|
workI18n, metadataObj, getFieldAliasOrName, schemaItems, // schemaObj,
|
|
34
107
|
fieldInfo, metadata, pluginsForWork, groupsToWorks
|
|
35
108
|
}) {
|
|
36
109
|
const lParam = localizeParamNames
|
|
37
|
-
|
|
38
|
-
|
|
110
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- TS
|
|
111
|
+
?
|
|
112
|
+
/**
|
|
113
|
+
* @param {string} key
|
|
114
|
+
* @returns {string}
|
|
115
|
+
*/ (key) => /** @type {string} */ (l(['params', key]))
|
|
116
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- TS
|
|
117
|
+
:
|
|
118
|
+
/**
|
|
119
|
+
* @param {string} key
|
|
120
|
+
* @returns {string}
|
|
121
|
+
*/
|
|
122
|
+
(key) => key;
|
|
39
123
|
const lIndexedParam = localizeParamNames
|
|
40
|
-
|
|
41
|
-
|
|
124
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- TS
|
|
125
|
+
?
|
|
126
|
+
/**
|
|
127
|
+
* @param {string} key
|
|
128
|
+
* @returns {string}
|
|
129
|
+
*/
|
|
130
|
+
(key) => /** @type {string} */ (l(['params', 'indexed', key]))
|
|
131
|
+
// eslint-disable-next-line @stylistic/operator-linebreak -- TS
|
|
132
|
+
:
|
|
133
|
+
/**
|
|
134
|
+
* @param {string} key
|
|
135
|
+
* @returns {string}
|
|
136
|
+
*/
|
|
137
|
+
(key) => key;
|
|
42
138
|
|
|
43
139
|
// Returns element with localized option text (as Jamilih), with
|
|
44
140
|
// optional fallback direction
|
|
141
|
+
/**
|
|
142
|
+
* @type {LElement}
|
|
143
|
+
*/
|
|
45
144
|
const lElement = (key, el, attToLocalize, atts, children = []) => {
|
|
46
145
|
atts[attToLocalize] = l(
|
|
47
146
|
key
|
|
@@ -55,6 +154,10 @@ export default async function workDisplay ({
|
|
|
55
154
|
};
|
|
56
155
|
|
|
57
156
|
// Returns plain text node or element (as Jamilih) with fallback direction
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @type {LDirectional}
|
|
160
|
+
*/
|
|
58
161
|
const lDirectional = (key, substitutions) => l(
|
|
59
162
|
key,
|
|
60
163
|
substitutions
|
|
@@ -67,15 +170,20 @@ export default async function workDisplay ({
|
|
|
67
170
|
const fieldMatchesLocale = metadata.getFieldMatchesLocale({
|
|
68
171
|
namespace: this.namespace,
|
|
69
172
|
preferredLocale, schemaItems,
|
|
70
|
-
|
|
173
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
174
|
+
pluginsForWork: /** @type {import('./utils/Plugin.js').PluginsForWork} */ (
|
|
175
|
+
pluginsForWork
|
|
176
|
+
)
|
|
71
177
|
});
|
|
72
178
|
|
|
179
|
+
/** @type {import('jamilih').JamilihArray[]} */
|
|
73
180
|
const content = [];
|
|
74
181
|
this.getBrowseFieldData({
|
|
75
182
|
metadataObj, schemaItems, getFieldAliasOrName,
|
|
76
183
|
callback ({browseFields, i}) {
|
|
77
184
|
Templates.workDisplay.addBrowseFields({
|
|
78
|
-
browseFields,
|
|
185
|
+
browseFields,
|
|
186
|
+
fieldInfo,
|
|
79
187
|
lDirectional, i, lIndexedParam, $p, content
|
|
80
188
|
});
|
|
81
189
|
}
|
|
@@ -89,10 +197,14 @@ export default async function workDisplay ({
|
|
|
89
197
|
const serializeParamsAsURL = getSerializeParamsAsURL({l, lParam, $p});
|
|
90
198
|
const paramsSetter = getParamsSetter({l, lParam, $p});
|
|
91
199
|
|
|
92
|
-
const {groups} =
|
|
200
|
+
const {groups} = /** @type {import('./utils/WorkInfo.js').FilesObject} */ (
|
|
201
|
+
await getJSON(this.files)
|
|
202
|
+
);
|
|
93
203
|
|
|
94
204
|
// const arabicContent = ['test1', 'test2']; // Todo: Fetch dynamically
|
|
95
|
-
const heading =
|
|
205
|
+
const heading = /** @type {string} */ (
|
|
206
|
+
getMetaProp(lang, metadataObj, 'heading')
|
|
207
|
+
);
|
|
96
208
|
|
|
97
209
|
const getFieldAliasOrNames = (() => {
|
|
98
210
|
// Avoid blocking but start now
|
|
@@ -102,10 +214,12 @@ export default async function workDisplay ({
|
|
|
102
214
|
const worksToFields = await Promise.all(workNames.map(async (workName, i) => {
|
|
103
215
|
return {
|
|
104
216
|
workName, shortcut: shortcuts[i],
|
|
105
|
-
fieldAliasOrNames: (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
217
|
+
fieldAliasOrNames: (
|
|
218
|
+
await this.getWorkData({
|
|
219
|
+
lang, fallbackLanguages, preferredLocale,
|
|
220
|
+
languages, work: /** @type {string} */ (workName)
|
|
221
|
+
})
|
|
222
|
+
)?.fieldInfo?.map(({fieldAliasOrName}) => fieldAliasOrName)
|
|
109
223
|
};
|
|
110
224
|
}));
|
|
111
225
|
return {
|
|
@@ -128,41 +242,53 @@ export default async function workDisplay ({
|
|
|
128
242
|
languageDisplay: 'standard' // 'dialect'
|
|
129
243
|
}
|
|
130
244
|
);
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* @param {string} code
|
|
248
|
+
*/
|
|
131
249
|
const languageI18n = (code) => {
|
|
132
|
-
return displayNames.of(code);
|
|
250
|
+
return /** @type {string} */ (displayNames.of(code));
|
|
133
251
|
};
|
|
134
252
|
|
|
135
253
|
Templates.workDisplay.main({
|
|
136
|
-
languageParam,
|
|
254
|
+
languageParam,
|
|
255
|
+
// lang,
|
|
256
|
+
workI18n,
|
|
137
257
|
l, namespace: this.namespace, groups, heading,
|
|
138
|
-
languageI18n,
|
|
258
|
+
languageI18n,
|
|
259
|
+
// fallbackDirection,
|
|
139
260
|
langs, fieldInfo, localizeParamNames,
|
|
140
261
|
serializeParamsAsURL, paramsSetter, replaceHash,
|
|
141
262
|
getFieldAliasOrNames,
|
|
142
263
|
hideFormattingSection, $p,
|
|
143
264
|
metadataObj, lParam, lElement, lDirectional, lIndexedParam,
|
|
144
265
|
fieldMatchesLocale,
|
|
145
|
-
preferredLocale, schemaItems,
|
|
266
|
+
preferredLocale, schemaItems,
|
|
267
|
+
content,
|
|
146
268
|
preferencesPlugin
|
|
147
269
|
});
|
|
148
270
|
}
|
|
149
271
|
|
|
150
272
|
try {
|
|
151
|
-
const {workI18n, fileData, metadataObj, ...args} =
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
273
|
+
const {workI18n, fileData, metadataObj, ...args} =
|
|
274
|
+
/** @type {import('./utils/WorkInfo.js').GetWorkDataReturn} */ (
|
|
275
|
+
await this.getWorkData({
|
|
276
|
+
lang, fallbackLanguages, preferredLocale,
|
|
277
|
+
languages,
|
|
278
|
+
work: /** @type {string} */ ($p.get('work'))
|
|
279
|
+
}));
|
|
155
280
|
|
|
156
|
-
document.title = workI18n(
|
|
281
|
+
document.title = /** @type {string} */ (workI18n(
|
|
157
282
|
'browserfile-workdisplay',
|
|
158
283
|
{
|
|
159
284
|
work: fileData
|
|
160
|
-
? getMetaProp(lang, metadataObj, 'alias')
|
|
285
|
+
? /** @type {string} */ (getMetaProp(lang, metadataObj, 'alias'))
|
|
161
286
|
: ''
|
|
162
287
|
}
|
|
163
|
-
);
|
|
288
|
+
));
|
|
164
289
|
await _displayWork.call(this, {workI18n, metadataObj, ...args});
|
|
165
|
-
} catch (
|
|
290
|
+
} catch (error) {
|
|
291
|
+
const err = /** @type {Error} */ (error);
|
|
166
292
|
console.log('err', err);
|
|
167
293
|
dialogs.alert(err);
|
|
168
294
|
}
|
package/resources/workSelect.js
CHANGED
|
@@ -5,6 +5,15 @@ import {getMetaProp} from './utils/Metadata.js';
|
|
|
5
5
|
import {dialogs} from './utils/dialogs.js';
|
|
6
6
|
import Templates from './templates/index.js';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @param {{
|
|
10
|
+
* files: string,
|
|
11
|
+
* lang: string[],
|
|
12
|
+
* fallbackLanguages: string[],
|
|
13
|
+
* $p: import('./utils/IntlURLSearchParams.js').default,
|
|
14
|
+
* followParams: (formSelector: string, cb: () => void) => void
|
|
15
|
+
* }} cfg
|
|
16
|
+
*/
|
|
8
17
|
export default async function workSelect ({
|
|
9
18
|
files, lang, fallbackLanguages, $p, followParams
|
|
10
19
|
/* , l, defineFormatter */
|
|
@@ -12,40 +21,48 @@ export default async function workSelect ({
|
|
|
12
21
|
// We use getJSON instead of JsonRefs as we do not necessarily need to
|
|
13
22
|
// resolve the file contents here
|
|
14
23
|
try {
|
|
15
|
-
const works =
|
|
24
|
+
const works = /** @type {import('./utils/WorkInfo.js').FilesObject} */ (
|
|
25
|
+
await getJSON(files)
|
|
26
|
+
);
|
|
16
27
|
const localizationStrings = works['localization-strings'];
|
|
17
28
|
|
|
18
|
-
const metadataObjs =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
const metadataObjs = /** @type {import('./utils/Metadata.js').MetadataObj[]} */ (
|
|
30
|
+
await getJSON(works.groups.reduce((arr, fileGroup) => {
|
|
31
|
+
const metadataBaseDir = (works.metadataBaseDirectory || '') +
|
|
32
|
+
(fileGroup.metadataBaseDirectory || '') + '/';
|
|
33
|
+
return fileGroup.files.reduce((ar, fileData) => [
|
|
34
|
+
...ar, metadataBaseDir + fileData.metadataFile
|
|
35
|
+
],
|
|
36
|
+
arr);
|
|
37
|
+
}, /** @type {string[]} */ ([])))
|
|
38
|
+
);
|
|
26
39
|
|
|
27
40
|
const workI18n = await i18n({
|
|
28
41
|
messageStyle: 'plainNested',
|
|
29
42
|
locales: lang,
|
|
30
43
|
defaultLocales: fallbackLanguages,
|
|
31
44
|
// Todo: Could at least share this with `index.js`
|
|
32
|
-
localeStringFinder ({
|
|
45
|
+
async localeStringFinder ({
|
|
33
46
|
locales, defaultLocales
|
|
34
|
-
}) {
|
|
35
|
-
const locale = [
|
|
47
|
+
} = {}) {
|
|
48
|
+
const locale = [
|
|
49
|
+
...(/** @type {string[]} */ (locales)),
|
|
50
|
+
...(/** @type {string[]} */ (defaultLocales))
|
|
51
|
+
].find((language) => {
|
|
36
52
|
return language in localizationStrings;
|
|
37
53
|
});
|
|
38
54
|
return {
|
|
39
|
-
|
|
55
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
56
|
+
locale: /** @type {string} */ (locale),
|
|
40
57
|
strings: {
|
|
41
58
|
head: {},
|
|
42
|
-
body: localizationStrings[locale]
|
|
59
|
+
body: localizationStrings[/** @type {string} */ (locale)]
|
|
43
60
|
}
|
|
44
61
|
};
|
|
45
62
|
}
|
|
46
63
|
});
|
|
47
64
|
|
|
48
|
-
document.title = workI18n('browserfile-workselect');
|
|
65
|
+
document.title = /** @type {string} */ (workI18n('browserfile-workselect'));
|
|
49
66
|
/*
|
|
50
67
|
// Would need adapting now that not using IMF
|
|
51
68
|
function lDirectional (key, substitutions, formats) {
|
|
@@ -64,13 +81,16 @@ export default async function workSelect ({
|
|
|
64
81
|
|
|
65
82
|
const metadataObjsIter = metadataObjs[Symbol.iterator]();
|
|
66
83
|
const getNextAlias = () => {
|
|
67
|
-
const metadataObj =
|
|
84
|
+
const metadataObj = /** @type {import('./utils/Metadata.js').MetadataObj} */ (
|
|
85
|
+
metadataObjsIter.next().value
|
|
86
|
+
);
|
|
68
87
|
return getMetaProp(lang, metadataObj, 'alias');
|
|
69
88
|
};
|
|
70
89
|
Templates.workSelect({
|
|
71
90
|
groups: works.groups, workI18n, getNextAlias, $p, followParams
|
|
72
91
|
});
|
|
73
|
-
} catch (
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const err = /** @type {Error} */ (error);
|
|
74
94
|
console.log('Error', err);
|
|
75
95
|
dialogs.alert(err);
|
|
76
96
|
}
|
package/server/main.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/* eslint-env node -- Environment here */
|
|
4
|
-
import http from 'http';
|
|
4
|
+
import http from 'node:http';
|
|
5
5
|
|
|
6
|
+
// @ts-expect-error Todo: Needs Types
|
|
6
7
|
import statik from '@brettz9/node-static';
|
|
7
8
|
import fetch from 'node-fetch';
|
|
9
|
+
// @ts-expect-error Todo: Needs Types
|
|
8
10
|
import commandLineArgs from 'command-line-args';
|
|
9
11
|
import DOMParser from 'dom-parser';
|
|
12
|
+
|
|
13
|
+
// Why can't we just import `indexeddbshim` here? Because we need a UMD module?
|
|
14
|
+
// @ts-expect-error Todo: Needs Types
|
|
10
15
|
import setGlobalVars from 'indexeddbshim/dist/indexeddbshim-UnicodeIdentifiers-node.cjs';
|
|
11
16
|
import {getJSON} from 'simple-get-json';
|
|
12
17
|
import {setFetch} from 'intl-dom';
|
|
@@ -18,6 +23,8 @@ import {setServiceWorkerDefaults} from '../resources/utils/ServiceWorker.js';
|
|
|
18
23
|
import {Languages} from '../resources/utils/Languages.js';
|
|
19
24
|
import activateCallback from '../resources/activateCallback.js';
|
|
20
25
|
|
|
26
|
+
// Todo: Should loosen this to not follow all of `fetch`'s API
|
|
27
|
+
// @ts-expect-error Todo: Needs types
|
|
21
28
|
setFetch(fetch);
|
|
22
29
|
|
|
23
30
|
// Todo (low): See
|
|
@@ -26,6 +33,28 @@ setFetch(fetch);
|
|
|
26
33
|
// server-side and apply fetch listener as Node middleware to retrieve a
|
|
27
34
|
// locally-saved copy of pre-fetched (cached) files during install event
|
|
28
35
|
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {{
|
|
38
|
+
* nodeActivate: boolean,
|
|
39
|
+
* port: number,
|
|
40
|
+
* domain: string,
|
|
41
|
+
* basePath: string,
|
|
42
|
+
* interlinearSeparator: string,
|
|
43
|
+
* localizeParamNames: boolean,
|
|
44
|
+
* trustFormatHTML: boolean,
|
|
45
|
+
* allowPlugins: boolean,
|
|
46
|
+
* showEmptyInterlinear: boolean,
|
|
47
|
+
* showTitleOnSingleInterlinear: boolean,
|
|
48
|
+
* serviceWorkerPath: string,
|
|
49
|
+
* userJSON: string,
|
|
50
|
+
* languages: string,
|
|
51
|
+
* files: string,
|
|
52
|
+
* namespace: string,
|
|
53
|
+
* httpServer: string,
|
|
54
|
+
* expressServer: string
|
|
55
|
+
* }} UserOptions
|
|
56
|
+
*/
|
|
57
|
+
|
|
29
58
|
const optionDefinitions = [
|
|
30
59
|
// Node-server-specific
|
|
31
60
|
{name: 'nodeActivate', type: Boolean},
|
|
@@ -64,6 +93,27 @@ const port = 'port' in userParams ? userParams.port : 8000;
|
|
|
64
93
|
const domain = userParams.domain || `localhost`;
|
|
65
94
|
const basePath = userParams.basePath || `http://${domain}${port ? ':' + port : ''}/`;
|
|
66
95
|
|
|
96
|
+
/* eslint-disable jsdoc/reject-any-type -- Arbitrary */
|
|
97
|
+
/**
|
|
98
|
+
* @typedef {any} AnyValue
|
|
99
|
+
*/
|
|
100
|
+
/* eslint-enable jsdoc/reject-any-type -- Arbitrary */
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @typedef {import('../resources/utils/ServiceWorker.js').ServiceWorkerConfig &
|
|
104
|
+
* UserOptions & {
|
|
105
|
+
* lang: string[],
|
|
106
|
+
* langs: LanguageInfo[],
|
|
107
|
+
* fallbackLanguages: string[],
|
|
108
|
+
* log: (...args: AnyValue[]) => void,
|
|
109
|
+
* nodeActivate?: boolean,
|
|
110
|
+
* port?: number,
|
|
111
|
+
* skipIndexedDB: false,
|
|
112
|
+
* noDynamic: false,
|
|
113
|
+
* }
|
|
114
|
+
* } ResultsDisplayServerContext
|
|
115
|
+
*/
|
|
116
|
+
|
|
67
117
|
const userParamsWithDefaults = {
|
|
68
118
|
...setServiceWorkerDefaults({}, {
|
|
69
119
|
namespace: 'textbrowser',
|
|
@@ -72,6 +122,9 @@ const userParamsWithDefaults = {
|
|
|
72
122
|
serviceWorkerPath: `${basePath}sw.js?pathToUserJSON=${encodeURIComponent(userParams.userJSON || '')}`
|
|
73
123
|
}),
|
|
74
124
|
...userParams,
|
|
125
|
+
/**
|
|
126
|
+
* @param {...AnyValue} args
|
|
127
|
+
*/
|
|
75
128
|
log (...args) {
|
|
76
129
|
console.log(...args);
|
|
77
130
|
},
|
|
@@ -100,8 +153,9 @@ setGlobalVars(null, {
|
|
|
100
153
|
}); // Adds `indexedDB` and `IDBKeyRange` to global in Node
|
|
101
154
|
|
|
102
155
|
if (userParams.nodeActivate) {
|
|
156
|
+
// @ts-expect-error Ok
|
|
103
157
|
// eslint-disable-next-line n/no-unsupported-features/node-builtins -- node-fetch
|
|
104
|
-
|
|
158
|
+
globalThis.fetch = /** @type {fetch} */ (fetch);
|
|
105
159
|
setTimeout(async () => {
|
|
106
160
|
await activateCallback({...userParamsWithDefaults, basePath});
|
|
107
161
|
});
|
|
@@ -109,15 +163,46 @@ if (userParams.nodeActivate) {
|
|
|
109
163
|
}
|
|
110
164
|
console.log('past activate check');
|
|
111
165
|
|
|
112
|
-
|
|
166
|
+
// @ts-expect-error Ok
|
|
167
|
+
globalThis.DOMParser = DOMParser; // potentially used within resultsDisplay.js
|
|
113
168
|
|
|
114
169
|
const fileServer = new statik.Server(); // Pass path; otherwise uses current directory
|
|
115
170
|
|
|
116
|
-
|
|
171
|
+
/**
|
|
172
|
+
* @typedef {{
|
|
173
|
+
* code: string,
|
|
174
|
+
* direction: "ltr"|"rtl",
|
|
175
|
+
* locale: {
|
|
176
|
+
* $ref: string
|
|
177
|
+
* }
|
|
178
|
+
* }} LanguageInfo
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @typedef {{
|
|
183
|
+
* [key: string]: string|string[]|LocalizationStrings
|
|
184
|
+
* }} LocalizationStrings
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @typedef {{
|
|
189
|
+
* languages: LanguageInfo[],
|
|
190
|
+
* localeFileBasePath?: string,
|
|
191
|
+
* "localization-strings": LocalizationStrings
|
|
192
|
+
* }} LanguagesData
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @type {LanguagesData}
|
|
197
|
+
*/
|
|
198
|
+
let langData;
|
|
199
|
+
|
|
200
|
+
/** @type {Languages} */
|
|
201
|
+
let languagesInstance;
|
|
117
202
|
|
|
118
203
|
const srv = http.createServer(async (req, res) => {
|
|
119
204
|
// console.log('URL::', new URL(req.url));
|
|
120
|
-
const {pathname, search} = new URL(req.url, basePath);
|
|
205
|
+
const {pathname, search} = new URL(/** @type {string} */ (req.url), basePath);
|
|
121
206
|
if (pathname !== '/textbrowser' || !search) {
|
|
122
207
|
const staticServer = () => {
|
|
123
208
|
if (pathname.includes('.git')) {
|
|
@@ -148,19 +233,25 @@ const srv = http.createServer(async (req, res) => {
|
|
|
148
233
|
);
|
|
149
234
|
};
|
|
150
235
|
if (userParams.expressServer) {
|
|
236
|
+
/** @type {import('express').Application} */
|
|
151
237
|
const app = (await import(userParams.expressServer)).default();
|
|
152
238
|
|
|
153
|
-
if (userParams.httpServer && (!app._router || !app._router.stack.some(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
239
|
+
if (userParams.httpServer && (!app._router || !app._router.stack.some(
|
|
240
|
+
/** @type {(info: {regexp: RegExp}) => boolean} */
|
|
241
|
+
({regexp}) => {
|
|
242
|
+
// Hack to ignore middleware like jsonParser (and hopefully
|
|
243
|
+
// not get any other)
|
|
244
|
+
return regexp.source !== String.raw`^\/?(?=\\/|$)` &&
|
|
245
|
+
regexp.test(/** @type {string} */ (req.url));
|
|
246
|
+
}
|
|
247
|
+
))) {
|
|
158
248
|
await runHttpServer();
|
|
159
249
|
|
|
160
250
|
// Ideally we could use `next` here to serve as a back-up static
|
|
161
251
|
// server (i.e., for the bahaiwritings app proper), but the indexes
|
|
162
252
|
// app apparently tries to use it (and fails) after a single
|
|
163
253
|
// successful HTML page load. So we let the Express app handle
|
|
254
|
+
// @ts-expect-error Ok
|
|
164
255
|
app(req, res, () => {
|
|
165
256
|
// Empty
|
|
166
257
|
});
|
|
@@ -168,6 +259,7 @@ const srv = http.createServer(async (req, res) => {
|
|
|
168
259
|
}
|
|
169
260
|
|
|
170
261
|
// app.get('*', staticServer);
|
|
262
|
+
// @ts-expect-error Ok
|
|
171
263
|
app(req, res, next);
|
|
172
264
|
|
|
173
265
|
return;
|
|
@@ -184,8 +276,9 @@ const srv = http.createServer(async (req, res) => {
|
|
|
184
276
|
return;
|
|
185
277
|
}
|
|
186
278
|
const languages = (req.headers['accept-language']?.replace(/;q=.*$/, '') ?? 'en-US').split(',');
|
|
279
|
+
// @ts-expect-error Polyglot reasons
|
|
187
280
|
// eslint-disable-next-line n/no-unsupported-features/node-builtins -- Polyglot reasons
|
|
188
|
-
|
|
281
|
+
globalThis.navigator = {
|
|
189
282
|
language: languages[0],
|
|
190
283
|
languages
|
|
191
284
|
};
|
|
@@ -194,7 +287,9 @@ const srv = http.createServer(async (req, res) => {
|
|
|
194
287
|
});
|
|
195
288
|
|
|
196
289
|
if (!langData || !languagesInstance) {
|
|
197
|
-
langData =
|
|
290
|
+
langData = /** @type {LanguagesData} */ (
|
|
291
|
+
await getJSON(userParamsWithDefaults.languages)
|
|
292
|
+
);
|
|
198
293
|
languagesInstance = new Languages({langData});
|
|
199
294
|
}
|
|
200
295
|
|
|
@@ -207,22 +302,25 @@ const srv = http.createServer(async (req, res) => {
|
|
|
207
302
|
});
|
|
208
303
|
|
|
209
304
|
const resultsDisplay = async function () {
|
|
210
|
-
const serverOutput =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
305
|
+
const serverOutput = /** @type {"html"|"jamilih"|"json"} */ (
|
|
306
|
+
$p.get('serverOutput', true)
|
|
307
|
+
);
|
|
308
|
+
const allowPluginsParam = $p.get('allowPlugins', true);
|
|
309
|
+
const allowPlugins = Boolean(allowPluginsParam && allowPluginsParam !== '0');
|
|
310
|
+
|
|
215
311
|
const isHTML = serverOutput === 'html';
|
|
216
312
|
res.writeHead(200, {'Content-Type': isHTML
|
|
217
313
|
? 'text/html;charset=utf8'
|
|
218
314
|
: 'application/json;charset=utf8'
|
|
219
315
|
});
|
|
316
|
+
|
|
220
317
|
// Todo: Move sw-sample.js to bahaiwritings and test
|
|
221
318
|
const result = await resultsDisplayServer.call(
|
|
222
319
|
// Context
|
|
223
|
-
{
|
|
320
|
+
/** @type {ResultsDisplayServerContext} */
|
|
321
|
+
({
|
|
224
322
|
...userParamsWithDefaults, lang, langs, fallbackLanguages
|
|
225
|
-
},
|
|
323
|
+
}),
|
|
226
324
|
// resultsArgs
|
|
227
325
|
{
|
|
228
326
|
l,
|
|
@@ -235,7 +333,7 @@ const srv = http.createServer(async (req, res) => {
|
|
|
235
333
|
allowPlugins,
|
|
236
334
|
serverOutput,
|
|
237
335
|
langData,
|
|
238
|
-
prefI18n: $p.get('prefI18n', true)
|
|
336
|
+
prefI18n: /** @type {"true"|"false"|null} */ ($p.get('prefI18n', true))
|
|
239
337
|
}
|
|
240
338
|
);
|
|
241
339
|
res.end(isHTML ? result : JSON.stringify(result));
|
package/sw-sample.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/* eslint-env serviceworker -- Service worker */
|
|
2
2
|
|
|
3
|
+
// eslint-disable-next-line sonarjs/no-internal-api-use -- Demo
|
|
3
4
|
import swHelper from './node_modules/textbrowser/dist/sw-helper.js';
|
|
4
5
|
|
|
5
6
|
// IMPORTANT: Keep this comment and increment this number to trigger
|
|
6
7
|
// a worker change: 1
|
|
7
8
|
|
|
8
|
-
swHelper(
|
|
9
|
+
swHelper(globalThis);
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": ["es2022", "DOM", "DOM.Iterable", "webworker"],
|
|
4
|
+
"moduleResolution": "Bundler",
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"checkJs": true,
|
|
8
|
+
"emitDeclarationOnly": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"declarationMap": true,
|
|
11
|
+
"strict": true,
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"target": "es2017",
|
|
14
|
+
"outDir": "dist"
|
|
15
|
+
},
|
|
16
|
+
"include": [
|
|
17
|
+
"*.js",
|
|
18
|
+
"resources",
|
|
19
|
+
"server",
|
|
20
|
+
"test",
|
|
21
|
+
"dist/sw-helper.js"
|
|
22
|
+
// "typings/*.d.ts"
|
|
23
|
+
],
|
|
24
|
+
"exclude": [
|
|
25
|
+
"node_modules", "resources/vendor", "resources/user-sample.js",
|
|
26
|
+
"resources/user.js",
|
|
27
|
+
"sw-sample.js",
|
|
28
|
+
"dist"
|
|
29
|
+
]
|
|
30
|
+
}
|
package/resources/user.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import TextBrowser from '../dist/index-es.js';
|
|
2
|
-
|
|
3
|
-
const tb = new TextBrowser({
|
|
4
|
-
languages: 'appdata/languages.json', // Default
|
|
5
|
-
// serviceWorkerPath: 'sw.js', // Default
|
|
6
|
-
// site: 'site.json', // Default
|
|
7
|
-
// localizeParamNames: true, // Not well-tested
|
|
8
|
-
// hideFormattingSection: true,
|
|
9
|
-
// requestPersistentStorage: false,
|
|
10
|
-
// showEmptyInterlinear: false,
|
|
11
|
-
// showTitleOnSingleInterlinear: false,
|
|
12
|
-
files: 'files.json', // Change as needed to your `files.json` location
|
|
13
|
-
stylesheets: ['@builtin'], // Add other paths for your CSS
|
|
14
|
-
namespace: 'myapp', // Used for namespacing localStorage
|
|
15
|
-
allowPlugins: true, // Enables `files.json`-specified plugins
|
|
16
|
-
// dynamicBasePath: '',
|
|
17
|
-
trustFormatHTML: true // Needed if allowing for raw HTML fields (don't use for untrusted schemas)
|
|
18
|
-
// , interlinearSeparator: '<hr />' // Defaults to `<br /><br />`
|
|
19
|
-
});
|
|
20
|
-
await tb.init();
|