ochre-sdk 1.0.78 → 1.1.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/README.md +31 -3
- package/dist/_virtual/_rolldown/runtime.mjs +13 -0
- package/dist/categories.d.mts +249 -0
- package/dist/categories.mjs +259 -0
- package/dist/constants.d.mts +14 -0
- package/dist/constants.mjs +18 -1
- package/dist/errors.d.mts +23 -0
- package/dist/{utilities.mjs → errors.mjs} +33 -84
- package/dist/fetchers/gallery.mjs +15 -51
- package/dist/fetchers/item-children.mjs +20 -66
- package/dist/fetchers/item-links.mjs +26 -79
- package/dist/fetchers/item-ocr-data.d.mts +2 -2
- package/dist/fetchers/item-ocr-data.mjs +11 -15
- package/dist/fetchers/item.d.mts +0 -15
- package/dist/fetchers/item.mjs +20 -72
- package/dist/fetchers/request.d.mts +70 -0
- package/dist/fetchers/request.mjs +100 -0
- package/dist/fetchers/set/items.mjs +27 -73
- package/dist/fetchers/set/property-values.d.mts +2 -3
- package/dist/fetchers/set/property-values.mjs +96 -130
- package/dist/fetchers/website-metadata.mjs +35 -57
- package/dist/fetchers/website.d.mts +2 -3
- package/dist/fetchers/website.mjs +22 -31
- package/dist/getters.d.mts +78 -148
- package/dist/getters.mjs +127 -208
- package/dist/helpers.d.mts +0 -4
- package/dist/helpers.mjs +19 -6
- package/dist/index.d.mts +8 -6
- package/dist/index.mjs +6 -4
- package/dist/ocr.d.mts +37 -0
- package/dist/ocr.mjs +52 -0
- package/dist/parsers/helpers.d.mts +21 -1
- package/dist/parsers/helpers.mjs +26 -6
- package/dist/parsers/index.d.mts +0 -8
- package/dist/parsers/index.mjs +118 -259
- package/dist/parsers/languages.d.mts +72 -0
- package/dist/parsers/languages.mjs +132 -0
- package/dist/parsers/multilingual.d.mts +49 -74
- package/dist/parsers/multilingual.mjs +88 -189
- package/dist/parsers/property-token.d.mts +34 -0
- package/dist/parsers/property-token.mjs +29 -0
- package/dist/parsers/string.d.mts +19 -0
- package/dist/parsers/string.mjs +45 -25
- package/dist/parsers/website/bounds.d.mts +10 -0
- package/dist/parsers/website/bounds.mjs +28 -0
- package/dist/parsers/website/components.d.mts +91 -0
- package/dist/parsers/website/components.mjs +681 -0
- package/dist/parsers/website/index.d.mts +0 -7
- package/dist/parsers/website/index.mjs +92 -1153
- package/dist/parsers/website/links.d.mts +36 -0
- package/dist/parsers/website/links.mjs +58 -0
- package/dist/parsers/website/messages.d.mts +24 -0
- package/dist/parsers/website/messages.mjs +31 -0
- package/dist/parsers/website/options.d.mts +6 -0
- package/dist/parsers/website/options.mjs +114 -0
- package/dist/parsers/website/properties.d.mts +12 -0
- package/dist/parsers/website/properties.mjs +158 -0
- package/dist/parsers/website/reader.d.mts +54 -4
- package/dist/parsers/website/reader.mjs +65 -20
- package/dist/parsers/website/slug.d.mts +64 -0
- package/dist/parsers/website/slug.mjs +82 -0
- package/dist/parsers/website/styles.d.mts +28 -0
- package/dist/parsers/website/styles.mjs +103 -0
- package/dist/parsers/website/walk.d.mts +68 -0
- package/dist/parsers/website/walk.mjs +116 -0
- package/dist/query.d.mts +66 -18
- package/dist/query.mjs +202 -48
- package/dist/reflection.d.mts +64 -0
- package/dist/reflection.mjs +79 -0
- package/dist/schemas.d.mts +7 -0
- package/dist/schemas.mjs +12 -3
- package/dist/types/index.d.mts +1 -31
- package/dist/types/utilities.d.mts +9 -0
- package/dist/types/utilities.mjs +1 -0
- package/dist/types/website.d.mts +49 -58
- package/dist/xml/metadata.d.mts +16 -0
- package/dist/xml/metadata.mjs +32 -11
- package/dist/xml/schemas.d.mts +5970 -3
- package/dist/xml/schemas.mjs +43 -45
- package/dist/xml/types.d.mts +13 -30
- package/dist/xquery.d.mts +46 -0
- package/dist/xquery.mjs +66 -0
- package/package.json +3 -3
- package/dist/utilities.d.mts +0 -54
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_LANGUAGES } from "../constants.mjs";
|
|
2
|
+
import { readProperty } from "../reflection.mjs";
|
|
2
3
|
import { serializeMDXText } from "./mdx.mjs";
|
|
3
4
|
//#region src/parsers/multilingual.ts
|
|
4
5
|
const MULTILINGUAL_STRING_INTERNAL_INIT = Symbol("MultilingualString.internalInit");
|
|
@@ -56,8 +57,28 @@ function getImplicitLanguages(content, options) {
|
|
|
56
57
|
for (const language of Object.keys(content)) if (!languages.includes(language)) languages.push(language);
|
|
57
58
|
return languages.length > 0 ? languages : [...DEFAULT_LANGUAGES];
|
|
58
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Pick the language reads should fall back to first
|
|
62
|
+
* @param availableLanguages - The languages carrying content, in order
|
|
63
|
+
* @param supportedLanguages - Every language the string was created for
|
|
64
|
+
* @returns The default language
|
|
65
|
+
*/
|
|
66
|
+
function resolveDefaultLanguageOption(availableLanguages, supportedLanguages) {
|
|
67
|
+
return availableLanguages[0] ?? supportedLanguages[0] ?? DEFAULT_LANGUAGES[0];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Whether a constructor argument is the module's own normalized init
|
|
71
|
+
*
|
|
72
|
+
* The assertion is earned by the brand rather than by inspecting the fields:
|
|
73
|
+
* {@link MULTILINGUAL_STRING_INTERNAL_INIT} is a module-private symbol, so no
|
|
74
|
+
* caller outside this file can produce a value carrying it, and the single
|
|
75
|
+
* producer is `fromNormalized`. That is what makes the narrowing sound; a
|
|
76
|
+
* field-by-field check would only re-state what the brand already guarantees.
|
|
77
|
+
* @param value - The constructor argument
|
|
78
|
+
* @returns True when the value carries the internal brand
|
|
79
|
+
*/
|
|
59
80
|
function isInternalInit(value) {
|
|
60
|
-
return
|
|
81
|
+
return readProperty(value, MULTILINGUAL_STRING_INTERNAL_INIT) === true;
|
|
61
82
|
}
|
|
62
83
|
/**
|
|
63
84
|
* Multilingual string
|
|
@@ -84,7 +105,7 @@ var MultilingualString = class MultilingualString {
|
|
|
84
105
|
for (const language of actualLanguages) normalizedContent[language] = entriesFromTexts(content[language] ?? []);
|
|
85
106
|
const availableLanguages = getLanguagesWithEntries(normalizedContent, actualLanguages);
|
|
86
107
|
const defaultOptions = {
|
|
87
|
-
defaultLanguage: options.defaultLanguage ?? availableLanguages
|
|
108
|
+
defaultLanguage: options.defaultLanguage ?? resolveDefaultLanguageOption(availableLanguages, actualLanguages),
|
|
88
109
|
availableLanguages: actualLanguages,
|
|
89
110
|
aliases: normalizeAliases(options.aliases)
|
|
90
111
|
};
|
|
@@ -97,7 +118,7 @@ var MultilingualString = class MultilingualString {
|
|
|
97
118
|
}
|
|
98
119
|
const availableLanguages = getLanguagesWithEntries(normalizedContent, languages);
|
|
99
120
|
const defaultOptions = {
|
|
100
|
-
defaultLanguage: options.defaultLanguage ?? availableLanguages
|
|
121
|
+
defaultLanguage: options.defaultLanguage ?? resolveDefaultLanguageOption(availableLanguages, languages),
|
|
101
122
|
availableLanguages: languages,
|
|
102
123
|
aliases: normalizeAliases(options.aliases)
|
|
103
124
|
};
|
|
@@ -120,6 +141,7 @@ var MultilingualString = class MultilingualString {
|
|
|
120
141
|
static fromJSON(json, languages, options = {}) {
|
|
121
142
|
const content = json.content;
|
|
122
143
|
const mergedOptions = {
|
|
144
|
+
defaultLanguage: json.defaultLanguage,
|
|
123
145
|
...options,
|
|
124
146
|
aliases: json.aliases
|
|
125
147
|
};
|
|
@@ -144,256 +166,133 @@ var MultilingualString = class MultilingualString {
|
|
|
144
166
|
this._availableLanguages = parsed._availableLanguages;
|
|
145
167
|
this._aliases = parsed._aliases;
|
|
146
168
|
}
|
|
147
|
-
|
|
148
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Resolve the entries to read for a language
|
|
171
|
+
*
|
|
172
|
+
* The fallback order is requested language, then the dataset's default
|
|
173
|
+
* language, then the first language that has any content. This is the only
|
|
174
|
+
* place that order is written down; every reader below is a projection of it.
|
|
175
|
+
*/
|
|
176
|
+
resolveEntries(language, isExact) {
|
|
177
|
+
const candidateLanguages = isExact ? [language] : [
|
|
178
|
+
language,
|
|
179
|
+
this._options.defaultLanguage,
|
|
180
|
+
...this._availableLanguages
|
|
181
|
+
];
|
|
182
|
+
for (const candidateLanguage of candidateLanguages) {
|
|
183
|
+
if (candidateLanguage == null) continue;
|
|
184
|
+
const entries = this._content[candidateLanguage] ?? [];
|
|
185
|
+
if (entries.length > 0) return entries;
|
|
186
|
+
}
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
resolvePrimaryEntry(language, isExact) {
|
|
190
|
+
const entries = this.resolveEntries(language, isExact);
|
|
149
191
|
for (const entry of entries) if (entry.isPrimary) return entry;
|
|
150
192
|
return entries[0] ?? null;
|
|
151
193
|
}
|
|
152
194
|
/**
|
|
153
|
-
* Get text in a specific language
|
|
195
|
+
* Get text in a specific language, falling back when it has none
|
|
154
196
|
*/
|
|
155
197
|
getText(language) {
|
|
156
|
-
|
|
157
|
-
const defaultEntry = this.getPrimaryEntry(this._options.defaultLanguage);
|
|
158
|
-
if (defaultEntry != null) return defaultEntry.text;
|
|
159
|
-
}
|
|
160
|
-
if (language != null) {
|
|
161
|
-
const requestedEntry = this.getPrimaryEntry(language);
|
|
162
|
-
if (requestedEntry != null) return requestedEntry.text;
|
|
163
|
-
}
|
|
164
|
-
const defaultEntry = this.getPrimaryEntry(this._options.defaultLanguage);
|
|
165
|
-
if (defaultEntry != null) return defaultEntry.text;
|
|
166
|
-
for (const availableLanguage of this._availableLanguages) {
|
|
167
|
-
const entry = this.getPrimaryEntry(availableLanguage);
|
|
168
|
-
if (entry != null) return entry.text;
|
|
169
|
-
}
|
|
170
|
-
return "";
|
|
198
|
+
return this.resolvePrimaryEntry(language, false)?.text ?? "";
|
|
171
199
|
}
|
|
172
200
|
/**
|
|
173
|
-
* Get rich text in a specific language
|
|
201
|
+
* Get rich text in a specific language, falling back when it has none
|
|
174
202
|
*/
|
|
175
203
|
getRichText(language) {
|
|
176
|
-
|
|
177
|
-
const defaultEntry = this.getPrimaryEntry(this._options.defaultLanguage);
|
|
178
|
-
if (defaultEntry != null) return defaultEntry.richText;
|
|
179
|
-
}
|
|
180
|
-
if (language != null) {
|
|
181
|
-
const requestedEntry = this.getPrimaryEntry(language);
|
|
182
|
-
if (requestedEntry != null) return requestedEntry.richText;
|
|
183
|
-
}
|
|
184
|
-
const defaultEntry = this.getPrimaryEntry(this._options.defaultLanguage);
|
|
185
|
-
if (defaultEntry != null) return defaultEntry.richText;
|
|
186
|
-
for (const availableLanguage of this._availableLanguages) {
|
|
187
|
-
const entry = this.getPrimaryEntry(availableLanguage);
|
|
188
|
-
if (entry != null) return entry.richText;
|
|
189
|
-
}
|
|
190
|
-
return "";
|
|
204
|
+
return this.resolvePrimaryEntry(language, false)?.richText ?? "";
|
|
191
205
|
}
|
|
192
206
|
/**
|
|
193
|
-
* Get
|
|
207
|
+
* Get text in a specific language, with no fallback
|
|
194
208
|
*/
|
|
195
209
|
getExactText(language) {
|
|
196
|
-
return this.
|
|
210
|
+
return this.resolvePrimaryEntry(language, true)?.text ?? "";
|
|
197
211
|
}
|
|
198
212
|
/**
|
|
199
|
-
* Get
|
|
213
|
+
* Get rich text in a specific language, with no fallback
|
|
200
214
|
*/
|
|
201
215
|
getExactRichText(language) {
|
|
202
|
-
return this.
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Get all text entries in a specific language without fallback
|
|
206
|
-
*/
|
|
207
|
-
getExactTexts(language) {
|
|
208
|
-
return Array.from(this._content[language] ?? [], (entry) => entry.text);
|
|
216
|
+
return this.resolvePrimaryEntry(language, true)?.richText ?? "";
|
|
209
217
|
}
|
|
210
218
|
/**
|
|
211
|
-
* Get
|
|
212
|
-
*/
|
|
213
|
-
getExactRichTexts(language) {
|
|
214
|
-
return Array.from(this._content[language] ?? [], (entry) => entry.richText);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Get all text entries in a specific language with fallback
|
|
218
|
-
*/
|
|
219
|
-
getTexts(language) {
|
|
220
|
-
if (language != null && (this._content[language]?.length ?? 0) > 0) return this.getExactTexts(language);
|
|
221
|
-
const defaultLanguage = this._options.defaultLanguage;
|
|
222
|
-
if ((this._content[defaultLanguage]?.length ?? 0) > 0) return this.getExactTexts(defaultLanguage);
|
|
223
|
-
const firstLanguage = this._availableLanguages[0];
|
|
224
|
-
return firstLanguage == null ? [] : this.getExactTexts(firstLanguage);
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Get all rich text entries in a specific language with fallback
|
|
228
|
-
*/
|
|
229
|
-
getRichTexts(language) {
|
|
230
|
-
if (language != null && (this._content[language]?.length ?? 0) > 0) return this.getExactRichTexts(language);
|
|
231
|
-
const defaultLanguage = this._options.defaultLanguage;
|
|
232
|
-
if ((this._content[defaultLanguage]?.length ?? 0) > 0) return this.getExactRichTexts(defaultLanguage);
|
|
233
|
-
const firstLanguage = this._availableLanguages[0];
|
|
234
|
-
return firstLanguage == null ? [] : this.getExactRichTexts(firstLanguage);
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Get all entries in a specific language without fallback
|
|
219
|
+
* Get every entry for a specific language, with no fallback
|
|
238
220
|
*/
|
|
239
221
|
getExactEntries(language) {
|
|
240
|
-
return Array.from(this.
|
|
241
|
-
text: entry.text,
|
|
242
|
-
richText: entry.richText,
|
|
243
|
-
isPrimary: entry.isPrimary
|
|
244
|
-
}));
|
|
222
|
+
return Array.from(this.resolveEntries(language, true), (entry) => ({ ...entry }));
|
|
245
223
|
}
|
|
246
224
|
/**
|
|
247
|
-
* Get
|
|
248
|
-
*/
|
|
249
|
-
getEntries(language) {
|
|
250
|
-
if (language != null && (this._content[language]?.length ?? 0) > 0) return this.getExactEntries(language);
|
|
251
|
-
const defaultLanguage = this._options.defaultLanguage;
|
|
252
|
-
if ((this._content[defaultLanguage]?.length ?? 0) > 0) return this.getExactEntries(defaultLanguage);
|
|
253
|
-
const firstLanguage = this._availableLanguages[0];
|
|
254
|
-
return firstLanguage == null ? [] : this.getExactEntries(firstLanguage);
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Get aliases carried by OCHRE as zxx content
|
|
225
|
+
* Get the alias values OCHRE carries as `zxx` content
|
|
258
226
|
*/
|
|
259
227
|
getAliases() {
|
|
260
228
|
return [...this._aliases];
|
|
261
229
|
}
|
|
262
230
|
/**
|
|
263
|
-
*
|
|
264
|
-
*/
|
|
265
|
-
hasLanguage(language) {
|
|
266
|
-
return (this._content[language]?.length ?? 0) > 0;
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Check if aliases exist
|
|
270
|
-
*/
|
|
271
|
-
hasAliases() {
|
|
272
|
-
return this._aliases.length > 0;
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Get all available languages
|
|
231
|
+
* Get the languages that actually carry content
|
|
276
232
|
*/
|
|
277
233
|
getAvailableLanguages() {
|
|
278
|
-
return this._availableLanguages;
|
|
234
|
+
return [...this._availableLanguages];
|
|
279
235
|
}
|
|
280
236
|
/**
|
|
281
|
-
* Get
|
|
282
|
-
*/
|
|
283
|
-
getSupportedLanguages() {
|
|
284
|
-
return this._options.availableLanguages;
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Check if the multilingual string is empty (no content in any language)
|
|
288
|
-
*/
|
|
289
|
-
isEmpty() {
|
|
290
|
-
return this._availableLanguages.length === 0;
|
|
291
|
-
}
|
|
292
|
-
/**
|
|
293
|
-
* Check if the multilingual string has any content
|
|
294
|
-
*/
|
|
295
|
-
hasContent() {
|
|
296
|
-
for (const language of this._availableLanguages) {
|
|
297
|
-
const entries = this._content[language] ?? [];
|
|
298
|
-
for (const entry of entries) if (entry.text.trim().length > 0 || entry.richText.trim().length > 0) return true;
|
|
299
|
-
}
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Get the default language
|
|
237
|
+
* Get the language reads fall back to before trying the rest
|
|
304
238
|
*/
|
|
305
239
|
getDefaultLanguage() {
|
|
306
240
|
return this._options.defaultLanguage;
|
|
307
241
|
}
|
|
308
242
|
/**
|
|
309
|
-
*
|
|
243
|
+
* Set the text for a language, or append another entry to it
|
|
244
|
+
* @param language - The language to write
|
|
245
|
+
* @param text - The text to write
|
|
246
|
+
* @param options - Write options
|
|
247
|
+
* @param options.shouldAppend - Append as an additional entry instead of replacing
|
|
248
|
+
* @returns A new multilingual string
|
|
310
249
|
*/
|
|
311
|
-
|
|
250
|
+
with(language, text, options = {}) {
|
|
312
251
|
const newContent = cloneContent(this._content);
|
|
313
|
-
newContent[language] =
|
|
314
|
-
const newAvailableLanguages = getLanguagesWithEntries(newContent, this._options.availableLanguages);
|
|
315
|
-
return MultilingualString.fromNormalized(newContent, this._options, newAvailableLanguages);
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Add another text entry for a language (returns new instance)
|
|
319
|
-
*/
|
|
320
|
-
withEntry(language, text) {
|
|
321
|
-
const newContent = cloneContent(this._content);
|
|
322
|
-
newContent[language] = normalizePrimary([...newContent[language] ?? [], {
|
|
252
|
+
newContent[language] = options.shouldAppend === true ? normalizePrimary([...newContent[language] ?? [], {
|
|
323
253
|
...normalizeInputText(text),
|
|
324
254
|
isPrimary: false
|
|
325
|
-
}]);
|
|
326
|
-
|
|
327
|
-
return MultilingualString.fromNormalized(newContent, this._options, newAvailableLanguages);
|
|
255
|
+
}]) : entriesFromTexts([text]);
|
|
256
|
+
return MultilingualString.fromNormalized(newContent, this._options, getLanguagesWithEntries(newContent, this._options.availableLanguages));
|
|
328
257
|
}
|
|
329
258
|
/**
|
|
330
|
-
*
|
|
259
|
+
* Remove the content for a language
|
|
260
|
+
*
|
|
261
|
+
* When the removed language was the default, the default moves to the first
|
|
262
|
+
* language that still has content, so reads keep resolving.
|
|
263
|
+
* @param language - The language to remove
|
|
264
|
+
* @returns A new multilingual string
|
|
331
265
|
*/
|
|
332
|
-
|
|
333
|
-
return MultilingualString.fromNormalized(this._content, {
|
|
334
|
-
...this._options,
|
|
335
|
-
aliases: normalizeAliases(aliases)
|
|
336
|
-
}, this._availableLanguages);
|
|
337
|
-
}
|
|
338
|
-
/**
|
|
339
|
-
* Remove text for a language (returns new instance)
|
|
340
|
-
*/
|
|
341
|
-
withoutLanguage(language) {
|
|
342
|
-
const newContent = {};
|
|
266
|
+
without(language) {
|
|
343
267
|
const currentContent = cloneContent(this._content);
|
|
344
|
-
for (const supportedLanguage of this._options.availableLanguages) if (supportedLanguage !== language) newContent[supportedLanguage] = normalizePrimary(currentContent[supportedLanguage] ?? []);
|
|
345
|
-
const newAvailableLanguages = getLanguagesWithEntries(newContent, this._options.availableLanguages);
|
|
346
|
-
const newDefaultLanguage = this._options.defaultLanguage === language ? newAvailableLanguages[0] ?? this._options.availableLanguages[0] : this._options.defaultLanguage;
|
|
347
|
-
return MultilingualString.fromNormalized(newContent, {
|
|
348
|
-
...this._options,
|
|
349
|
-
defaultLanguage: newDefaultLanguage
|
|
350
|
-
}, newAvailableLanguages);
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Transform all language versions (returns new instance)
|
|
354
|
-
*/
|
|
355
|
-
map(function_) {
|
|
356
|
-
const newContent = {};
|
|
357
|
-
for (const language of this._availableLanguages) newContent[language] = normalizePrimary(Array.from(this._content[language] ?? [], (entry) => ({
|
|
358
|
-
text: function_(entry.text, language),
|
|
359
|
-
richText: function_(entry.richText, language),
|
|
360
|
-
isPrimary: entry.isPrimary
|
|
361
|
-
})));
|
|
362
|
-
return MultilingualString.fromNormalized(newContent, this._options, this._availableLanguages);
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Filter languages based on predicate (returns new instance)
|
|
366
|
-
*/
|
|
367
|
-
filter(shouldInclude) {
|
|
368
268
|
const newContent = {};
|
|
369
|
-
for (const
|
|
370
|
-
const entries = [];
|
|
371
|
-
const languageEntries = this._content[language] ?? [];
|
|
372
|
-
for (const entry of languageEntries) if (shouldInclude(entry.text, language)) entries.push(entry);
|
|
373
|
-
newContent[language] = normalizePrimary(entries);
|
|
374
|
-
}
|
|
269
|
+
for (const supportedLanguage of this._options.availableLanguages) if (supportedLanguage !== language) newContent[supportedLanguage] = normalizePrimary(currentContent[supportedLanguage] ?? []);
|
|
375
270
|
const newAvailableLanguages = getLanguagesWithEntries(newContent, this._options.availableLanguages);
|
|
376
|
-
const newDefaultLanguage = (newContent[this._options.defaultLanguage]?.length ?? 0) > 0 ? this._options.defaultLanguage : newAvailableLanguages[0] ?? this._options.availableLanguages[0];
|
|
377
271
|
return MultilingualString.fromNormalized(newContent, {
|
|
378
272
|
...this._options,
|
|
379
|
-
defaultLanguage:
|
|
273
|
+
defaultLanguage: this._options.defaultLanguage === language ? resolveDefaultLanguageOption(newAvailableLanguages, this._options.availableLanguages) : this._options.defaultLanguage
|
|
380
274
|
}, newAvailableLanguages);
|
|
381
275
|
}
|
|
382
276
|
/**
|
|
383
|
-
* Get the string representation
|
|
277
|
+
* Get the string representation, using the default language
|
|
384
278
|
*/
|
|
385
279
|
toString() {
|
|
386
280
|
return this.getText();
|
|
387
281
|
}
|
|
388
282
|
/**
|
|
389
|
-
* Get JSON representation
|
|
283
|
+
* Get the JSON representation
|
|
284
|
+
*
|
|
285
|
+
* Carries `defaultLanguage`, because it is not derivable from the content:
|
|
286
|
+
* without it {@link MultilingualString.fromJSON} would fall back to the first
|
|
287
|
+
* available language and `getText()` would resolve differently.
|
|
390
288
|
*/
|
|
391
289
|
toJSON() {
|
|
392
290
|
const content = {};
|
|
393
291
|
for (const language of this._availableLanguages) content[language] = this.getExactEntries(language);
|
|
394
292
|
return {
|
|
395
293
|
content,
|
|
396
|
-
aliases: this.getAliases()
|
|
294
|
+
aliases: this.getAliases(),
|
|
295
|
+
defaultLanguage: this._options.defaultLanguage
|
|
397
296
|
};
|
|
398
297
|
}
|
|
399
298
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/parsers/property-token.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The attributes a property value can carry its text in
|
|
4
|
+
*/
|
|
5
|
+
type PropertyValueTextSource = {
|
|
6
|
+
rawValue?: string;
|
|
7
|
+
payload?: string;
|
|
8
|
+
slug?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The text a property value stands for
|
|
12
|
+
*
|
|
13
|
+
* OCHRE spreads that text over four places, so which one wins is real domain
|
|
14
|
+
* knowledge and this is the only place it is written down. The content step is
|
|
15
|
+
* injected because the two callers reach it differently: the item parser builds
|
|
16
|
+
* a full multilingual string, while the rich-text parser needs one language's
|
|
17
|
+
* plain text. Reading the sources in a different order is what let the two
|
|
18
|
+
* disagree for a value carrying both a `slug` and `content`.
|
|
19
|
+
* @param value - The raw property value
|
|
20
|
+
* @param readContentText - Reads the value's `content` as plain text, or null when it has none
|
|
21
|
+
* @returns The text, or an empty string when the value carries none
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare function readPropertyValueText(value: PropertyValueTextSource, readContentText: () => string | null): string;
|
|
25
|
+
/**
|
|
26
|
+
* The UUID a property value points at, treating an empty attribute as absent
|
|
27
|
+
* @param value - The raw property value
|
|
28
|
+
* @returns The UUID, or null when there is none
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
31
|
+
export declare function readPropertyValueUuid(value: {
|
|
32
|
+
uuid?: string;
|
|
33
|
+
} | undefined): string | null;
|
|
34
|
+
//#endregion
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region src/parsers/property-token.ts
|
|
2
|
+
/**
|
|
3
|
+
* The text a property value stands for
|
|
4
|
+
*
|
|
5
|
+
* OCHRE spreads that text over four places, so which one wins is real domain
|
|
6
|
+
* knowledge and this is the only place it is written down. The content step is
|
|
7
|
+
* injected because the two callers reach it differently: the item parser builds
|
|
8
|
+
* a full multilingual string, while the rich-text parser needs one language's
|
|
9
|
+
* plain text. Reading the sources in a different order is what let the two
|
|
10
|
+
* disagree for a value carrying both a `slug` and `content`.
|
|
11
|
+
* @param value - The raw property value
|
|
12
|
+
* @param readContentText - Reads the value's `content` as plain text, or null when it has none
|
|
13
|
+
* @returns The text, or an empty string when the value carries none
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
function readPropertyValueText(value, readContentText) {
|
|
17
|
+
return value.rawValue ?? value.payload ?? readContentText() ?? value.slug ?? "";
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The UUID a property value points at, treating an empty attribute as absent
|
|
21
|
+
* @param value - The raw property value
|
|
22
|
+
* @returns The UUID, or null when there is none
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
function readPropertyValueUuid(value) {
|
|
26
|
+
return value?.uuid == null || value.uuid === "" ? null : value.uuid;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { readPropertyValueText, readPropertyValueUuid };
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
import { MultilingualString, MultilingualStringText } from "./multilingual.mjs";
|
|
2
2
|
import { XMLContent, XMLString } from "../xml/types.mjs";
|
|
3
3
|
//#region src/parsers/string.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Rewrite a permanent identification URL as an OCHRE API endpoint
|
|
6
|
+
*
|
|
7
|
+
* The counterpart of {@link transformPermanentIdentificationUrlToItemLink}:
|
|
8
|
+
* the same prefix becomes an API call here and a route into a consuming
|
|
9
|
+
* website there, so which one a caller wants depends on who reads the result.
|
|
10
|
+
* @param url - The permanent identification URL
|
|
11
|
+
* @returns The API URL
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
4
14
|
export declare function transformPermanentIdentificationUrl(url: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Rewrite a permanent identification URL as a website item route
|
|
17
|
+
* @param url - The permanent identification URL
|
|
18
|
+
* @returns The item route
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export declare function transformPermanentIdentificationUrlToItemLink(url: string): string;
|
|
5
22
|
export declare function parseXMLString(string: XMLString): MultilingualStringText;
|
|
6
23
|
/**
|
|
7
24
|
* Parses rich text content into a formatted string with links and annotations
|
|
@@ -9,12 +26,14 @@ export declare function parseXMLString(string: XMLString): MultilingualStringTex
|
|
|
9
26
|
* @param item - XML-based rich text item to parse
|
|
10
27
|
* @param options - Options for parsing
|
|
11
28
|
* @param options.languages - Languages of the content
|
|
29
|
+
* @param options.defaultLanguage - The language the dataset declares as its default
|
|
12
30
|
* @returns Plain and rich formatted strings
|
|
13
31
|
*
|
|
14
32
|
* @internal
|
|
15
33
|
*/
|
|
16
34
|
export declare function parseXMLContent<V extends ReadonlyArray<string>>(item: XMLContent, options: {
|
|
17
35
|
languages: V;
|
|
36
|
+
defaultLanguage?: V[number];
|
|
18
37
|
}): MultilingualString<V>;
|
|
19
38
|
/**
|
|
20
39
|
* Extracts alias strings from XMLContent where lang="zxx"
|
package/dist/parsers/string.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { TEXT_ANNOTATION_UUID } from "../constants.mjs";
|
|
1
|
+
import { OCHRE_ENDPOINT, PERMANENT_IDENTIFICATION_URL_PREFIX, TEXT_ANNOTATION_UUID, getOchreItemUrl } from "../constants.mjs";
|
|
2
|
+
import { normalizePropertyVariableLabel } from "../getters.mjs";
|
|
3
|
+
import { getXMLSourceIndex } from "../xml/metadata.mjs";
|
|
2
4
|
import { serializeMDXContent, serializeMDXText } from "./mdx.mjs";
|
|
3
5
|
import { MultilingualString } from "./multilingual.mjs";
|
|
6
|
+
import { readPropertyValueText, readPropertyValueUuid } from "./property-token.mjs";
|
|
4
7
|
import { renderOptionsSchema } from "../schemas.mjs";
|
|
5
|
-
import { getXMLSourceIndex } from "../xml/metadata.mjs";
|
|
6
8
|
import * as v from "valibot";
|
|
7
9
|
//#region src/parsers/string.ts
|
|
8
10
|
const TEXT_ANNOTATION_TOKEN = "text-annotation";
|
|
@@ -21,9 +23,6 @@ const MDX_RENDER_ELEMENTS = {
|
|
|
21
23
|
italic: "em",
|
|
22
24
|
underline: "u"
|
|
23
25
|
};
|
|
24
|
-
function isXMLRichTextLink(value) {
|
|
25
|
-
return typeof value === "object" && value != null;
|
|
26
|
-
}
|
|
27
26
|
function getLinkStringProperty(link, property) {
|
|
28
27
|
switch (property) {
|
|
29
28
|
case "uuid": return "uuid" in link && typeof link.uuid === "string" ? link.uuid : null;
|
|
@@ -32,8 +31,27 @@ function getLinkStringProperty(link, property) {
|
|
|
32
31
|
case "width": return "width" in link && link.width != null ? link.width.toString() : null;
|
|
33
32
|
}
|
|
34
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Rewrite a permanent identification URL as an OCHRE API endpoint
|
|
36
|
+
*
|
|
37
|
+
* The counterpart of {@link transformPermanentIdentificationUrlToItemLink}:
|
|
38
|
+
* the same prefix becomes an API call here and a route into a consuming
|
|
39
|
+
* website there, so which one a caller wants depends on who reads the result.
|
|
40
|
+
* @param url - The permanent identification URL
|
|
41
|
+
* @returns The API URL
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
35
44
|
function transformPermanentIdentificationUrl(url) {
|
|
36
|
-
return url.replace(
|
|
45
|
+
return url.replace(PERMANENT_IDENTIFICATION_URL_PREFIX, () => `${OCHRE_ENDPOINT}?uuid=`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Rewrite a permanent identification URL as a website item route
|
|
49
|
+
* @param url - The permanent identification URL
|
|
50
|
+
* @returns The item route
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
function transformPermanentIdentificationUrlToItemLink(url) {
|
|
54
|
+
return url.replace(PERMANENT_IDENTIFICATION_URL_PREFIX, "/item/");
|
|
37
55
|
}
|
|
38
56
|
/**
|
|
39
57
|
* Applies text rendering options (bold, italic, underline) to a string
|
|
@@ -126,7 +144,7 @@ function createMDXComponent(variant, properties) {
|
|
|
126
144
|
returnString = `<ExternalLink${createMDXStringAttribute("href", href == null ? "#" : transformPermanentIdentificationUrl(href))}>${text}</ExternalLink>`;
|
|
127
145
|
break;
|
|
128
146
|
case "documentLink":
|
|
129
|
-
returnString = `<ExternalLink${createMDXStringAttribute("href",
|
|
147
|
+
returnString = `<ExternalLink${createMDXStringAttribute("href", getOchreItemUrl(uuid ?? "null", "load"))}>${text}</ExternalLink>`;
|
|
130
148
|
break;
|
|
131
149
|
case "tooltipSpan": returnString = `<TooltipSpan${createMDXStringAttribute("content", content)}>${text}</TooltipSpan>`;
|
|
132
150
|
}
|
|
@@ -137,8 +155,7 @@ function createMDXStringAttribute(name, value) {
|
|
|
137
155
|
return ` ${name}=${MDX_QUOTED_ATTRIBUTE_ESCAPE_REGEX.test(value) ? `{${JSON.stringify(value)}}` : `"${value}"`}`;
|
|
138
156
|
}
|
|
139
157
|
function getPropertyValueUuid(property) {
|
|
140
|
-
|
|
141
|
-
return value?.uuid == null || value.uuid === "" ? null : value.uuid;
|
|
158
|
+
return readPropertyValueUuid(property?.value?.[0]);
|
|
142
159
|
}
|
|
143
160
|
function getFirstPropertyMetadata(item) {
|
|
144
161
|
const itemProperty = item.properties?.property[0];
|
|
@@ -159,23 +176,16 @@ function parseContentLikeForLanguage(value, options) {
|
|
|
159
176
|
function parsePropertyValueText(property, options) {
|
|
160
177
|
const value = property?.value?.[0];
|
|
161
178
|
if (value == null) return "";
|
|
162
|
-
|
|
163
|
-
if (value.payload != null) return value.payload;
|
|
164
|
-
if (value.slug != null) return value.slug;
|
|
165
|
-
if (value.content != null) return parseContentLikeForLanguage(value, options);
|
|
166
|
-
return "";
|
|
167
|
-
}
|
|
168
|
-
function normalizePropertyToken(value) {
|
|
169
|
-
return value.trim().toLowerCase().replaceAll(/[\s_]+/g, "-");
|
|
179
|
+
return readPropertyValueText(value, () => value.content == null ? null : parseContentLikeForLanguage(value, options));
|
|
170
180
|
}
|
|
171
181
|
function hasMatchingPropertyLabel(property, uuid, tokens, options) {
|
|
172
182
|
if (uuid !== "" && property.label.uuid === uuid) return true;
|
|
173
|
-
const label =
|
|
183
|
+
const label = normalizePropertyVariableLabel(parseContentLikeForLanguage(property.label, options));
|
|
174
184
|
return tokens.includes(label);
|
|
175
185
|
}
|
|
176
186
|
function hasMatchingPropertyValue(property, uuid, tokens, options) {
|
|
177
187
|
if (uuid !== "" && getPropertyValueUuid(property) === uuid) return true;
|
|
178
|
-
const value =
|
|
188
|
+
const value = normalizePropertyVariableLabel(parsePropertyValueText(property, options));
|
|
179
189
|
return tokens.includes(value);
|
|
180
190
|
}
|
|
181
191
|
function parseTextStylingSize(textStylingProperty, options) {
|
|
@@ -336,7 +346,7 @@ function getXMLRichTextLinks(item) {
|
|
|
336
346
|
for (const rawLinks of linkGroups) {
|
|
337
347
|
if (!Array.isArray(rawLinks)) continue;
|
|
338
348
|
for (const rawLink of rawLinks) {
|
|
339
|
-
if (
|
|
349
|
+
if (isTextAnnotationMarkerLink(rawLink)) continue;
|
|
340
350
|
links.push({
|
|
341
351
|
link: rawLink,
|
|
342
352
|
fallbackIndex
|
|
@@ -408,7 +418,7 @@ function renderRichTextItem(item, linkString, contentItem, options) {
|
|
|
408
418
|
let result = "";
|
|
409
419
|
for (const link of links) {
|
|
410
420
|
const linkContent = link.identification != null ? "content" in link.identification.label ? parseXMLContent(link.identification.label, { languages }) : MultilingualString.create(contentItem.lang, parseXMLString(link.identification.label), languages) : MultilingualString.create(contentItem.lang, "", languages);
|
|
411
|
-
const contentText =
|
|
421
|
+
const contentText = rendering === "plain" ? linkContent.getExactText(contentItem.lang) : linkContent.getExactRichText(contentItem.lang);
|
|
412
422
|
result += renderRichTextLink(item, link, linkString, contentText, annotationMetadata);
|
|
413
423
|
}
|
|
414
424
|
return applyNewlineWhitespace(result, item.whitespace, rendering);
|
|
@@ -419,6 +429,7 @@ function renderRichTextItem(item, linkString, contentItem, options) {
|
|
|
419
429
|
* @param item - XML-based rich text item to parse
|
|
420
430
|
* @param options - Options for parsing
|
|
421
431
|
* @param options.languages - Languages of the content
|
|
432
|
+
* @param options.defaultLanguage - The language the dataset declares as its default
|
|
422
433
|
* @returns Plain and rich formatted strings
|
|
423
434
|
*
|
|
424
435
|
* @internal
|
|
@@ -434,15 +445,24 @@ function parseXMLContent(item, options) {
|
|
|
434
445
|
entries.push(parseXMLContentItem(contentItem, { languages }));
|
|
435
446
|
content[language] = entries;
|
|
436
447
|
}
|
|
437
|
-
if (Object.keys(content).length > 0) return MultilingualString.fromEntries(content, languages, {
|
|
448
|
+
if (Object.keys(content).length > 0) return MultilingualString.fromEntries(content, languages, {
|
|
449
|
+
aliases,
|
|
450
|
+
defaultLanguage: options.defaultLanguage
|
|
451
|
+
});
|
|
438
452
|
for (const contentItem of item.content) {
|
|
439
453
|
if (contentItem.lang === "zxx") continue;
|
|
440
454
|
const fallbackText = parseXMLContentItem(contentItem, { languages: [contentItem.lang] });
|
|
441
455
|
const fallbackContent = {};
|
|
442
456
|
for (const language of languages) fallbackContent[language] = [fallbackText];
|
|
443
|
-
return MultilingualString.fromEntries(fallbackContent, languages, {
|
|
457
|
+
return MultilingualString.fromEntries(fallbackContent, languages, {
|
|
458
|
+
aliases,
|
|
459
|
+
defaultLanguage: options.defaultLanguage
|
|
460
|
+
});
|
|
444
461
|
}
|
|
445
|
-
return MultilingualString.empty(languages, {
|
|
462
|
+
return MultilingualString.empty(languages, {
|
|
463
|
+
aliases,
|
|
464
|
+
defaultLanguage: options.defaultLanguage
|
|
465
|
+
});
|
|
446
466
|
}
|
|
447
467
|
function parseXMLContentItem(contentItem, options) {
|
|
448
468
|
const rawMDXBlocks = [];
|
|
@@ -483,4 +503,4 @@ function extractAliases(content) {
|
|
|
483
503
|
return aliases.length > 0 ? aliases : null;
|
|
484
504
|
}
|
|
485
505
|
//#endregion
|
|
486
|
-
export { extractAliases, parseXMLContent, parseXMLString, transformPermanentIdentificationUrl };
|
|
506
|
+
export { extractAliases, parseXMLContent, parseXMLString, transformPermanentIdentificationUrl, transformPermanentIdentificationUrlToItemLink };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/parsers/website/bounds.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Parses raw bounds data into a standardized bounds structure
|
|
4
|
+
*
|
|
5
|
+
* @param bounds - Raw bounds data in OCHRE format
|
|
6
|
+
* @returns Parsed bounds object
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseBounds(bounds: string): [[number, number], [number, number]];
|
|
10
|
+
//#endregion
|