textbrowser 0.49.1 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ncurc.cjs +3 -0
- package/CHANGES.md +14 -0
- package/dist/WorkInfo-es.js +262 -13
- 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 +860 -134
- 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 +22 -9
- 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/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,21 @@ 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
|
+
/**
|
|
97
|
+
* @typedef {import('../resources/utils/ServiceWorker.js').ServiceWorkerConfig &
|
|
98
|
+
* UserOptions & {
|
|
99
|
+
* lang: string[],
|
|
100
|
+
* langs: LanguageInfo[],
|
|
101
|
+
* fallbackLanguages: string[],
|
|
102
|
+
* log: (...args: any[]) => void,
|
|
103
|
+
* nodeActivate?: boolean,
|
|
104
|
+
* port?: number,
|
|
105
|
+
* skipIndexedDB: false,
|
|
106
|
+
* noDynamic: false,
|
|
107
|
+
* }
|
|
108
|
+
* } ResultsDisplayServerContext
|
|
109
|
+
*/
|
|
110
|
+
|
|
67
111
|
const userParamsWithDefaults = {
|
|
68
112
|
...setServiceWorkerDefaults({}, {
|
|
69
113
|
namespace: 'textbrowser',
|
|
@@ -72,6 +116,9 @@ const userParamsWithDefaults = {
|
|
|
72
116
|
serviceWorkerPath: `${basePath}sw.js?pathToUserJSON=${encodeURIComponent(userParams.userJSON || '')}`
|
|
73
117
|
}),
|
|
74
118
|
...userParams,
|
|
119
|
+
/**
|
|
120
|
+
* @param {...any} args
|
|
121
|
+
*/
|
|
75
122
|
log (...args) {
|
|
76
123
|
console.log(...args);
|
|
77
124
|
},
|
|
@@ -100,8 +147,9 @@ setGlobalVars(null, {
|
|
|
100
147
|
}); // Adds `indexedDB` and `IDBKeyRange` to global in Node
|
|
101
148
|
|
|
102
149
|
if (userParams.nodeActivate) {
|
|
150
|
+
// @ts-expect-error Ok
|
|
103
151
|
// eslint-disable-next-line n/no-unsupported-features/node-builtins -- node-fetch
|
|
104
|
-
|
|
152
|
+
globalThis.fetch = /** @type {fetch} */ (fetch);
|
|
105
153
|
setTimeout(async () => {
|
|
106
154
|
await activateCallback({...userParamsWithDefaults, basePath});
|
|
107
155
|
});
|
|
@@ -109,15 +157,46 @@ if (userParams.nodeActivate) {
|
|
|
109
157
|
}
|
|
110
158
|
console.log('past activate check');
|
|
111
159
|
|
|
112
|
-
|
|
160
|
+
// @ts-expect-error Ok
|
|
161
|
+
globalThis.DOMParser = DOMParser; // potentially used within resultsDisplay.js
|
|
113
162
|
|
|
114
163
|
const fileServer = new statik.Server(); // Pass path; otherwise uses current directory
|
|
115
164
|
|
|
116
|
-
|
|
165
|
+
/**
|
|
166
|
+
* @typedef {{
|
|
167
|
+
* code: string,
|
|
168
|
+
* direction: "ltr"|"rtl",
|
|
169
|
+
* locale: {
|
|
170
|
+
* $ref: string
|
|
171
|
+
* }
|
|
172
|
+
* }} LanguageInfo
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @typedef {{
|
|
177
|
+
* [key: string]: string|string[]|LocalizationStrings
|
|
178
|
+
* }} LocalizationStrings
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @typedef {{
|
|
183
|
+
* languages: LanguageInfo[],
|
|
184
|
+
* localeFileBasePath?: string,
|
|
185
|
+
* "localization-strings": LocalizationStrings
|
|
186
|
+
* }} LanguagesData
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @type {LanguagesData}
|
|
191
|
+
*/
|
|
192
|
+
let langData;
|
|
193
|
+
|
|
194
|
+
/** @type {Languages} */
|
|
195
|
+
let languagesInstance;
|
|
117
196
|
|
|
118
197
|
const srv = http.createServer(async (req, res) => {
|
|
119
198
|
// console.log('URL::', new URL(req.url));
|
|
120
|
-
const {pathname, search} = new URL(req.url, basePath);
|
|
199
|
+
const {pathname, search} = new URL(/** @type {string} */ (req.url), basePath);
|
|
121
200
|
if (pathname !== '/textbrowser' || !search) {
|
|
122
201
|
const staticServer = () => {
|
|
123
202
|
if (pathname.includes('.git')) {
|
|
@@ -148,19 +227,25 @@ const srv = http.createServer(async (req, res) => {
|
|
|
148
227
|
);
|
|
149
228
|
};
|
|
150
229
|
if (userParams.expressServer) {
|
|
230
|
+
/** @type {import('express').Application} */
|
|
151
231
|
const app = (await import(userParams.expressServer)).default();
|
|
152
232
|
|
|
153
|
-
if (userParams.httpServer && (!app._router || !app._router.stack.some(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
233
|
+
if (userParams.httpServer && (!app._router || !app._router.stack.some(
|
|
234
|
+
/** @type {(info: {regexp: RegExp}) => boolean} */
|
|
235
|
+
({regexp}) => {
|
|
236
|
+
// Hack to ignore middleware like jsonParser (and hopefully
|
|
237
|
+
// not get any other)
|
|
238
|
+
return regexp.source !== String.raw`^\/?(?=\\/|$)` &&
|
|
239
|
+
regexp.test(/** @type {string} */ (req.url));
|
|
240
|
+
}
|
|
241
|
+
))) {
|
|
158
242
|
await runHttpServer();
|
|
159
243
|
|
|
160
244
|
// Ideally we could use `next` here to serve as a back-up static
|
|
161
245
|
// server (i.e., for the bahaiwritings app proper), but the indexes
|
|
162
246
|
// app apparently tries to use it (and fails) after a single
|
|
163
247
|
// successful HTML page load. So we let the Express app handle
|
|
248
|
+
// @ts-expect-error Ok
|
|
164
249
|
app(req, res, () => {
|
|
165
250
|
// Empty
|
|
166
251
|
});
|
|
@@ -168,6 +253,7 @@ const srv = http.createServer(async (req, res) => {
|
|
|
168
253
|
}
|
|
169
254
|
|
|
170
255
|
// app.get('*', staticServer);
|
|
256
|
+
// @ts-expect-error Ok
|
|
171
257
|
app(req, res, next);
|
|
172
258
|
|
|
173
259
|
return;
|
|
@@ -184,6 +270,7 @@ const srv = http.createServer(async (req, res) => {
|
|
|
184
270
|
return;
|
|
185
271
|
}
|
|
186
272
|
const languages = (req.headers['accept-language']?.replace(/;q=.*$/, '') ?? 'en-US').split(',');
|
|
273
|
+
// @ts-expect-error Polyglot reasons
|
|
187
274
|
// eslint-disable-next-line n/no-unsupported-features/node-builtins -- Polyglot reasons
|
|
188
275
|
global.navigator = {
|
|
189
276
|
language: languages[0],
|
|
@@ -194,7 +281,9 @@ const srv = http.createServer(async (req, res) => {
|
|
|
194
281
|
});
|
|
195
282
|
|
|
196
283
|
if (!langData || !languagesInstance) {
|
|
197
|
-
langData =
|
|
284
|
+
langData = /** @type {LanguagesData} */ (
|
|
285
|
+
await getJSON(userParamsWithDefaults.languages)
|
|
286
|
+
);
|
|
198
287
|
languagesInstance = new Languages({langData});
|
|
199
288
|
}
|
|
200
289
|
|
|
@@ -207,22 +296,25 @@ const srv = http.createServer(async (req, res) => {
|
|
|
207
296
|
});
|
|
208
297
|
|
|
209
298
|
const resultsDisplay = async function () {
|
|
210
|
-
const serverOutput =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
299
|
+
const serverOutput = /** @type {"html"|"jamilih"|"json"} */ (
|
|
300
|
+
$p.get('serverOutput', true)
|
|
301
|
+
);
|
|
302
|
+
const allowPluginsParam = $p.get('allowPlugins', true);
|
|
303
|
+
const allowPlugins = Boolean(allowPluginsParam && allowPluginsParam !== '0');
|
|
304
|
+
|
|
215
305
|
const isHTML = serverOutput === 'html';
|
|
216
306
|
res.writeHead(200, {'Content-Type': isHTML
|
|
217
307
|
? 'text/html;charset=utf8'
|
|
218
308
|
: 'application/json;charset=utf8'
|
|
219
309
|
});
|
|
310
|
+
|
|
220
311
|
// Todo: Move sw-sample.js to bahaiwritings and test
|
|
221
312
|
const result = await resultsDisplayServer.call(
|
|
222
313
|
// Context
|
|
223
|
-
{
|
|
314
|
+
/** @type {ResultsDisplayServerContext} */
|
|
315
|
+
({
|
|
224
316
|
...userParamsWithDefaults, lang, langs, fallbackLanguages
|
|
225
|
-
},
|
|
317
|
+
}),
|
|
226
318
|
// resultsArgs
|
|
227
319
|
{
|
|
228
320
|
l,
|
|
@@ -235,7 +327,7 @@ const srv = http.createServer(async (req, res) => {
|
|
|
235
327
|
allowPlugins,
|
|
236
328
|
serverOutput,
|
|
237
329
|
langData,
|
|
238
|
-
prefI18n: $p.get('prefI18n', true)
|
|
330
|
+
prefI18n: /** @type {"true"|"false"|null} */ ($p.get('prefI18n', true))
|
|
239
331
|
}
|
|
240
332
|
);
|
|
241
333
|
res.end(isHTML ? result : JSON.stringify(result));
|
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();
|