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
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { WebImage } from "../../types/website.mjs";
|
|
2
|
+
import { ItemLink, ItemLinkCategory, ItemLinks, PropertyValueContent } from "../../types/index.mjs";
|
|
3
|
+
import { WebsitePageSlugs } from "./slug.mjs";
|
|
4
|
+
//#region src/parsers/website/links.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* The link categories a website can point at
|
|
7
|
+
*/
|
|
8
|
+
export type WebsiteLinkCategory = Extract<ItemLinkCategory, "resource" | "set" | "tree">;
|
|
9
|
+
export declare function findWebsiteLink<U extends WebsiteLinkCategory, T extends ReadonlyArray<string>>(links: ItemLinks<T>, category: U, isMatch?: (link: ItemLink<U, T>) => boolean): ItemLink<U, T> | null;
|
|
10
|
+
export declare function findWebsiteLinkByCategories<U extends WebsiteLinkCategory, T extends ReadonlyArray<string>>(links: ItemLinks<T>, categories: ReadonlyArray<U>): ItemLink<U, T> | null;
|
|
11
|
+
export declare function getWebsiteLinks<U extends WebsiteLinkCategory, T extends ReadonlyArray<string>>(links: ItemLinks<T>, category: U): Array<ItemLink<U, T>>;
|
|
12
|
+
/**
|
|
13
|
+
* Where a "link-to", "navigate-to" or "redirect-to" property points
|
|
14
|
+
*
|
|
15
|
+
* An external href is rewritten to an item route; anything else resolves
|
|
16
|
+
* through the page slug map, so a link to a page inside a segment gets that
|
|
17
|
+
* segment's full slug rather than the bare one OCHRE stores on the page.
|
|
18
|
+
* @param value - The raw property value holding the target
|
|
19
|
+
* @param pageSlugs - The website's resolved page slugs
|
|
20
|
+
* @returns The target, or null when the property carries none
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseWebsiteLinkTarget<T extends ReadonlyArray<string>>(value: PropertyValueContent<T> | null, pageSlugs: WebsitePageSlugs | undefined): string | null;
|
|
24
|
+
/**
|
|
25
|
+
* The image a link stands for
|
|
26
|
+
*
|
|
27
|
+
* Built the same way wherever a website shows a linked image, so the six
|
|
28
|
+
* fields and the fallbacks for a link OCHRE has no dimensions for are stated
|
|
29
|
+
* once.
|
|
30
|
+
* @param link - The resource link pointing at the image
|
|
31
|
+
* @param quality - The quality the consumer should request
|
|
32
|
+
* @returns The image
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
export declare function webImageFromLink<T extends ReadonlyArray<string>>(link: ItemLinks<T>[number], quality: WebImage<T>["quality"]): WebImage<T>;
|
|
36
|
+
//#endregion
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { transformPermanentIdentificationUrlToItemLink } from "../string.mjs";
|
|
2
|
+
//#region src/parsers/website/links.ts
|
|
3
|
+
function isWebsiteLink(link, category) {
|
|
4
|
+
return link.category === category;
|
|
5
|
+
}
|
|
6
|
+
function findWebsiteLink(links, category, isMatch) {
|
|
7
|
+
for (const link of links) if (isWebsiteLink(link, category) && (isMatch == null || isMatch(link))) return link;
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
function findWebsiteLinkByCategories(links, categories) {
|
|
11
|
+
for (const link of links) for (const category of categories) if (isWebsiteLink(link, category)) return link;
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
function getWebsiteLinks(links, category) {
|
|
15
|
+
const matchedLinks = [];
|
|
16
|
+
for (const link of links) if (isWebsiteLink(link, category)) matchedLinks.push(link);
|
|
17
|
+
return matchedLinks;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Where a "link-to", "navigate-to" or "redirect-to" property points
|
|
21
|
+
*
|
|
22
|
+
* An external href is rewritten to an item route; anything else resolves
|
|
23
|
+
* through the page slug map, so a link to a page inside a segment gets that
|
|
24
|
+
* segment's full slug rather than the bare one OCHRE stores on the page.
|
|
25
|
+
* @param value - The raw property value holding the target
|
|
26
|
+
* @param pageSlugs - The website's resolved page slugs
|
|
27
|
+
* @returns The target, or null when the property carries none
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
function parseWebsiteLinkTarget(value, pageSlugs) {
|
|
31
|
+
if (value == null) return null;
|
|
32
|
+
if (value.href != null) return transformPermanentIdentificationUrlToItemLink(value.href);
|
|
33
|
+
return (value.uuid == null ? void 0 : pageSlugs?.get(value.uuid)) ?? value.slug;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The image a link stands for
|
|
37
|
+
*
|
|
38
|
+
* Built the same way wherever a website shows a linked image, so the six
|
|
39
|
+
* fields and the fallbacks for a link OCHRE has no dimensions for are stated
|
|
40
|
+
* once.
|
|
41
|
+
* @param link - The resource link pointing at the image
|
|
42
|
+
* @param quality - The quality the consumer should request
|
|
43
|
+
* @returns The image
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
function webImageFromLink(link, quality) {
|
|
47
|
+
const image = "image" in link ? link.image : null;
|
|
48
|
+
return {
|
|
49
|
+
uuid: link.uuid,
|
|
50
|
+
label: link.identification.label,
|
|
51
|
+
description: link.description,
|
|
52
|
+
width: image?.width ?? 0,
|
|
53
|
+
height: image?.height ?? 0,
|
|
54
|
+
quality
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { findWebsiteLink, findWebsiteLinkByCategories, getWebsiteLinks, parseWebsiteLinkTarget, webImageFromLink };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { WebElementComponent } from "../../types/website.mjs";
|
|
2
|
+
import { XMLWebsiteResource } from "../../xml/types.mjs";
|
|
3
|
+
//#region src/parsers/website/messages.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Name a resource well enough to find it in OCHRE from an error message
|
|
6
|
+
*
|
|
7
|
+
* Every throw in the website parser goes through here, because a UUID on its
|
|
8
|
+
* own is not something anyone can look up quickly and a label on its own is
|
|
9
|
+
* not unique.
|
|
10
|
+
* @param resource - The resource the error is about
|
|
11
|
+
* @returns A comma-separated description of the resource
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export declare function formatXMLWebsiteResourceMetadata(resource: XMLWebsiteResource): string;
|
|
15
|
+
/**
|
|
16
|
+
* Describe a component parser failure
|
|
17
|
+
* @param message - What went wrong
|
|
18
|
+
* @param componentName - The component being parsed
|
|
19
|
+
* @param elementResource - The element the component belongs to
|
|
20
|
+
* @returns The error message
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatComponentError(message: string, componentName: WebElementComponent["component"] | undefined, elementResource: XMLWebsiteResource): string;
|
|
24
|
+
//#endregion
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { parseStringContent } from "../helpers.mjs";
|
|
2
|
+
//#region src/parsers/website/messages.ts
|
|
3
|
+
/**
|
|
4
|
+
* Name a resource well enough to find it in OCHRE from an error message
|
|
5
|
+
*
|
|
6
|
+
* Every throw in the website parser goes through here, because a UUID on its
|
|
7
|
+
* own is not something anyone can look up quickly and a label on its own is
|
|
8
|
+
* not unique.
|
|
9
|
+
* @param resource - The resource the error is about
|
|
10
|
+
* @returns A comma-separated description of the resource
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
function formatXMLWebsiteResourceMetadata(resource) {
|
|
14
|
+
const metadata = [`label “${parseStringContent(resource.identification.label)}”`, `uuid “${resource.uuid}”`];
|
|
15
|
+
if (resource.slug != null) metadata.push(`slug “${resource.slug}”`);
|
|
16
|
+
if (resource.identification.abbreviation != null) metadata.push(`abbreviation “${parseStringContent(resource.identification.abbreviation)}”`);
|
|
17
|
+
return metadata.join(", ");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Describe a component parser failure
|
|
21
|
+
* @param message - What went wrong
|
|
22
|
+
* @param componentName - The component being parsed
|
|
23
|
+
* @param elementResource - The element the component belongs to
|
|
24
|
+
* @returns The error message
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
function formatComponentError(message, componentName, elementResource) {
|
|
28
|
+
return `${message} for component “${componentName ?? "(unknown)"}” (${formatXMLWebsiteResourceMetadata(elementResource)})`;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { formatComponentError, formatXMLWebsiteResourceMetadata };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { WebOptions } from "../../types/website.mjs";
|
|
2
|
+
import { XMLWebsiteOptions } from "../../xml/types.mjs";
|
|
3
|
+
import { ParserOptions } from "../helpers.mjs";
|
|
4
|
+
//#region src/parsers/website/options.d.ts
|
|
5
|
+
export declare function parseWebsiteOptions<T extends ReadonlyArray<string>>(rawOptions: XMLWebsiteOptions | undefined, options: ParserOptions<T>): WebOptions<T>;
|
|
6
|
+
//#endregion
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { parseContentLike } from "../helpers.mjs";
|
|
2
|
+
import { parseIdentification, parseNotes } from "../index.mjs";
|
|
3
|
+
//#region src/parsers/website/options.ts
|
|
4
|
+
function parseContextTreeLevel(contextItemToParse, options) {
|
|
5
|
+
let type = "";
|
|
6
|
+
const levels = [];
|
|
7
|
+
const levelsToParse = contextItemToParse.levels?.level ?? [];
|
|
8
|
+
for (const level of levelsToParse) {
|
|
9
|
+
const [rawVariableUuid = "", rawValueUuid] = level.payload.split(",", 2);
|
|
10
|
+
const valueUuid = rawValueUuid == null || rawValueUuid.trim() === "null" ? null : rawValueUuid.trim();
|
|
11
|
+
type = level.dataType ?? type;
|
|
12
|
+
levels.push({
|
|
13
|
+
variableUuid: rawVariableUuid.trim(),
|
|
14
|
+
valueUuid
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
context: levels,
|
|
19
|
+
type,
|
|
20
|
+
identification: parseIdentification(contextItemToParse.identification, options),
|
|
21
|
+
description: parseContentLike(contextItemToParse.description, options)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function parseFilterContextDisplay(filterOption) {
|
|
25
|
+
switch (filterOption) {
|
|
26
|
+
case "inline-displayed": return {
|
|
27
|
+
isInlineDisplayed: true,
|
|
28
|
+
isSidebarDisplayed: false,
|
|
29
|
+
isSidebarOpen: false
|
|
30
|
+
};
|
|
31
|
+
case "inline-sidebar-displayed-closed": return {
|
|
32
|
+
isInlineDisplayed: true,
|
|
33
|
+
isSidebarDisplayed: true,
|
|
34
|
+
isSidebarOpen: false
|
|
35
|
+
};
|
|
36
|
+
case "inline-sidebar-displayed-open": return {
|
|
37
|
+
isInlineDisplayed: true,
|
|
38
|
+
isSidebarDisplayed: true,
|
|
39
|
+
isSidebarOpen: true
|
|
40
|
+
};
|
|
41
|
+
case "sidebar-displayed-closed": return {
|
|
42
|
+
isInlineDisplayed: false,
|
|
43
|
+
isSidebarDisplayed: true,
|
|
44
|
+
isSidebarOpen: false
|
|
45
|
+
};
|
|
46
|
+
case "sidebar-displayed-open": return {
|
|
47
|
+
isInlineDisplayed: false,
|
|
48
|
+
isSidebarDisplayed: true,
|
|
49
|
+
isSidebarOpen: true
|
|
50
|
+
};
|
|
51
|
+
default: return {
|
|
52
|
+
isInlineDisplayed: false,
|
|
53
|
+
isSidebarDisplayed: false,
|
|
54
|
+
isSidebarOpen: false
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function parseContexts(contextLevels, options) {
|
|
59
|
+
const contextTreeLevels = [];
|
|
60
|
+
for (const contextLevel of contextLevels) for (const contextItemToParse of contextLevel.context) contextTreeLevels.push(parseContextTreeLevel(contextItemToParse, options));
|
|
61
|
+
return contextTreeLevels;
|
|
62
|
+
}
|
|
63
|
+
function parseFilterContexts(filterContextLevels, options) {
|
|
64
|
+
const filterContextTreeLevels = [];
|
|
65
|
+
for (const filterContextLevel of filterContextLevels) for (const contextItemToParse of filterContextLevel.context) filterContextTreeLevels.push({
|
|
66
|
+
...parseContextTreeLevel(contextItemToParse, options),
|
|
67
|
+
filterType: contextItemToParse.filterType ?? "property",
|
|
68
|
+
filterVariant: contextItemToParse.filterVariant ?? null,
|
|
69
|
+
...parseFilterContextDisplay(contextItemToParse.filterOption)
|
|
70
|
+
});
|
|
71
|
+
return filterContextTreeLevels;
|
|
72
|
+
}
|
|
73
|
+
function parseAllOptionContexts(options, parserOptions) {
|
|
74
|
+
function handleContexts(contexts) {
|
|
75
|
+
return parseContexts(contexts ?? [], parserOptions);
|
|
76
|
+
}
|
|
77
|
+
function handleFilterContexts(contexts) {
|
|
78
|
+
return parseFilterContexts(contexts ?? [], parserOptions);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
flatten: handleContexts(options.flattenContexts),
|
|
82
|
+
suppress: handleContexts(options.suppressContexts),
|
|
83
|
+
filter: handleFilterContexts(options.filterContexts),
|
|
84
|
+
sort: handleContexts(options.sortContexts),
|
|
85
|
+
detail: handleContexts(options.detailContexts),
|
|
86
|
+
download: handleContexts(options.downloadContexts),
|
|
87
|
+
label: handleContexts(options.labelContexts),
|
|
88
|
+
prominent: handleContexts(options.prominentContexts)
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function parseWebsiteScopes(scopes, options) {
|
|
92
|
+
if (scopes == null) return null;
|
|
93
|
+
return Array.from(scopes.scope, (scope) => ({
|
|
94
|
+
uuid: scope.uuid.payload,
|
|
95
|
+
type: scope.uuid.type,
|
|
96
|
+
identification: parseIdentification(scope.identification, options)
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
function parseWebsiteOptions(rawOptions, options) {
|
|
100
|
+
const parsedOptions = {
|
|
101
|
+
scopes: parseWebsiteScopes(rawOptions?.scopes, options),
|
|
102
|
+
contextTree: rawOptions == null ? null : parseAllOptionContexts(rawOptions, options),
|
|
103
|
+
labels: { title: null }
|
|
104
|
+
};
|
|
105
|
+
const notes = parseNotes(rawOptions?.notes, options);
|
|
106
|
+
for (const note of notes) {
|
|
107
|
+
if (note.title?.getText() !== "Title label") continue;
|
|
108
|
+
parsedOptions.labels.title = note.content;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
return parsedOptions;
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { parseWebsiteOptions };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { WebSidebar, Website } from "../../types/website.mjs";
|
|
2
|
+
import { XMLWebsiteProperties, XMLWebsiteTree } from "../../xml/types.mjs";
|
|
3
|
+
import { ParserOptions } from "../helpers.mjs";
|
|
4
|
+
//#region src/parsers/website/properties.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Parses raw website properties into a standardized Website properties structure
|
|
7
|
+
*
|
|
8
|
+
* @param properties - Array of raw website properties in OCHRE format
|
|
9
|
+
* @returns Parsed WebsiteProperties object
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseWebsiteProperties<T extends ReadonlyArray<string>>(properties: XMLWebsiteProperties["property"], websiteTree: XMLWebsiteTree, sidebar: WebSidebar<T> | null, options: ParserOptions<T>, parent: Website<T>["properties"] | null): Website<T>["properties"];
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { parseSimplifiedProperties } from "../index.mjs";
|
|
2
|
+
import { parseWebsiteOptions } from "./options.mjs";
|
|
3
|
+
import { websitePresentationReader } from "./reader.mjs";
|
|
4
|
+
import { parseStylesheets } from "./styles.mjs";
|
|
5
|
+
//#region src/parsers/website/properties.ts
|
|
6
|
+
/**
|
|
7
|
+
* Parses raw website properties into a standardized Website properties structure
|
|
8
|
+
*
|
|
9
|
+
* @param properties - Array of raw website properties in OCHRE format
|
|
10
|
+
* @returns Parsed WebsiteProperties object
|
|
11
|
+
*/
|
|
12
|
+
function parseWebsiteProperties(properties, websiteTree, sidebar, options, parent) {
|
|
13
|
+
const mainProperties = parseSimplifiedProperties({ property: properties }, options);
|
|
14
|
+
const websiteReader = websitePresentationReader(mainProperties).nested("presentation");
|
|
15
|
+
const returnProperties = {
|
|
16
|
+
type: parent?.type ?? "traditional",
|
|
17
|
+
status: parent?.status ?? "development",
|
|
18
|
+
versionLabel: parent?.versionLabel ?? "release",
|
|
19
|
+
privacy: parent?.privacy ?? "public",
|
|
20
|
+
contact: parent?.contact ?? null,
|
|
21
|
+
loadingVariant: "spinner",
|
|
22
|
+
theme: {
|
|
23
|
+
isThemeToggleDisplayed: true,
|
|
24
|
+
defaultTheme: "system"
|
|
25
|
+
},
|
|
26
|
+
icon: {
|
|
27
|
+
logoUuid: null,
|
|
28
|
+
faviconUuid: null,
|
|
29
|
+
appleTouchIconUuid: null
|
|
30
|
+
},
|
|
31
|
+
navbar: {
|
|
32
|
+
isDisplayed: true,
|
|
33
|
+
variant: "default",
|
|
34
|
+
alignment: "start",
|
|
35
|
+
isProjectDisplayed: true,
|
|
36
|
+
searchBarBoundElementUuid: null,
|
|
37
|
+
items: parent?.navbar.items ?? null
|
|
38
|
+
},
|
|
39
|
+
footer: {
|
|
40
|
+
isDisplayed: true,
|
|
41
|
+
logoUuid: null,
|
|
42
|
+
items: parent?.footer.items ?? null
|
|
43
|
+
},
|
|
44
|
+
sidebar: sidebar ?? parent?.sidebar ?? null,
|
|
45
|
+
itemPage: {
|
|
46
|
+
isMainContentDisplayed: parent?.itemPage.isMainContentDisplayed ?? true,
|
|
47
|
+
description: {
|
|
48
|
+
isDisplayed: parent?.itemPage.description.isDisplayed ?? true,
|
|
49
|
+
isHeaderDisplayed: parent?.itemPage.description.isHeaderDisplayed ?? true
|
|
50
|
+
},
|
|
51
|
+
document: {
|
|
52
|
+
isDisplayed: parent?.itemPage.document.isDisplayed ?? true,
|
|
53
|
+
isHeaderDisplayed: parent?.itemPage.document.isHeaderDisplayed ?? true
|
|
54
|
+
},
|
|
55
|
+
notes: {
|
|
56
|
+
isDisplayed: parent?.itemPage.notes.isDisplayed ?? true,
|
|
57
|
+
isHeaderDisplayed: parent?.itemPage.notes.isHeaderDisplayed ?? true,
|
|
58
|
+
variant: parent?.itemPage.notes.variant ?? "discrete"
|
|
59
|
+
},
|
|
60
|
+
events: {
|
|
61
|
+
isDisplayed: parent?.itemPage.events.isDisplayed ?? true,
|
|
62
|
+
isHeaderDisplayed: parent?.itemPage.events.isHeaderDisplayed ?? true,
|
|
63
|
+
variant: parent?.itemPage.events.variant ?? "tabular"
|
|
64
|
+
},
|
|
65
|
+
periods: {
|
|
66
|
+
isDisplayed: parent?.itemPage.periods.isDisplayed ?? true,
|
|
67
|
+
isHeaderDisplayed: parent?.itemPage.periods.isHeaderDisplayed ?? true
|
|
68
|
+
},
|
|
69
|
+
isPropertiesDisplayed: parent?.itemPage.isPropertiesDisplayed ?? true,
|
|
70
|
+
bibliography: {
|
|
71
|
+
isDisplayed: parent?.itemPage.bibliography.isDisplayed ?? true,
|
|
72
|
+
isHeaderDisplayed: parent?.itemPage.bibliography.isHeaderDisplayed ?? true
|
|
73
|
+
},
|
|
74
|
+
isPropertyValuesGrouped: parent?.itemPage.isPropertyValuesGrouped ?? true,
|
|
75
|
+
isPublicationDateTimeDisplayed: parent?.itemPage.isPublicationDateTimeDisplayed ?? true,
|
|
76
|
+
isPersistentIdentifierDisplayed: parent?.itemPage.isPersistentIdentifierDisplayed ?? true,
|
|
77
|
+
iiifViewer: parent?.itemPage.iiifViewer ?? "universal-viewer"
|
|
78
|
+
},
|
|
79
|
+
options: {
|
|
80
|
+
contextTree: parent?.options.contextTree ?? null,
|
|
81
|
+
scopes: parent?.options.scopes ?? null,
|
|
82
|
+
labels: { title: parent?.options.labels.title ?? null },
|
|
83
|
+
stylesheets: { properties: parent?.options.stylesheets.properties ?? [] }
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
const contactProperty = websiteReader.property("contact");
|
|
87
|
+
if (contactProperty !== null) {
|
|
88
|
+
const contactContent = contactProperty.values[0]?.content.toString().split(";") ?? [];
|
|
89
|
+
if (contactContent.length === 2) returnProperties.contact = {
|
|
90
|
+
name: contactContent[0],
|
|
91
|
+
email: contactContent[1] ?? null
|
|
92
|
+
};
|
|
93
|
+
else throw new Error(`Contact property must use “name;email”, got “${contactProperty.values[0]?.content}” (website uuid “${websiteTree.uuid}”)`, { cause: websiteTree });
|
|
94
|
+
}
|
|
95
|
+
websiteReader.readAll(returnProperties, {
|
|
96
|
+
type: "webUI",
|
|
97
|
+
status: "status",
|
|
98
|
+
versionLabel: "version-label",
|
|
99
|
+
privacy: "privacy",
|
|
100
|
+
loadingVariant: "loading-variant"
|
|
101
|
+
});
|
|
102
|
+
websiteReader.readAll(returnProperties.theme, {
|
|
103
|
+
isThemeToggleDisplayed: "supports-theme-toggle",
|
|
104
|
+
defaultTheme: "default-theme"
|
|
105
|
+
});
|
|
106
|
+
websiteReader.readAllUuids(returnProperties.icon, {
|
|
107
|
+
logoUuid: "navbar-logo",
|
|
108
|
+
faviconUuid: "favicon-ico",
|
|
109
|
+
appleTouchIconUuid: "favicon-img"
|
|
110
|
+
});
|
|
111
|
+
websiteReader.readAll(returnProperties.navbar, {
|
|
112
|
+
isDisplayed: "navbar-displayed",
|
|
113
|
+
variant: "navbar-variant",
|
|
114
|
+
alignment: "navbar-alignment",
|
|
115
|
+
isProjectDisplayed: "navbar-project-displayed"
|
|
116
|
+
});
|
|
117
|
+
websiteReader.readAllUuids(returnProperties.navbar, { searchBarBoundElementUuid: "bound-element-navbar-search-bar" });
|
|
118
|
+
websiteReader.readAll(returnProperties.footer, { isDisplayed: "footer-displayed" });
|
|
119
|
+
websiteReader.readAllUuids(returnProperties.footer, { logoUuid: "footer-logo" });
|
|
120
|
+
const itemPageReader = websiteReader.nestedByValue("page-type", "item-page");
|
|
121
|
+
if (itemPageReader.size > 0) {
|
|
122
|
+
for (const [key, slug] of [
|
|
123
|
+
["description", "description"],
|
|
124
|
+
["document", "document"],
|
|
125
|
+
["notes", "notes"],
|
|
126
|
+
["events", "events"],
|
|
127
|
+
["periods", "periods"],
|
|
128
|
+
["bibliography", "bibliography"]
|
|
129
|
+
]) {
|
|
130
|
+
const section = returnProperties.itemPage[key];
|
|
131
|
+
itemPageReader.readAll(section, {
|
|
132
|
+
isDisplayed: `item-page-${slug}-displayed`,
|
|
133
|
+
isHeaderDisplayed: `item-page-${slug}-header-displayed`
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
itemPageReader.readAll(returnProperties.itemPage.notes, { variant: "item-page-notes-display-variant" });
|
|
137
|
+
itemPageReader.readAll(returnProperties.itemPage.events, { variant: "item-page-events-display-variant" });
|
|
138
|
+
itemPageReader.readAll(returnProperties.itemPage, {
|
|
139
|
+
isPropertyValuesGrouped: "item-page-property-values-grouped",
|
|
140
|
+
isPublicationDateTimeDisplayed: "item-page-publication-date-time-displayed",
|
|
141
|
+
isPersistentIdentifierDisplayed: "item-page-persistent-identifier-displayed",
|
|
142
|
+
iiifViewer: "item-page-iiif-viewer"
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (websiteTree.options != null) {
|
|
146
|
+
const parsedOptions = parseWebsiteOptions(websiteTree.options, options);
|
|
147
|
+
returnProperties.options.scopes = (parsedOptions.scopes != null && parsedOptions.scopes.length > 0 ? parsedOptions : returnProperties.options).scopes;
|
|
148
|
+
returnProperties.options.contextTree = parsedOptions.contextTree ?? returnProperties.options.contextTree;
|
|
149
|
+
returnProperties.options.labels = { title: parsedOptions.labels.title ?? returnProperties.options.labels.title };
|
|
150
|
+
}
|
|
151
|
+
if ("styleOptions" in websiteTree && websiteTree.styleOptions != null) {
|
|
152
|
+
const stylesheetProperties = parseStylesheets(websiteTree.styleOptions.style);
|
|
153
|
+
if (stylesheetProperties.length > 0) returnProperties.options.stylesheets.properties = stylesheetProperties;
|
|
154
|
+
}
|
|
155
|
+
return returnProperties;
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
158
|
+
export { parseWebsiteProperties };
|
|
@@ -3,24 +3,74 @@ import { LanguageCodes, PropertyValueContent, SimplifiedProperty } from "../../t
|
|
|
3
3
|
import { ParserOptions } from "../helpers.mjs";
|
|
4
4
|
//#region src/parsers/website/reader.d.ts
|
|
5
5
|
type WebsitePropertyContent<T extends LanguageCodes> = PropertyValueContent<T>["content"];
|
|
6
|
+
/**
|
|
7
|
+
* The fields of an object that hold a UUID, which are the only ones
|
|
8
|
+
* {@link WebsitePresentationReader.readAllUuids} can write
|
|
9
|
+
*/
|
|
10
|
+
type UuidKeys<O> = { [K in keyof O]-?: O[K] extends string | null ? K : never; }[keyof O];
|
|
11
|
+
/**
|
|
12
|
+
* Reads a website's presentation properties
|
|
13
|
+
*
|
|
14
|
+
* OCHRE stores everything a website declares about itself as labeled property
|
|
15
|
+
* values nested under a "presentation" property, so every read is "find the
|
|
16
|
+
* property with this label, then take its first value". This owns that walk
|
|
17
|
+
* and the coercions that go with it, and hands back readers for nested levels
|
|
18
|
+
* so the caller never touches the raw property array.
|
|
19
|
+
*/
|
|
6
20
|
export declare class WebsitePresentationReader<T extends LanguageCodes> {
|
|
7
21
|
private readonly sourceProperties;
|
|
8
22
|
constructor(sourceProperties: ReadonlyArray<SimplifiedProperty<T>>);
|
|
23
|
+
private propertyByValue;
|
|
24
|
+
/**
|
|
25
|
+
* Overwrite one field from a labeled OCHRE property
|
|
26
|
+
*
|
|
27
|
+
* Private because {@link readAll} covers every caller: a single-field read
|
|
28
|
+
* is a one-entry label map, and going through the map keeps the field's type
|
|
29
|
+
* coming from the target rather than from a type argument.
|
|
30
|
+
*/
|
|
31
|
+
private readOne;
|
|
9
32
|
property(label: string): SimplifiedProperty<T> | null;
|
|
10
33
|
requiredProperty(label: string, message: string): SimplifiedProperty<T>;
|
|
11
|
-
propertyByValue(label: string, value: WebsitePropertyContent<T>): SimplifiedProperty<T> | null;
|
|
12
34
|
valueNode(label: string): PropertyValueContent<T> | null;
|
|
13
|
-
values(label: string): Array<PropertyValueContent<T>>;
|
|
14
35
|
value<U = WebsitePropertyContent<T>>(label: string): U | null;
|
|
15
36
|
valueOr<U>(label: string, fallback: U): U;
|
|
37
|
+
/**
|
|
38
|
+
* Read a property whose field is a string but whose OCHRE value may not be
|
|
39
|
+
*
|
|
40
|
+
* OCHRE types a dimension like "width" from what was entered, so the same
|
|
41
|
+
* property arrives as `"50%"` on one resource and `50` on another. Anything
|
|
42
|
+
* that is neither is treated as unset rather than stringified, so a stray
|
|
43
|
+
* boolean does not become the literal text "true".
|
|
44
|
+
* @param label - The OCHRE property label to read
|
|
45
|
+
* @returns The string, or null when the property is unset or not string-like
|
|
46
|
+
*/
|
|
16
47
|
stringValue(label: string): string | null;
|
|
17
|
-
numberValue(label: string): number | null;
|
|
18
48
|
uuid(label: string): string | null;
|
|
19
49
|
multilingualValue(label: string, options: ParserOptions<T>): MultilingualString<T> | null;
|
|
50
|
+
/**
|
|
51
|
+
* Overwrite several fields from the OCHRE properties naming them
|
|
52
|
+
*
|
|
53
|
+
* The defaults object carries the shape and the fallback values, and the
|
|
54
|
+
* label map carries the OCHRE names, so a component states each property
|
|
55
|
+
* twice rather than five times: once as a default and once as a label. The
|
|
56
|
+
* field's type comes from the defaults object, so no type argument is needed.
|
|
57
|
+
* @param target - The object holding the fields, pre-filled with defaults
|
|
58
|
+
* @param labels - The OCHRE property label for each field to overwrite
|
|
59
|
+
*/
|
|
60
|
+
readAll<O extends object>(target: O, labels: Partial<Record<keyof O, string>>): void;
|
|
61
|
+
/**
|
|
62
|
+
* Overwrite several UUID fields from the UUIDs labeled OCHRE properties
|
|
63
|
+
* point at
|
|
64
|
+
*
|
|
65
|
+
* The same shape as {@link readAll}, for the fields that take the value's
|
|
66
|
+
* target rather than its content.
|
|
67
|
+
* @param target - The object holding the fields, pre-filled with defaults
|
|
68
|
+
* @param labels - The OCHRE property label for each field to overwrite
|
|
69
|
+
*/
|
|
70
|
+
readAllUuids<O extends object>(target: O, labels: Partial<Record<UuidKeys<O>, string>>): void;
|
|
20
71
|
nested(label: string): WebsitePresentationReader<T>;
|
|
21
72
|
nestedByValue(label: string, value: WebsitePropertyContent<T>): WebsitePresentationReader<T>;
|
|
22
73
|
get size(): number;
|
|
23
|
-
get properties(): ReadonlyArray<SimplifiedProperty<T>>;
|
|
24
74
|
}
|
|
25
75
|
export declare function websitePresentationReader<T extends LanguageCodes>(properties: ReadonlyArray<SimplifiedProperty<T>>): WebsitePresentationReader<T>;
|
|
26
76
|
//#endregion
|
|
@@ -1,27 +1,46 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getProperty, getPropertyValue } from "../../getters.mjs";
|
|
2
2
|
import { multilingualFromText } from "../helpers.mjs";
|
|
3
3
|
//#region src/parsers/website/reader.ts
|
|
4
|
+
/**
|
|
5
|
+
* Reads a website's presentation properties
|
|
6
|
+
*
|
|
7
|
+
* OCHRE stores everything a website declares about itself as labeled property
|
|
8
|
+
* values nested under a "presentation" property, so every read is "find the
|
|
9
|
+
* property with this label, then take its first value". This owns that walk
|
|
10
|
+
* and the coercions that go with it, and hands back readers for nested levels
|
|
11
|
+
* so the caller never touches the raw property array.
|
|
12
|
+
*/
|
|
4
13
|
var WebsitePresentationReader = class WebsitePresentationReader {
|
|
5
14
|
sourceProperties;
|
|
6
15
|
constructor(sourceProperties) {
|
|
7
16
|
this.sourceProperties = sourceProperties;
|
|
8
17
|
}
|
|
18
|
+
propertyByValue(label, value) {
|
|
19
|
+
return getProperty(this.sourceProperties, {
|
|
20
|
+
label,
|
|
21
|
+
valueContent: value
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Overwrite one field from a labeled OCHRE property
|
|
26
|
+
*
|
|
27
|
+
* Private because {@link readAll} covers every caller: a single-field read
|
|
28
|
+
* is a one-entry label map, and going through the map keeps the field's type
|
|
29
|
+
* coming from the target rather than from a type argument.
|
|
30
|
+
*/
|
|
31
|
+
readOne(target, key, label) {
|
|
32
|
+
target[key] = this.valueOr(label, target[key]);
|
|
33
|
+
}
|
|
9
34
|
property(label) {
|
|
10
|
-
return
|
|
35
|
+
return getProperty(this.sourceProperties, { label });
|
|
11
36
|
}
|
|
12
37
|
requiredProperty(label, message) {
|
|
13
38
|
const property = this.property(label);
|
|
14
39
|
if (property === null) throw new Error(message, { cause: this.sourceProperties });
|
|
15
40
|
return property;
|
|
16
41
|
}
|
|
17
|
-
propertyByValue(label, value) {
|
|
18
|
-
return getPropertyByVariableLabelAndValueContent(this.sourceProperties, label, value);
|
|
19
|
-
}
|
|
20
42
|
valueNode(label) {
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
values(label) {
|
|
24
|
-
return this.property(label)?.values ?? [];
|
|
43
|
+
return getPropertyValue(this.sourceProperties, { label });
|
|
25
44
|
}
|
|
26
45
|
value(label) {
|
|
27
46
|
return this.valueNode(label)?.content ?? null;
|
|
@@ -29,16 +48,20 @@ var WebsitePresentationReader = class WebsitePresentationReader {
|
|
|
29
48
|
valueOr(label, fallback) {
|
|
30
49
|
return this.value(label) ?? fallback;
|
|
31
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Read a property whose field is a string but whose OCHRE value may not be
|
|
53
|
+
*
|
|
54
|
+
* OCHRE types a dimension like "width" from what was entered, so the same
|
|
55
|
+
* property arrives as `"50%"` on one resource and `50` on another. Anything
|
|
56
|
+
* that is neither is treated as unset rather than stringified, so a stray
|
|
57
|
+
* boolean does not become the literal text "true".
|
|
58
|
+
* @param label - The OCHRE property label to read
|
|
59
|
+
* @returns The string, or null when the property is unset or not string-like
|
|
60
|
+
*/
|
|
32
61
|
stringValue(label) {
|
|
33
62
|
const value = this.value(label);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
numberValue(label) {
|
|
37
|
-
const value = this.value(label);
|
|
38
|
-
if (typeof value === "number") return value;
|
|
39
|
-
if (typeof value !== "string" || value.trim() === "") return null;
|
|
40
|
-
const parsedValue = Number(value);
|
|
41
|
-
return Number.isNaN(parsedValue) ? null : parsedValue;
|
|
63
|
+
if (typeof value === "string") return value;
|
|
64
|
+
return typeof value === "number" ? value.toString() : null;
|
|
42
65
|
}
|
|
43
66
|
uuid(label) {
|
|
44
67
|
return this.valueNode(label)?.uuid ?? null;
|
|
@@ -49,6 +72,31 @@ var WebsitePresentationReader = class WebsitePresentationReader {
|
|
|
49
72
|
if (value.label != null) return value.label;
|
|
50
73
|
return typeof value.content === "string" ? multilingualFromText(value.content, options) : null;
|
|
51
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Overwrite several fields from the OCHRE properties naming them
|
|
77
|
+
*
|
|
78
|
+
* The defaults object carries the shape and the fallback values, and the
|
|
79
|
+
* label map carries the OCHRE names, so a component states each property
|
|
80
|
+
* twice rather than five times: once as a default and once as a label. The
|
|
81
|
+
* field's type comes from the defaults object, so no type argument is needed.
|
|
82
|
+
* @param target - The object holding the fields, pre-filled with defaults
|
|
83
|
+
* @param labels - The OCHRE property label for each field to overwrite
|
|
84
|
+
*/
|
|
85
|
+
readAll(target, labels) {
|
|
86
|
+
for (const [key, label] of Object.entries(labels)) if (label != null) this.readOne(target, key, label);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Overwrite several UUID fields from the UUIDs labeled OCHRE properties
|
|
90
|
+
* point at
|
|
91
|
+
*
|
|
92
|
+
* The same shape as {@link readAll}, for the fields that take the value's
|
|
93
|
+
* target rather than its content.
|
|
94
|
+
* @param target - The object holding the fields, pre-filled with defaults
|
|
95
|
+
* @param labels - The OCHRE property label for each field to overwrite
|
|
96
|
+
*/
|
|
97
|
+
readAllUuids(target, labels) {
|
|
98
|
+
for (const [key, label] of Object.entries(labels)) if (label != null) target[key] = this.uuid(label) ?? target[key];
|
|
99
|
+
}
|
|
52
100
|
nested(label) {
|
|
53
101
|
return new WebsitePresentationReader(this.property(label)?.properties ?? []);
|
|
54
102
|
}
|
|
@@ -58,9 +106,6 @@ var WebsitePresentationReader = class WebsitePresentationReader {
|
|
|
58
106
|
get size() {
|
|
59
107
|
return this.sourceProperties.length;
|
|
60
108
|
}
|
|
61
|
-
get properties() {
|
|
62
|
-
return this.sourceProperties;
|
|
63
|
-
}
|
|
64
109
|
};
|
|
65
110
|
function websitePresentationReader(properties) {
|
|
66
111
|
return new WebsitePresentationReader(properties);
|