ochre-sdk 1.3.17 → 1.3.19
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/fetchers/website-metadata.mjs +12 -1
- package/dist/parsers/website/components.mjs +21 -1
- package/dist/parsers/website/index.mjs +63 -23
- package/dist/parsers/website/reader.d.mts +1 -0
- package/dist/parsers/website/reader.mjs +11 -0
- package/dist/types/website.d.mts +20 -1
- package/package.json +1 -1
|
@@ -90,6 +90,16 @@ declare function local:matching-pages($resources, $target-slug, $slug-prefix) {
|
|
|
90
90
|
)
|
|
91
91
|
};
|
|
92
92
|
|
|
93
|
+
declare function local:oak-collection-pages($tree, $resources, $target-slug) {
|
|
94
|
+
if ($tree/properties/property[label/string() = "presentation"][value/string() = "website"]/property[label/string() = "webUI"]/value/string() = "oak") then
|
|
95
|
+
for $resource in $resources[local:presentation(.) = "element"]
|
|
96
|
+
let $slug := local:clean-slug($resource/@slug)
|
|
97
|
+
where string(($resource/properties/property[label/string() = "presentation"]/property[label/string() = "component"]/value)[1]) = "collection"
|
|
98
|
+
and (if ($slug != "") then $slug else string(($resource/identification/abbreviation/content/string)[1])) = $target-slug
|
|
99
|
+
return local:metadata-page($resource)
|
|
100
|
+
else ()
|
|
101
|
+
};
|
|
102
|
+
|
|
93
103
|
declare function local:metadata-tree($tree, $target-slug, $slug-prefix) {
|
|
94
104
|
let $resources := local:resource-items($tree/items/resource)
|
|
95
105
|
let $presentation-properties := $tree/properties/property[label/string() = "presentation"][value/string() = "website"]/property[label/string() = (${Object.values(METADATA_PRESENTATION_LABELS).map((label) => stringLiteral(label)).join(", ")})]
|
|
@@ -103,7 +113,8 @@ declare function local:metadata-tree($tree, $target-slug, $slug-prefix) {
|
|
|
103
113
|
$resources[local:presentation(.) = "page"],
|
|
104
114
|
$target-slug,
|
|
105
115
|
$slug-prefix
|
|
106
|
-
)
|
|
116
|
+
),
|
|
117
|
+
local:oak-collection-pages($tree, $resources, $target-slug)
|
|
107
118
|
}
|
|
108
119
|
}
|
|
109
120
|
};
|
|
@@ -65,7 +65,8 @@ function parseCollectionPropertyOverrides(reader) {
|
|
|
65
65
|
read("isSortDisplayed", "sort-displayed");
|
|
66
66
|
read("isUsingQueryParams", "is-using-query-params");
|
|
67
67
|
read("isInteractive", "is-interactive");
|
|
68
|
-
|
|
68
|
+
const imageLayout = reader.value("image-layout");
|
|
69
|
+
if (imageLayout != null) imageOverrides.layout = imageLayout === "suppress" ? null : imageLayout;
|
|
69
70
|
readImage("fit", "image-fit");
|
|
70
71
|
readImage("alignment", "image-alignment");
|
|
71
72
|
readImage("isPlaceholderDisplayed", "image-placeholder-displayed");
|
|
@@ -455,6 +456,24 @@ function parseMapComponent(parameters) {
|
|
|
455
456
|
let maximumBounds = null;
|
|
456
457
|
const maximumBoundsProperty = componentReader.value("maximum-bounds");
|
|
457
458
|
if (maximumBoundsProperty !== null) maximumBounds = parseBounds(String(maximumBoundsProperty));
|
|
459
|
+
const layerSettings = [];
|
|
460
|
+
for (const layerReader of componentReader.nestedAllByValue("customize-special", "map-layer")) {
|
|
461
|
+
const uuid = layerReader.uuid("use-layer");
|
|
462
|
+
if (uuid == null) continue;
|
|
463
|
+
const opacity = layerReader.value("opacity-percent");
|
|
464
|
+
const filterFields = layerReader.stringValues("filter-field");
|
|
465
|
+
layerSettings.push({
|
|
466
|
+
uuid,
|
|
467
|
+
isBasemap: layerReader.value("is-basemap"),
|
|
468
|
+
isDisplayedByDefault: layerReader.value("displayed-by-default"),
|
|
469
|
+
opacity: typeof opacity === "number" ? Math.min(Math.max(opacity, 0), 100) / 100 : null,
|
|
470
|
+
ochreLinkField: layerReader.stringValue("ochre-link-field"),
|
|
471
|
+
periodField: layerReader.stringValue("period-field"),
|
|
472
|
+
periodOrder: layerReader.stringValues("period-order"),
|
|
473
|
+
filterFields: filterFields.length > 0 ? filterFields : null,
|
|
474
|
+
markerColor: layerReader.stringValue("marker-color")
|
|
475
|
+
});
|
|
476
|
+
}
|
|
458
477
|
return {
|
|
459
478
|
component: "map",
|
|
460
479
|
linkUuids,
|
|
@@ -462,6 +481,7 @@ function parseMapComponent(parameters) {
|
|
|
462
481
|
customBasemap,
|
|
463
482
|
initialBounds,
|
|
464
483
|
maximumBounds,
|
|
484
|
+
layerSettings,
|
|
465
485
|
...properties
|
|
466
486
|
};
|
|
467
487
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { cleanObject, parseLicense, parseRequiredContentLike } from "../helpers.mjs";
|
|
1
|
+
import { cleanObject, parseLicense, parseRequiredContentLike, parseStringContent } from "../helpers.mjs";
|
|
2
2
|
import { parseMetadataLanguages, resolveDefaultLanguage, resolveLanguages } from "../languages.mjs";
|
|
3
3
|
import { parseIdentification, parseLinks, parseMetadata, parsePersonList, parseSimplifiedProperties } from "../index.mjs";
|
|
4
4
|
import { findWebsiteLink, parseWebsiteLinkTarget, webImageFromLink } from "./links.mjs";
|
|
5
|
+
import { formatXMLWebsiteResourceMetadata } from "./messages.mjs";
|
|
5
6
|
import { websitePresentationReader } from "./reader.mjs";
|
|
6
7
|
import { emptyResponsiveStyles, parseResponsiveCssStyles } from "./styles.mjs";
|
|
8
|
+
import { cleanWebsitePageSlug } from "./slug.mjs";
|
|
7
9
|
import { collectWebsitePageSlugs, normalizeWebsiteResources, readWebsitePages } from "./walk.mjs";
|
|
8
10
|
import { parseWebElement, parseWebTitle } from "./components.mjs";
|
|
9
11
|
import { parseWebsiteProperties } from "./properties.mjs";
|
|
@@ -53,23 +55,13 @@ function parseWebpageRedirect(redirectValue, context) {
|
|
|
53
55
|
};
|
|
54
56
|
return null;
|
|
55
57
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
* @param page - The page node, with its slug and nesting already resolved
|
|
60
|
-
* @returns Parsed Webpage object
|
|
61
|
-
*/
|
|
62
|
-
function parseWebpage(page, options, context) {
|
|
63
|
-
const webpageResource = page.resource;
|
|
64
|
-
const webpageProperties = parseSimplifiedProperties(webpageResource.properties, options);
|
|
65
|
-
const webpageReader = websitePresentationReader(webpageProperties);
|
|
66
|
-
const identification = parseIdentification(webpageResource.identification, options);
|
|
67
|
-
const returnWebpage = {
|
|
68
|
-
uuid: webpageResource.uuid,
|
|
58
|
+
function createWebpage(resource, slug, options) {
|
|
59
|
+
return {
|
|
60
|
+
uuid: resource.uuid,
|
|
69
61
|
type: "page",
|
|
70
|
-
title: identification.label,
|
|
71
|
-
slug
|
|
72
|
-
publicationDateTime:
|
|
62
|
+
title: parseIdentification(resource.identification, options).label,
|
|
63
|
+
slug,
|
|
64
|
+
publicationDateTime: resource.publicationDateTime ?? null,
|
|
73
65
|
items: [],
|
|
74
66
|
segments: [],
|
|
75
67
|
properties: {
|
|
@@ -86,6 +78,18 @@ function parseWebpage(page, options, context) {
|
|
|
86
78
|
},
|
|
87
79
|
webpages: []
|
|
88
80
|
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Parses a walked page node into a standardized Webpage structure
|
|
84
|
+
*
|
|
85
|
+
* @param page - The page node, with its slug and nesting already resolved
|
|
86
|
+
* @returns Parsed Webpage object
|
|
87
|
+
*/
|
|
88
|
+
function parseWebpage(page, options, context) {
|
|
89
|
+
const webpageResource = page.resource;
|
|
90
|
+
const webpageProperties = parseSimplifiedProperties(webpageResource.properties, options);
|
|
91
|
+
const webpageReader = websitePresentationReader(webpageProperties);
|
|
92
|
+
const returnWebpage = createWebpage(webpageResource, page.slug, options);
|
|
89
93
|
const websiteLinks = parseLinks(webpageResource.links, options);
|
|
90
94
|
const imageLink = findWebsiteLink(websiteLinks, "resource", (link) => link.type === "image" || link.type === "IIIF");
|
|
91
95
|
const webpageResources = normalizeWebsiteResources(webpageResource.resource);
|
|
@@ -265,6 +269,36 @@ function parseWebBlock(blockResource, options, context) {
|
|
|
265
269
|
returnBlock.cssStyles = parseResponsiveCssStyles(blockProperties);
|
|
266
270
|
return returnBlock;
|
|
267
271
|
}
|
|
272
|
+
function parseOakWebsite(resources, webpages, options, context) {
|
|
273
|
+
const webpagesByUuid = new Map(webpages.map((webpage) => [webpage.uuid, webpage]));
|
|
274
|
+
const items = [];
|
|
275
|
+
let map = null;
|
|
276
|
+
for (const resource of resources) {
|
|
277
|
+
const webpage = webpagesByUuid.get(resource.uuid);
|
|
278
|
+
if (webpage != null) {
|
|
279
|
+
items.push(webpage);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const component = websitePresentationReader(parseSimplifiedProperties(resource.properties, options)).nestedByValue("presentation", "element").value("component");
|
|
283
|
+
if (component !== "map" && component !== "collection") continue;
|
|
284
|
+
const element = parseWebElement(resource, options, context.pageSlugsByUuid);
|
|
285
|
+
if (element.component === "map") {
|
|
286
|
+
map ??= element;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
const resourceSlug = cleanWebsitePageSlug(resource.slug) ?? "";
|
|
290
|
+
const slug = resourceSlug === "" ? parseStringContent(resource.identification.abbreviation, options) : resourceSlug;
|
|
291
|
+
if (slug === "") throw new Error(`Slug not found for OAK collection (${formatXMLWebsiteResourceMetadata(resource)})`, { cause: resource });
|
|
292
|
+
const collectionPage = createWebpage(resource, slug, options);
|
|
293
|
+
collectionPage.items = [element];
|
|
294
|
+
collectionPage.properties.isDisplayedInNavbar = false;
|
|
295
|
+
items.push(collectionPage);
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
items,
|
|
299
|
+
oak: { map }
|
|
300
|
+
};
|
|
301
|
+
}
|
|
268
302
|
function parseWebsiteTree(websiteTree, options, context, type, slugPrefix) {
|
|
269
303
|
if (!websiteTree.properties) throw new Error(`Website properties not found (website uuid “${websiteTree.uuid}”)`, { cause: websiteTree });
|
|
270
304
|
if (type === "website" && websiteTree.items?.resource == null) throw new Error(`Website pages not found (website uuid “${websiteTree.uuid}”)`, { cause: websiteTree });
|
|
@@ -278,6 +312,15 @@ function parseWebsiteTree(websiteTree, options, context, type, slugPrefix) {
|
|
|
278
312
|
const sidebar = parseSidebar(resources, options, treeContext);
|
|
279
313
|
const properties = parseWebsiteProperties(websiteTree.properties.property, websiteTree, sidebar, options, context.parentProperties ?? null);
|
|
280
314
|
const license = parseLicense(websiteTree.availability) ?? context.parentLicense ?? null;
|
|
315
|
+
const webpages = parseWebpages(pages, options, {
|
|
316
|
+
...treeContext,
|
|
317
|
+
parentProperties: properties,
|
|
318
|
+
parentLicense: license
|
|
319
|
+
});
|
|
320
|
+
const { items, oak } = type === "website" && properties.type === "oak" ? parseOakWebsite(resources, webpages, options, treeContext) : {
|
|
321
|
+
items: webpages,
|
|
322
|
+
oak: null
|
|
323
|
+
};
|
|
281
324
|
return {
|
|
282
325
|
uuid: websiteTree.uuid,
|
|
283
326
|
type,
|
|
@@ -287,12 +330,9 @@ function parseWebsiteTree(websiteTree, options, context, type, slugPrefix) {
|
|
|
287
330
|
identification: parseIdentification(websiteTree.identification, options),
|
|
288
331
|
creators: websiteTree.creators ? parsePersonList(websiteTree.creators.creator, options) : [],
|
|
289
332
|
license,
|
|
290
|
-
items
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
parentLicense: license
|
|
294
|
-
}),
|
|
295
|
-
properties
|
|
333
|
+
items,
|
|
334
|
+
properties,
|
|
335
|
+
oak
|
|
296
336
|
};
|
|
297
337
|
}
|
|
298
338
|
function parseWebsite(data, options) {
|
|
@@ -44,6 +44,7 @@ export declare class WebsitePresentationReader<T extends LanguageCodes> {
|
|
|
44
44
|
* @returns The string, or null when the property is unset or not string-like
|
|
45
45
|
*/
|
|
46
46
|
stringValue(label: string): string | null;
|
|
47
|
+
stringValues(label: string): Array<string>;
|
|
47
48
|
uuid(label: string): string | null;
|
|
48
49
|
multilingualValue(label: string, options: ParserOptions<T>): MultilingualString<T> | null;
|
|
49
50
|
/**
|
|
@@ -63,6 +63,17 @@ var WebsitePresentationReader = class WebsitePresentationReader {
|
|
|
63
63
|
if (typeof value === "string") return value;
|
|
64
64
|
return typeof value === "number" ? value.toString() : null;
|
|
65
65
|
}
|
|
66
|
+
stringValues(label) {
|
|
67
|
+
const values = [];
|
|
68
|
+
for (const property of this.sourceProperties) {
|
|
69
|
+
if (getProperty([property], { label }) == null) continue;
|
|
70
|
+
for (const { content } of property.values) {
|
|
71
|
+
const value = typeof content === "number" ? content.toString() : content;
|
|
72
|
+
if (typeof value === "string" && value.trim() !== "") values.push(value.trim());
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return values;
|
|
76
|
+
}
|
|
66
77
|
uuid(label) {
|
|
67
78
|
return this.valueNode(label)?.uuid ?? null;
|
|
68
79
|
}
|
package/dist/types/website.d.mts
CHANGED
|
@@ -219,6 +219,14 @@ export type Website<T extends LanguageCodes = LanguageCodes> = {
|
|
|
219
219
|
};
|
|
220
220
|
}>;
|
|
221
221
|
};
|
|
222
|
+
/**
|
|
223
|
+
* The bare Map element of an OAK website, null for every other design. Its
|
|
224
|
+
* bare Collection elements are in `items` as pages hidden from the navbar,
|
|
225
|
+
* in tree order.
|
|
226
|
+
*/
|
|
227
|
+
oak: {
|
|
228
|
+
map: WebElementOf<"map", T> | null;
|
|
229
|
+
} | null;
|
|
222
230
|
};
|
|
223
231
|
export type WebsiteSegment<T extends LanguageCodes = LanguageCodes> = Website<T> & {
|
|
224
232
|
type: "segment";
|
|
@@ -358,7 +366,7 @@ export type WebElementComponent<T extends LanguageCodes = LanguageCodes> = {
|
|
|
358
366
|
paginationVariant: "default" | "numeric";
|
|
359
367
|
loadingVariant: WebLoadingVariant;
|
|
360
368
|
image: {
|
|
361
|
-
layout: "top" | "bottom" | "start" | "end" | null;
|
|
369
|
+
layout: "top" | "bottom" | "start" | "end" | "thumbnail" | null;
|
|
362
370
|
fit: "fill" | "fit";
|
|
363
371
|
alignment: "top" | "center" | "bottom" | null;
|
|
364
372
|
isPlaceholderDisplayed: boolean;
|
|
@@ -426,6 +434,17 @@ export type WebElementComponent<T extends LanguageCodes = LanguageCodes> = {
|
|
|
426
434
|
customBasemap: string | null;
|
|
427
435
|
initialBounds: [[number, number], [number, number]] | null;
|
|
428
436
|
maximumBounds: [[number, number], [number, number]] | null;
|
|
437
|
+
layerSettings: Array<{
|
|
438
|
+
uuid: string;
|
|
439
|
+
isBasemap: boolean | null;
|
|
440
|
+
isDisplayedByDefault: boolean | null;
|
|
441
|
+
opacity: number | null;
|
|
442
|
+
ochreLinkField: string | null;
|
|
443
|
+
periodField: string | null;
|
|
444
|
+
periodOrder: Array<string>;
|
|
445
|
+
filterFields: Array<string> | null;
|
|
446
|
+
markerColor: string | null;
|
|
447
|
+
}>;
|
|
429
448
|
isControlsDisplayed: boolean;
|
|
430
449
|
isInteractive: boolean;
|
|
431
450
|
isClustered: boolean;
|