ochre-sdk 1.0.13 → 1.0.15
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/dist/constants.d.mts +17 -0
- package/dist/constants.mjs +85 -0
- package/dist/fetchers/gallery.d.mts +38 -0
- package/dist/fetchers/gallery.mjs +91 -0
- package/dist/fetchers/item-links.d.mts +32 -0
- package/dist/fetchers/item-links.mjs +120 -0
- package/dist/fetchers/item.d.mts +74 -0
- package/dist/fetchers/item.mjs +146 -0
- package/dist/fetchers/set/items.d.mts +48 -0
- package/dist/fetchers/set/items.mjs +268 -0
- package/dist/fetchers/set/property-values.d.mts +46 -0
- package/dist/fetchers/set/property-values.mjs +514 -0
- package/dist/fetchers/website.d.mts +25 -0
- package/dist/fetchers/website.mjs +38 -0
- package/dist/getters.d.mts +193 -0
- package/dist/getters.mjs +341 -0
- package/dist/helpers.d.mts +18 -0
- package/dist/helpers.mjs +33 -0
- package/dist/index.d.mts +12 -1971
- package/dist/index.mjs +9 -7236
- package/dist/parsers/helpers.d.mts +27 -0
- package/dist/parsers/helpers.mjs +53 -0
- package/dist/parsers/index.d.mts +65 -0
- package/dist/parsers/index.mjs +1338 -0
- package/dist/parsers/mdx.d.mts +4 -0
- package/dist/parsers/mdx.mjs +9 -0
- package/dist/parsers/multilingual.d.mts +189 -0
- package/dist/parsers/multilingual.mjs +410 -0
- package/dist/parsers/string.d.mts +29 -0
- package/dist/parsers/string.mjs +445 -0
- package/dist/parsers/website/index.d.mts +20 -0
- package/dist/parsers/website/index.mjs +1245 -0
- package/dist/parsers/website/reader.d.mts +29 -0
- package/dist/parsers/website/reader.mjs +75 -0
- package/dist/query.d.mts +13 -0
- package/dist/query.mjs +827 -0
- package/dist/schemas.d.mts +79 -0
- package/dist/schemas.mjs +223 -0
- package/dist/types/index.d.mts +840 -0
- package/dist/types/index.mjs +1 -0
- package/dist/types/website.d.mts +501 -0
- package/dist/types/website.mjs +1 -0
- package/dist/utils.d.mts +34 -0
- package/dist/utils.mjs +172 -0
- package/dist/xml/metadata.d.mts +5 -0
- package/dist/xml/metadata.mjs +30 -0
- package/dist/xml/schemas.d.mts +13 -0
- package/dist/xml/schemas.mjs +849 -0
- package/dist/xml/types.d.mts +901 -0
- package/dist/xml/types.mjs +1 -0
- package/package.json +19 -17
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import { TEXT_ANNOTATION_UUID } from "../constants.mjs";
|
|
2
|
+
import { serializeMDXText } from "./mdx.mjs";
|
|
3
|
+
import { MultilingualString } from "./multilingual.mjs";
|
|
4
|
+
import { renderOptionsSchema } from "../schemas.mjs";
|
|
5
|
+
import { getXMLSourceIndex } from "../xml/metadata.mjs";
|
|
6
|
+
import * as v from "valibot";
|
|
7
|
+
//#region src/parsers/string.ts
|
|
8
|
+
const TEXT_ANNOTATION_TOKEN = "text-annotation";
|
|
9
|
+
const TEXT_STYLING_TOKEN = "text-styling";
|
|
10
|
+
const HOVER_CARD_TOKEN = "hover-card";
|
|
11
|
+
const ITEM_PAGE_TOKEN = "item-page";
|
|
12
|
+
const ENTRY_PAGE_TOKEN = "entry-page";
|
|
13
|
+
const VARIANT_TOKEN = "variant";
|
|
14
|
+
const HEADING_LEVEL_TOKEN = "heading-level";
|
|
15
|
+
const MDX_QUOTED_ATTRIBUTE_ESCAPE_REGEX = /[\n\r"]/;
|
|
16
|
+
const MDX_RENDER_ELEMENTS = {
|
|
17
|
+
bold: "strong",
|
|
18
|
+
italic: "em",
|
|
19
|
+
underline: "u"
|
|
20
|
+
};
|
|
21
|
+
function isXMLRichTextLink(value) {
|
|
22
|
+
return typeof value === "object" && value != null;
|
|
23
|
+
}
|
|
24
|
+
function getLinkStringProperty(link, property) {
|
|
25
|
+
switch (property) {
|
|
26
|
+
case "uuid": return "uuid" in link && typeof link.uuid === "string" ? link.uuid : null;
|
|
27
|
+
case "href": return "href" in link && typeof link.href === "string" ? link.href : null;
|
|
28
|
+
case "height": return "height" in link && link.height != null ? link.height.toString() : null;
|
|
29
|
+
case "width": return "width" in link && link.width != null ? link.width.toString() : null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function transformPermanentIdentificationUrl(url) {
|
|
33
|
+
return url.replace("https://pi.lib.uchicago.edu/1001/org/ochre/", "https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?uuid=");
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Applies text rendering options (bold, italic, underline) to a string
|
|
37
|
+
*
|
|
38
|
+
* @param contentString - The string content to render
|
|
39
|
+
* @param renderString - Space-separated string of render options
|
|
40
|
+
* @param rendering - Which text rendering to produce
|
|
41
|
+
* @returns String with rich-text formatting applied
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
function parseRenderOptions(contentString, renderString, rendering) {
|
|
45
|
+
const { success, output } = v.safeParse(renderOptionsSchema, renderString);
|
|
46
|
+
if (!success) return contentString;
|
|
47
|
+
if (rendering !== "rich") return contentString.replaceAll("'", "'");
|
|
48
|
+
return applyRichRenderOptions(contentString, output).replaceAll("'", "'");
|
|
49
|
+
}
|
|
50
|
+
function applyRichRenderOptions(contentString, options) {
|
|
51
|
+
const withoutLeadingWhitespace = contentString.trimStart();
|
|
52
|
+
const leadingWhitespace = contentString.slice(0, contentString.length - withoutLeadingWhitespace.length);
|
|
53
|
+
const renderableContent = withoutLeadingWhitespace.trimEnd();
|
|
54
|
+
const trailingWhitespace = withoutLeadingWhitespace.slice(renderableContent.length);
|
|
55
|
+
if (renderableContent === "") return contentString;
|
|
56
|
+
return `${leadingWhitespace}${applyMDXRenderElements(renderableContent, options)}${trailingWhitespace}`;
|
|
57
|
+
}
|
|
58
|
+
function applyMDXRenderElements(contentString, options) {
|
|
59
|
+
let result = contentString;
|
|
60
|
+
for (const option of options) {
|
|
61
|
+
const element = MDX_RENDER_ELEMENTS[option];
|
|
62
|
+
result = `<${element}>${result}</${element}>`;
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parses XML string into a formatted string with rendering options
|
|
68
|
+
*
|
|
69
|
+
* @param string - XML string to parse
|
|
70
|
+
* @param options - Options for parsing
|
|
71
|
+
* @param options.rendering - Which text rendering to produce
|
|
72
|
+
* @returns Formatted string with rendering options
|
|
73
|
+
*
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
function parseXMLStringVariant(string, options) {
|
|
77
|
+
let returnString = parseXMLStringPayload(string, options);
|
|
78
|
+
if (string.rend != null) returnString = parseRenderOptions(returnString, string.rend, options.rendering);
|
|
79
|
+
return returnString;
|
|
80
|
+
}
|
|
81
|
+
function parseXMLStringPayload(string, options) {
|
|
82
|
+
const payload = string.payload ?? "";
|
|
83
|
+
return options.rendering === "rich" ? serializeMDXText(payload) : payload;
|
|
84
|
+
}
|
|
85
|
+
function parseXMLString(string) {
|
|
86
|
+
return {
|
|
87
|
+
text: parseXMLStringVariant(string, { rendering: "plain" }),
|
|
88
|
+
richText: parseXMLStringVariant(string, { rendering: "rich" })
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Creates an MDX component based on the variant
|
|
93
|
+
*
|
|
94
|
+
* @param variant - The variant of the component
|
|
95
|
+
* @param properties - The properties of the component
|
|
96
|
+
* @param properties.uuid - The UUID of the component
|
|
97
|
+
* @param properties.href - The href of the component
|
|
98
|
+
* @param properties.height - The height of the component
|
|
99
|
+
* @param properties.width - The width of the component
|
|
100
|
+
* @param properties.content - The content of the component
|
|
101
|
+
* @param properties.text - The text of the component
|
|
102
|
+
* @returns The MDX component as a string
|
|
103
|
+
*
|
|
104
|
+
* @internal
|
|
105
|
+
*/
|
|
106
|
+
function createMDXComponent(variant, properties) {
|
|
107
|
+
const { uuid, href, height, width, content, text } = properties;
|
|
108
|
+
const tooltipContent = getDistinctTooltipContent(content, text);
|
|
109
|
+
let returnString = "";
|
|
110
|
+
switch (variant) {
|
|
111
|
+
case "inlineImage":
|
|
112
|
+
returnString = `<InlineImage${createMDXStringAttribute("uuid", uuid ?? "null")}${createMDXStringAttribute("content", content)} height={${height ?? "null"}} width={${width ?? "null"}} />`;
|
|
113
|
+
break;
|
|
114
|
+
case "internalLink":
|
|
115
|
+
returnString = `<InternalLink${createMDXStringAttribute("uuid", uuid ?? "null")}${createMDXStringAttribute("content", tooltipContent)}>${text}</InternalLink>`;
|
|
116
|
+
break;
|
|
117
|
+
case "externalLink":
|
|
118
|
+
returnString = `<ExternalLink${createMDXStringAttribute("href", href == null ? "#" : transformPermanentIdentificationUrl(href))}${createMDXStringAttribute("content", tooltipContent)}>${text}</ExternalLink>`;
|
|
119
|
+
break;
|
|
120
|
+
case "documentLink":
|
|
121
|
+
returnString = `<ExternalLink${createMDXStringAttribute("href", `https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?uuid=${uuid}&load`)}${createMDXStringAttribute("content", tooltipContent)}>${text}</ExternalLink>`;
|
|
122
|
+
break;
|
|
123
|
+
case "tooltipSpan":
|
|
124
|
+
returnString = `<TooltipSpan${createMDXStringAttribute("content", content)}>${text}</TooltipSpan>`;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
return returnString;
|
|
128
|
+
}
|
|
129
|
+
function getDistinctTooltipContent(content, textContent) {
|
|
130
|
+
return content === textContent ? void 0 : content;
|
|
131
|
+
}
|
|
132
|
+
function createMDXStringAttribute(name, value) {
|
|
133
|
+
if (value == null || value === "") return "";
|
|
134
|
+
return ` ${name}=${MDX_QUOTED_ATTRIBUTE_ESCAPE_REGEX.test(value) ? `{${JSON.stringify(value)}}` : `"${value}"`}`;
|
|
135
|
+
}
|
|
136
|
+
function getPropertyValueUuid(property) {
|
|
137
|
+
const value = property?.value?.[0];
|
|
138
|
+
return value?.uuid == null || value.uuid === "" ? null : value.uuid;
|
|
139
|
+
}
|
|
140
|
+
function getFirstPropertyMetadata(item) {
|
|
141
|
+
const itemProperty = item.properties?.property[0];
|
|
142
|
+
if (itemProperty == null) return null;
|
|
143
|
+
return {
|
|
144
|
+
labelUuid: itemProperty.label.uuid,
|
|
145
|
+
valueUuid: getPropertyValueUuid(itemProperty)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function parseContentLikeForLanguage(value, options) {
|
|
149
|
+
if (value == null) return "";
|
|
150
|
+
if (!("content" in value)) return parseXMLString(value).text;
|
|
151
|
+
const contentItem = value.content.find((item) => item.lang === options.language) ?? value.content[0];
|
|
152
|
+
if (contentItem == null) return "";
|
|
153
|
+
const languages = [contentItem.lang];
|
|
154
|
+
return parseXMLContent({ content: [contentItem] }, { languages }).getText(contentItem.lang);
|
|
155
|
+
}
|
|
156
|
+
function parsePropertyValueText(property, options) {
|
|
157
|
+
const value = property?.value?.[0];
|
|
158
|
+
if (value == null) return "";
|
|
159
|
+
if (value.rawValue != null) return value.rawValue;
|
|
160
|
+
if (value.payload != null) return value.payload;
|
|
161
|
+
if (value.slug != null) return value.slug;
|
|
162
|
+
if (value.content != null) return parseContentLikeForLanguage(value, options);
|
|
163
|
+
return "";
|
|
164
|
+
}
|
|
165
|
+
function normalizePropertyToken(value) {
|
|
166
|
+
return value.trim().toLowerCase().replaceAll(/[\s_]+/g, "-");
|
|
167
|
+
}
|
|
168
|
+
function propertyLabelMatches(property, uuid, tokens, options) {
|
|
169
|
+
if (uuid !== "" && property.label.uuid === uuid) return true;
|
|
170
|
+
const label = normalizePropertyToken(parseContentLikeForLanguage(property.label, options));
|
|
171
|
+
return tokens.includes(label);
|
|
172
|
+
}
|
|
173
|
+
function propertyValueMatches(property, uuid, tokens, options) {
|
|
174
|
+
if (uuid !== "" && getPropertyValueUuid(property) === uuid) return true;
|
|
175
|
+
const value = normalizePropertyToken(parsePropertyValueText(property, options));
|
|
176
|
+
return tokens.includes(value);
|
|
177
|
+
}
|
|
178
|
+
function extractAnnotationMetadata(item, options) {
|
|
179
|
+
const result = {
|
|
180
|
+
linkVariant: null,
|
|
181
|
+
textStyling: null
|
|
182
|
+
};
|
|
183
|
+
const itemProperty = item.properties?.property[0];
|
|
184
|
+
if (itemProperty == null) return result;
|
|
185
|
+
if (!propertyLabelMatches(itemProperty, "f1c131b6-1498-48a4-95bf-a9edae9fd518", ["presentation"], options) || !propertyValueMatches(itemProperty, "b9ca2732-78f4-416e-b77f-dae7647e68a9", [TEXT_ANNOTATION_TOKEN], options)) return result;
|
|
186
|
+
for (const textAnnotationProperty of itemProperty.property ?? []) {
|
|
187
|
+
if (propertyValueMatches(textAnnotationProperty, "c7f6a08a-f07b-49b6-bcb1-af485da3c58f", [HOVER_CARD_TOKEN], options)) {
|
|
188
|
+
result.linkVariant = "hover-card";
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
if (propertyValueMatches(textAnnotationProperty, "bf4476ab-6bc8-40d0-a001-1446213c72ce", [ITEM_PAGE_TOKEN], options)) {
|
|
192
|
+
result.linkVariant = "item-page";
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (propertyValueMatches(textAnnotationProperty, "9d52db95-a9cf-45f7-a0bf-fc9ba9f0aae0", [ENTRY_PAGE_TOKEN], options)) {
|
|
196
|
+
result.linkVariant = "entry-page";
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (propertyValueMatches(textAnnotationProperty, "3e6f86ab-df81-45ae-8257-e2867357df56", [TEXT_STYLING_TOKEN], options)) {
|
|
200
|
+
let variant = "block";
|
|
201
|
+
let size = "md";
|
|
202
|
+
let headingLevel = null;
|
|
203
|
+
const cssStyles = [];
|
|
204
|
+
const textStylingProperties = textAnnotationProperty.property ?? [];
|
|
205
|
+
for (const textStylingProperty of textStylingProperties) {
|
|
206
|
+
if (propertyLabelMatches(textStylingProperty, "e1647bef-d801-4100-bdde-d081c422f763", [VARIANT_TOKEN], options)) {
|
|
207
|
+
variant = parsePropertyValueText(textStylingProperty, options);
|
|
208
|
+
for (const nestedProperty of textStylingProperty.property ?? []) if (propertyLabelMatches(nestedProperty, "", ["size"], options)) size = parsePropertyValueText(nestedProperty, options);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (propertyLabelMatches(textStylingProperty, "d4266f0b-3f8d-4b32-8c15-4b229c8bb11e", [HEADING_LEVEL_TOKEN], options)) {
|
|
212
|
+
headingLevel = parsePropertyValueText(textStylingProperty, options);
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
cssStyles.push({
|
|
216
|
+
label: parseContentLikeForLanguage(textStylingProperty.label, options),
|
|
217
|
+
value: parsePropertyValueText(textStylingProperty, options)
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
result.textStyling = {
|
|
221
|
+
variant,
|
|
222
|
+
size,
|
|
223
|
+
headingLevel,
|
|
224
|
+
cssStyles
|
|
225
|
+
};
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
function hasRichTextEnvelope(item) {
|
|
232
|
+
return item.properties?.property[0] != null || getXMLRichTextLinks(item).length > 0;
|
|
233
|
+
}
|
|
234
|
+
function parseXMLStringItem(item, contentItem, options) {
|
|
235
|
+
if (!(item.payload != null || item.string != null) && getXMLRichTextLinks(item).length === 0) return "";
|
|
236
|
+
if (hasRichTextEnvelope(item)) {
|
|
237
|
+
let linkString = item.payload != null ? parseXMLStringPayload(item, { rendering: options.rendering }) : parseNestedStringItems(item.string ?? [], contentItem, { ...options });
|
|
238
|
+
if (item.rend != null) linkString = parseRenderOptions(linkString, item.rend, options.rendering);
|
|
239
|
+
if (options.rendering === "plain") return linkString;
|
|
240
|
+
return renderRichTextItem(item, linkString, contentItem, options);
|
|
241
|
+
}
|
|
242
|
+
if (item.payload != null) return parseXMLStringVariant(item, { rendering: options.rendering });
|
|
243
|
+
let result = parseNestedStringItems(item.string ?? [], contentItem, options);
|
|
244
|
+
if (item.rend != null) result = parseRenderOptions(result, item.rend, options.rendering);
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
function parseNestedStringItems(items, contentItem, options) {
|
|
248
|
+
let result = "";
|
|
249
|
+
for (const item of items) result += parseXMLStringItem(item, contentItem, options);
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
function isTextAnnotationMarkerLink(link) {
|
|
253
|
+
return getLinkStringProperty(link, "uuid") === TEXT_ANNOTATION_UUID;
|
|
254
|
+
}
|
|
255
|
+
function wrapWithTextStyling(content, textStyling) {
|
|
256
|
+
if (textStyling == null) return content;
|
|
257
|
+
return `<Annotation type="text-styling"${createMDXStringAttribute("variant", textStyling.variant)}${createMDXStringAttribute("size", textStyling.size)}${createMDXStringAttribute("headingLevel", textStyling.headingLevel ?? void 0)}${textStyling.cssStyles.length > 0 ? ` cssStyles={{default: ${JSON.stringify(textStyling.cssStyles)}, tablet: [], mobile: []}}` : ""}>${content}</Annotation>`;
|
|
258
|
+
}
|
|
259
|
+
function createInternalLinkComponent(properties) {
|
|
260
|
+
const innerContent = wrapWithTextStyling(properties.text, properties.annotationMetadata.textStyling);
|
|
261
|
+
switch (properties.annotationMetadata.linkVariant) {
|
|
262
|
+
case "hover-card": return `<Annotation type="hover-card"${createMDXStringAttribute("uuid", properties.uuid ?? "null")}>${innerContent}</Annotation>`;
|
|
263
|
+
case "item-page": return `<InternalLink type="item"${createMDXStringAttribute("uuid", properties.uuid ?? "null")}>${innerContent}</InternalLink>`;
|
|
264
|
+
case "entry-page": return `<InternalLink type="entry"${createMDXStringAttribute("uuid", properties.uuid ?? "null")}>${innerContent}</InternalLink>`;
|
|
265
|
+
default: return `<InternalLink${createMDXStringAttribute("uuid", properties.uuid ?? "null")}${properties.propertyMetadata != null ? `${createMDXStringAttribute("properties", properties.propertyMetadata.labelUuid)}${createMDXStringAttribute("value", properties.propertyMetadata.valueUuid ?? void 0)}` : ""}${createMDXStringAttribute("content", getDistinctTooltipContent(properties.content, properties.text))}>${innerContent}</InternalLink>`;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function getXMLRichTextLinks(item) {
|
|
269
|
+
const links = [];
|
|
270
|
+
let fallbackIndex = 0;
|
|
271
|
+
for (const rawLinks of Object.values(item.links ?? {})) {
|
|
272
|
+
if (!Array.isArray(rawLinks)) continue;
|
|
273
|
+
for (const rawLink of rawLinks) if (isXMLRichTextLink(rawLink) && !isTextAnnotationMarkerLink(rawLink)) {
|
|
274
|
+
links.push({
|
|
275
|
+
link: rawLink,
|
|
276
|
+
fallbackIndex
|
|
277
|
+
});
|
|
278
|
+
fallbackIndex += 1;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
links.sort((left, right) => {
|
|
282
|
+
const leftIndex = getXMLSourceIndex(left.link);
|
|
283
|
+
const rightIndex = getXMLSourceIndex(right.link);
|
|
284
|
+
if (leftIndex != null && rightIndex != null && leftIndex !== rightIndex) return leftIndex - rightIndex;
|
|
285
|
+
return left.fallbackIndex - right.fallbackIndex;
|
|
286
|
+
});
|
|
287
|
+
const sortedLinks = [];
|
|
288
|
+
for (const { link } of links) sortedLinks.push(link);
|
|
289
|
+
return sortedLinks;
|
|
290
|
+
}
|
|
291
|
+
function renderRichTextItem(item, linkString, contentItem, options) {
|
|
292
|
+
const { languages, rendering } = options;
|
|
293
|
+
const annotationMetadata = extractAnnotationMetadata(item, { language: contentItem.lang });
|
|
294
|
+
const links = getXMLRichTextLinks(item);
|
|
295
|
+
if (links.length === 0) return wrapWithTextStyling(linkString, annotationMetadata.textStyling);
|
|
296
|
+
let result = "";
|
|
297
|
+
for (const link of links) {
|
|
298
|
+
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);
|
|
299
|
+
const contentText = (rendering === "rich" ? linkContent.getExactRichText(contentItem.lang) : linkContent.getExactText(contentItem.lang)) ?? "";
|
|
300
|
+
if ("type" in link && link.type != null) switch (link.type) {
|
|
301
|
+
case "IIIF":
|
|
302
|
+
case "image":
|
|
303
|
+
if ("rend" in link && link.rend === "inline") {
|
|
304
|
+
const component = createMDXComponent("inlineImage", {
|
|
305
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
306
|
+
href: getLinkStringProperty(link, "href") ?? void 0,
|
|
307
|
+
height: getLinkStringProperty(link, "height") ?? void 0,
|
|
308
|
+
width: getLinkStringProperty(link, "width") ?? void 0,
|
|
309
|
+
content: contentText,
|
|
310
|
+
text: linkString
|
|
311
|
+
});
|
|
312
|
+
result += component;
|
|
313
|
+
} else if (link.publicationDateTime != null) {
|
|
314
|
+
const component = createInternalLinkComponent({
|
|
315
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
316
|
+
text: linkString,
|
|
317
|
+
content: contentText,
|
|
318
|
+
annotationMetadata
|
|
319
|
+
});
|
|
320
|
+
result += component;
|
|
321
|
+
} else {
|
|
322
|
+
const component = createMDXComponent("tooltipSpan", {
|
|
323
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
324
|
+
text: linkString,
|
|
325
|
+
content: contentText
|
|
326
|
+
});
|
|
327
|
+
result += component;
|
|
328
|
+
}
|
|
329
|
+
break;
|
|
330
|
+
case "internalDocument": {
|
|
331
|
+
const component = createInternalLinkComponent({
|
|
332
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
333
|
+
text: linkString,
|
|
334
|
+
content: contentText,
|
|
335
|
+
annotationMetadata,
|
|
336
|
+
propertyMetadata: getFirstPropertyMetadata(item)
|
|
337
|
+
});
|
|
338
|
+
result += component;
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
case "externalDocument": {
|
|
342
|
+
const component = link.publicationDateTime != null ? createMDXComponent("documentLink", {
|
|
343
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
344
|
+
text: linkString,
|
|
345
|
+
content: contentText
|
|
346
|
+
}) : createMDXComponent("tooltipSpan", {
|
|
347
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
348
|
+
text: linkString,
|
|
349
|
+
content: contentText
|
|
350
|
+
});
|
|
351
|
+
result += component;
|
|
352
|
+
break;
|
|
353
|
+
}
|
|
354
|
+
case "webpage": {
|
|
355
|
+
const component = createMDXComponent("externalLink", {
|
|
356
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
357
|
+
href: getLinkStringProperty(link, "href") ?? "#",
|
|
358
|
+
text: linkString,
|
|
359
|
+
content: contentText
|
|
360
|
+
});
|
|
361
|
+
result += component;
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (link.publicationDateTime != null) {
|
|
366
|
+
const component = createInternalLinkComponent({
|
|
367
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
368
|
+
text: linkString,
|
|
369
|
+
content: contentText,
|
|
370
|
+
annotationMetadata
|
|
371
|
+
});
|
|
372
|
+
result += component;
|
|
373
|
+
} else {
|
|
374
|
+
const component = createMDXComponent("tooltipSpan", {
|
|
375
|
+
uuid: getLinkStringProperty(link, "uuid"),
|
|
376
|
+
text: linkString,
|
|
377
|
+
content: contentText
|
|
378
|
+
});
|
|
379
|
+
result += component;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return result;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Parses rich text content into a formatted string with links and annotations
|
|
386
|
+
*
|
|
387
|
+
* @param item - XML-based rich text item to parse
|
|
388
|
+
* @param options - Options for parsing
|
|
389
|
+
* @param options.languages - Languages of the content
|
|
390
|
+
* @returns Plain and rich formatted strings
|
|
391
|
+
*
|
|
392
|
+
* @internal
|
|
393
|
+
*/
|
|
394
|
+
function parseXMLContent(item, options) {
|
|
395
|
+
const { languages } = options;
|
|
396
|
+
const aliases = extractAliases(item) ?? [];
|
|
397
|
+
const content = {};
|
|
398
|
+
for (const contentItem of item.content) {
|
|
399
|
+
if (contentItem.lang === "zxx" || !languages.includes(contentItem.lang)) continue;
|
|
400
|
+
const language = contentItem.lang;
|
|
401
|
+
const entries = content[language] ?? [];
|
|
402
|
+
entries.push(parseXMLContentItem(contentItem, { languages }));
|
|
403
|
+
content[language] = entries;
|
|
404
|
+
}
|
|
405
|
+
if (Object.keys(content).length > 0) return MultilingualString.fromEntries(content, languages, { aliases });
|
|
406
|
+
for (const contentItem of item.content) {
|
|
407
|
+
if (contentItem.lang === "zxx") continue;
|
|
408
|
+
const fallbackText = parseXMLContentItem(contentItem, { languages: [contentItem.lang] });
|
|
409
|
+
const fallbackContent = {};
|
|
410
|
+
for (const language of languages) fallbackContent[language] = [fallbackText];
|
|
411
|
+
return MultilingualString.fromEntries(fallbackContent, languages, { aliases });
|
|
412
|
+
}
|
|
413
|
+
return MultilingualString.empty(languages, { aliases });
|
|
414
|
+
}
|
|
415
|
+
function parseXMLContentItem(contentItem, options) {
|
|
416
|
+
return {
|
|
417
|
+
text: parseNestedStringItems(contentItem.string, contentItem, {
|
|
418
|
+
...options,
|
|
419
|
+
rendering: "plain"
|
|
420
|
+
}),
|
|
421
|
+
richText: parseNestedStringItems(contentItem.string, contentItem, {
|
|
422
|
+
...options,
|
|
423
|
+
rendering: "rich"
|
|
424
|
+
})
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Extracts alias strings from XMLContent where lang="zxx"
|
|
429
|
+
* @param content - The XMLContent to extract aliases from
|
|
430
|
+
* @returns Array of alias strings, or null if none found
|
|
431
|
+
*
|
|
432
|
+
* @internal
|
|
433
|
+
*/
|
|
434
|
+
function extractAliases(content) {
|
|
435
|
+
if (content == null) return null;
|
|
436
|
+
const aliases = [];
|
|
437
|
+
for (const contentItem of content.content) {
|
|
438
|
+
if (contentItem.lang !== "zxx") continue;
|
|
439
|
+
const alias = parseXMLContentItem(contentItem, { languages: ["zxx"] }).text;
|
|
440
|
+
if (alias !== "") aliases.push(alias);
|
|
441
|
+
}
|
|
442
|
+
return aliases.length > 0 ? aliases : null;
|
|
443
|
+
}
|
|
444
|
+
//#endregion
|
|
445
|
+
export { extractAliases, parseXMLContent, parseXMLString, transformPermanentIdentificationUrl };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Webpage, Website } from "../../types/website.mjs";
|
|
2
|
+
import { XMLWebsiteData, XMLWebsiteResource } from "../../xml/types.mjs";
|
|
3
|
+
import { ParserOptions } from "../helpers.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/parsers/website/index.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Parses raw bounds data into a standardized bounds structure
|
|
8
|
+
*
|
|
9
|
+
* @param bounds - Raw bounds data in OCHRE format
|
|
10
|
+
* @returns Parsed bounds object
|
|
11
|
+
*/
|
|
12
|
+
declare function parseBounds(bounds: string): [[number, number], [number, number]];
|
|
13
|
+
declare function parseWebpageView<T extends ReadonlyArray<string>>(view: {
|
|
14
|
+
resource?: Array<XMLWebsiteResource>;
|
|
15
|
+
} | undefined, options: ParserOptions<T>, context: Pick<Website<T>, "belongsTo" | "metadata">): Webpage<T> | null;
|
|
16
|
+
declare function parseWebsite<const T extends ReadonlyArray<string> = ReadonlyArray<string>>(data: XMLWebsiteData, options?: {
|
|
17
|
+
languages?: T;
|
|
18
|
+
}): Website<T>;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { parseBounds, parseWebpageView, parseWebsite };
|