ochre-sdk 1.0.79 → 1.1.1

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.
Files changed (84) hide show
  1. package/README.md +60 -3
  2. package/dist/_virtual/_rolldown/runtime.mjs +13 -0
  3. package/dist/categories.d.mts +249 -0
  4. package/dist/categories.mjs +259 -0
  5. package/dist/constants.d.mts +14 -0
  6. package/dist/constants.mjs +18 -1
  7. package/dist/errors.d.mts +23 -0
  8. package/dist/{utilities.mjs → errors.mjs} +33 -84
  9. package/dist/fetchers/gallery.mjs +15 -51
  10. package/dist/fetchers/item-children.mjs +20 -66
  11. package/dist/fetchers/item-links.mjs +26 -79
  12. package/dist/fetchers/item-ocr-data.d.mts +2 -2
  13. package/dist/fetchers/item-ocr-data.mjs +11 -15
  14. package/dist/fetchers/item.d.mts +0 -15
  15. package/dist/fetchers/item.mjs +20 -72
  16. package/dist/fetchers/request.d.mts +70 -0
  17. package/dist/fetchers/request.mjs +100 -0
  18. package/dist/fetchers/set/items.mjs +27 -73
  19. package/dist/fetchers/set/property-values.d.mts +2 -3
  20. package/dist/fetchers/set/property-values.mjs +96 -130
  21. package/dist/fetchers/website-metadata.mjs +35 -57
  22. package/dist/fetchers/website.d.mts +2 -3
  23. package/dist/fetchers/website.mjs +22 -31
  24. package/dist/getters.d.mts +86 -145
  25. package/dist/getters.mjs +136 -207
  26. package/dist/helpers.d.mts +0 -4
  27. package/dist/helpers.mjs +19 -6
  28. package/dist/index.d.mts +8 -6
  29. package/dist/index.mjs +6 -4
  30. package/dist/ocr.d.mts +37 -0
  31. package/dist/ocr.mjs +52 -0
  32. package/dist/parsers/helpers.d.mts +21 -1
  33. package/dist/parsers/helpers.mjs +26 -6
  34. package/dist/parsers/index.d.mts +0 -8
  35. package/dist/parsers/index.mjs +118 -259
  36. package/dist/parsers/languages.d.mts +72 -0
  37. package/dist/parsers/languages.mjs +132 -0
  38. package/dist/parsers/multilingual.d.mts +134 -58
  39. package/dist/parsers/multilingual.mjs +191 -143
  40. package/dist/parsers/property-token.d.mts +34 -0
  41. package/dist/parsers/property-token.mjs +29 -0
  42. package/dist/parsers/string.d.mts +19 -0
  43. package/dist/parsers/string.mjs +45 -25
  44. package/dist/parsers/website/bounds.d.mts +10 -0
  45. package/dist/parsers/website/bounds.mjs +28 -0
  46. package/dist/parsers/website/components.d.mts +91 -0
  47. package/dist/parsers/website/components.mjs +681 -0
  48. package/dist/parsers/website/index.d.mts +0 -7
  49. package/dist/parsers/website/index.mjs +92 -1153
  50. package/dist/parsers/website/links.d.mts +36 -0
  51. package/dist/parsers/website/links.mjs +58 -0
  52. package/dist/parsers/website/messages.d.mts +24 -0
  53. package/dist/parsers/website/messages.mjs +31 -0
  54. package/dist/parsers/website/options.d.mts +6 -0
  55. package/dist/parsers/website/options.mjs +114 -0
  56. package/dist/parsers/website/properties.d.mts +12 -0
  57. package/dist/parsers/website/properties.mjs +158 -0
  58. package/dist/parsers/website/reader.d.mts +54 -4
  59. package/dist/parsers/website/reader.mjs +65 -20
  60. package/dist/parsers/website/slug.d.mts +64 -0
  61. package/dist/parsers/website/slug.mjs +82 -0
  62. package/dist/parsers/website/styles.d.mts +28 -0
  63. package/dist/parsers/website/styles.mjs +103 -0
  64. package/dist/parsers/website/walk.d.mts +68 -0
  65. package/dist/parsers/website/walk.mjs +116 -0
  66. package/dist/query.d.mts +66 -21
  67. package/dist/query.mjs +178 -44
  68. package/dist/reflection.d.mts +64 -0
  69. package/dist/reflection.mjs +79 -0
  70. package/dist/schemas.d.mts +7 -0
  71. package/dist/schemas.mjs +12 -3
  72. package/dist/types/index.d.mts +31 -31
  73. package/dist/types/utilities.d.mts +9 -0
  74. package/dist/types/utilities.mjs +1 -0
  75. package/dist/types/website.d.mts +54 -58
  76. package/dist/xml/metadata.d.mts +16 -0
  77. package/dist/xml/metadata.mjs +32 -11
  78. package/dist/xml/schemas.d.mts +5970 -3
  79. package/dist/xml/schemas.mjs +43 -45
  80. package/dist/xml/types.d.mts +14 -30
  81. package/dist/xquery.d.mts +46 -0
  82. package/dist/xquery.mjs +66 -0
  83. package/package.json +3 -3
  84. package/dist/utilities.d.mts +0 -54
@@ -1,8 +1,12 @@
1
- import { DEFAULT_LANGUAGES } from "../constants.mjs";
2
- import { MultilingualString } from "./multilingual.mjs";
1
+ import { CONTEXT_CATEGORY_ALIASES, ITEM_CATEGORY_BY_ALIAS, ITEM_CATEGORY_FACTS, SET_ITEM_CATEGORIES, isHeadingItemCategory, normalizeItemCategory } from "../categories.mjs";
2
+ import { readEntries, readProperty } from "../reflection.mjs";
3
3
  import { getXMLSourceIndex } from "../xml/metadata.mjs";
4
+ import { MultilingualString } from "./multilingual.mjs";
5
+ import { readPropertyValueText } from "./property-token.mjs";
4
6
  import { parseXMLString, transformPermanentIdentificationUrl } from "./string.mjs";
5
7
  import { getParserOptions, multilingualFromText, parseContentLike, parseContentLikeText, parseLicense, parseRequiredContentLike, parseStringLike } from "./helpers.mjs";
8
+ import { parseMetadataLanguages, resolveDefaultLanguage, resolveLanguages } from "./languages.mjs";
9
+ import * as v from "valibot";
6
10
  //#region src/parsers/index.ts
7
11
  function isXMLContextGroup(context) {
8
12
  return "context" in context;
@@ -10,68 +14,82 @@ function isXMLContextGroup(context) {
10
14
  function isXMLContextItem(context) {
11
15
  return "project" in context;
12
16
  }
13
- const SET_ITEM_CATEGORIES = ["tree", ...[
14
- "bibliography",
15
- "concept",
16
- "spatialUnit",
17
- "period",
18
- "person",
19
- "propertyVariable",
20
- "propertyValue",
21
- "resource",
22
- "text",
23
- "set"
24
- ]];
25
- const HEADING_ITEM_CATEGORIES = [
26
- "person",
27
- "propertyVariable",
28
- "propertyValue",
29
- "resource",
30
- "text",
31
- "set"
32
- ];
33
- const CONTEXT_CATEGORY_MAPPINGS = [
34
- {
35
- raw: "bibliography",
36
- parsed: "bibliography"
17
+ const ITEM_CATEGORIES = {
18
+ tree: {
19
+ parseEmbedded: (item, options) => parseTree(item, {
20
+ ...options,
21
+ containedItemCategory: normalizeTreeItemCategory(options.containedItemCategory)
22
+ }),
23
+ parseSetItem: (item, options) => parseSetTree(item, options),
24
+ parseLink: (item, options) => parseTreeItemLink(item, options)
25
+ },
26
+ bibliography: {
27
+ parseEmbedded: (item, options) => parseBibliography(item, options),
28
+ parseSetItem: (item, options) => parseSetBibliography(item, options),
29
+ parseLink: (item, options) => parseBibliographyItemLink(item, options)
30
+ },
31
+ concept: {
32
+ parseEmbedded: (item, options) => parseConcept(item, options),
33
+ parseSetItem: (item, options) => parseSetConcept(item, options),
34
+ parseLink: (item, options) => parseConceptItemLink(item, options)
35
+ },
36
+ spatialUnit: {
37
+ parseEmbedded: (item, options) => parseSpatialUnit(item, options),
38
+ parseSetItem: (item, options) => parseSetSpatialUnit(item, options),
39
+ parseLink: (item, options) => parseSpatialUnitItemLink(item, options)
37
40
  },
38
- {
39
- raw: "concept",
40
- parsed: "concept"
41
+ period: {
42
+ parseEmbedded: (item, options) => parsePeriod(item, options),
43
+ parseSetItem: (item, options) => parseSetPeriod(item, options),
44
+ parseLink: (item, options) => parsePeriodItemLink(item, options)
41
45
  },
42
- {
43
- raw: "spatialUnit",
44
- parsed: "spatialUnit"
46
+ person: {
47
+ parseEmbedded: (item, options) => parsePerson(item, options),
48
+ parseSetItem: (item, options) => {
49
+ const person = item;
50
+ return withSetItemProperties(parsePerson(person, options), person.properties, options);
51
+ },
52
+ parseLink: (item, options) => parsePersonItemLink(item, options)
45
53
  },
46
- {
47
- raw: "period",
48
- parsed: "period"
54
+ propertyVariable: {
55
+ parseEmbedded: (item, options) => parsePropertyVariable(item, options),
56
+ parseSetItem: (item, options) => parsePropertyVariable(item, options),
57
+ parseLink: (item, options) => parsePropertyVariableItemLink(item, options)
49
58
  },
50
- {
51
- raw: "propertyVariable",
52
- parsed: "propertyVariable"
59
+ propertyValue: {
60
+ parseEmbedded: (item, options) => parsePropertyValue(item, options),
61
+ parseSetItem: (item, options) => {
62
+ const propertyValue = item;
63
+ return withSetItemProperties(parsePropertyValue(propertyValue, options), propertyValue.properties, options);
64
+ },
65
+ parseLink: (item, options) => parsePropertyValueItemLink(item, options)
53
66
  },
54
- {
55
- raw: "variable",
56
- parsed: "propertyVariable"
67
+ resource: {
68
+ parseEmbedded: (item, options) => parseResource(item, options),
69
+ parseSetItem: (item, options) => parseSetResource(item, options),
70
+ parseLink: (item, options) => parseResourceItemLink(item, options)
57
71
  },
58
- {
59
- raw: "propertyValue",
60
- parsed: "propertyValue"
72
+ text: {
73
+ parseEmbedded: (item, options) => parseText(item, options),
74
+ parseSetItem: (item, options) => parseText(item, options),
75
+ parseLink: (item, options) => parseTextItemLink(item, options)
61
76
  },
62
- {
63
- raw: "value",
64
- parsed: "propertyValue"
77
+ set: {
78
+ parseEmbedded: (item, options) => parseSet(item, options),
79
+ parseSetItem: (item, options) => parseSetSet(item, options),
80
+ parseLink: (item, options) => parseSetItemLink(item, options)
65
81
  },
66
- {
67
- raw: "resource",
68
- parsed: "resource"
82
+ dictionaryUnit: {
83
+ parseEmbedded: null,
84
+ parseSetItem: null,
85
+ parseLink: (item, options) => parseDictionaryUnitItemLink(item, options)
69
86
  },
70
- {
71
- raw: "text",
72
- parsed: "text"
87
+ heading: {
88
+ parseEmbedded: null,
89
+ parseSetItem: null,
90
+ parseLink: null
73
91
  }
74
- ];
92
+ };
75
93
  const PROPERTY_DATA_TYPES = [
76
94
  "string",
77
95
  "coordinate",
@@ -128,12 +146,12 @@ function parseContextNode(rawContextItem) {
128
146
  };
129
147
  const headings = rawContextItem.heading ?? [];
130
148
  for (const heading of headings) node.heading.push(parseContextItem(heading));
131
- for (const { raw, parsed } of CONTEXT_CATEGORY_MAPPINGS) {
132
- const contextValues = rawContextItem[raw] ?? [];
149
+ for (const { alias, category } of CONTEXT_CATEGORY_ALIASES) {
150
+ const contextValues = rawContextItem[alias] ?? [];
133
151
  for (const contextValue of contextValues) {
134
- const parsedItems = node[parsed] ?? [];
152
+ const parsedItems = node[category] ?? [];
135
153
  parsedItems.push(parseContextItem(contextValue));
136
- node[parsed] = parsedItems;
154
+ node[category] = parsedItems;
137
155
  }
138
156
  }
139
157
  return node;
@@ -176,7 +194,7 @@ function parseEvent(rawEvent, options) {
176
194
  location: parseEventReference(rawEvent.location, options),
177
195
  other: rawEvent.other == null ? null : {
178
196
  uuid: rawEvent.other.uuid ?? null,
179
- category: normalizeCategory(rawEvent.other.category),
197
+ category: normalizeItemCategory(rawEvent.other.category),
180
198
  label: parseRequiredContentLike(rawEvent.other, options)
181
199
  }
182
200
  };
@@ -202,44 +220,26 @@ function parseBaseItem(category, rawItem, options) {
202
220
  events
203
221
  };
204
222
  }
205
- function normalizeCategory(category) {
206
- if (category == null) return null;
207
- if (category === "variable") return "propertyVariable";
208
- if (category === "value") return "propertyValue";
209
- for (const knownCategory of SET_ITEM_CATEGORIES) if (category === knownCategory) return knownCategory;
210
- return null;
211
- }
212
- function isHeadingItemCategory(category) {
213
- return HEADING_ITEM_CATEGORIES.includes(category);
214
- }
215
223
  function pushCategory(categories, category) {
216
224
  if (!categories.includes(category)) categories.push(category);
217
225
  }
218
226
  function getHierarchyEntryCategory(key) {
219
- switch (key) {
220
- case "heading":
221
- case "tree":
222
- case "bibliography":
223
- case "concept":
224
- case "spatialUnit":
225
- case "period":
226
- case "person":
227
- case "resource":
228
- case "text":
229
- case "set":
230
- case "dictionaryUnit": return key;
231
- case "propertyVariable":
232
- case "variable": return "propertyVariable";
233
- case "propertyValue":
234
- case "value": return "propertyValue";
235
- default: return null;
236
- }
237
- }
238
- function isRecord(value) {
239
- return typeof value === "object" && value != null;
240
- }
227
+ return ITEM_CATEGORY_BY_ALIAS.get(key) ?? null;
228
+ }
229
+ /**
230
+ * A group element wrapping child resources rather than being one itself
231
+ *
232
+ * A schema rather than a hand-written predicate: `v.is` narrows to exactly what
233
+ * it checked, and a wrapper is distinguished from a resource by carrying no
234
+ * `uuid`, which the `undefined` entry states rather than leaving to a
235
+ * `!("uuid" in value)` test whose false branch means nothing in particular.
236
+ */
237
+ const resourceWrapperSchema = v.looseObject({
238
+ uuid: v.undefined(),
239
+ resource: v.array(v.unknown())
240
+ });
241
241
  function isResourceWrapper(value) {
242
- return isRecord(value) && !("uuid" in value) && Array.isArray(value.resource);
242
+ return v.is(resourceWrapperSchema, value);
243
243
  }
244
244
  function sourceOrderSort(left, right) {
245
245
  const leftIndex = getXMLSourceIndex(left.item);
@@ -249,9 +249,8 @@ function sourceOrderSort(left, right) {
249
249
  }
250
250
  function collectHierarchyEntries(hierarchy, categories) {
251
251
  const entries = [];
252
- if (hierarchy == null) return entries;
253
252
  let fallbackIndex = 0;
254
- for (const [key, values] of Object.entries(hierarchy)) {
253
+ for (const [key, values] of readEntries(hierarchy)) {
255
254
  const category = getHierarchyEntryCategory(key);
256
255
  if (category == null || !(categories == null || categories.includes(category))) continue;
257
256
  if (!Array.isArray(values)) continue;
@@ -458,8 +457,7 @@ function parsePropertyDataType(dataType) {
458
457
  function parsePropertyValueContent(value, options) {
459
458
  const dataType = parsePropertyDataType(value.dataType);
460
459
  const rawLabel = value.content != null ? parseRequiredContentLike(value, options) : value.payload != null && value.payload !== "" ? multilingualFromText(value.payload, options) : null;
461
- const displayText = rawLabel?.getText() ?? value.payload ?? value.slug ?? "";
462
- const contentText = value.rawValue ?? value.payload ?? displayText;
460
+ const contentText = readPropertyValueText(value, () => rawLabel?.getText() ?? null);
463
461
  const common = {
464
462
  hierarchy: {
465
463
  isLeaf: value.inherited == null || !value.inherited,
@@ -563,24 +561,8 @@ function withoutItems(item) {
563
561
  return itemWithoutItems;
564
562
  }
565
563
  function parseEmbeddedItemEntry(entry, options) {
566
- switch (entry.category) {
567
- case "tree": return parseTree(entry.item, {
568
- ...options,
569
- containedItemCategory: normalizeTreeItemCategory(options.containedItemCategory)
570
- });
571
- case "bibliography": return parseBibliography(entry.item, options);
572
- case "concept": return parseConcept(entry.item, options);
573
- case "spatialUnit": return parseSpatialUnit(entry.item, options);
574
- case "period": return parsePeriod(entry.item, options);
575
- case "person": return parsePerson(entry.item, options);
576
- case "propertyVariable": return parsePropertyVariable(entry.item, options);
577
- case "propertyValue": return parsePropertyValue(entry.item, options);
578
- case "resource": return parseResource(entry.item, options);
579
- case "text": return parseText(entry.item, options);
580
- case "set": return parseSet(entry.item, options);
581
- case "dictionaryUnit":
582
- case "heading": return null;
583
- }
564
+ const parse = ITEM_CATEGORIES[entry.category].parseEmbedded;
565
+ return parse == null ? null : parse(entry.item, options);
584
566
  }
585
567
  function parseItemHierarchy(hierarchy, options, categories) {
586
568
  const items = [];
@@ -594,52 +576,19 @@ function parseItemHierarchy(hierarchy, options, categories) {
594
576
  function parseSetItemHierarchy(hierarchy, options, categories) {
595
577
  const items = [];
596
578
  if (hierarchy == null) return items;
597
- for (const entry of collectHierarchyEntries(hierarchy, categories)) switch (entry.category) {
598
- case "tree":
599
- items.push(parseSetTree(entry.item, options));
600
- break;
601
- case "bibliography":
602
- items.push(parseSetBibliography(entry.item, options));
603
- break;
604
- case "concept":
605
- items.push(parseSetConcept(entry.item, options));
606
- break;
607
- case "spatialUnit":
608
- items.push(parseSetSpatialUnit(entry.item, options));
609
- break;
610
- case "period":
611
- items.push(parseSetPeriod(entry.item, options));
612
- break;
613
- case "person": {
614
- const person = entry.item;
615
- items.push(withSetItemProperties(parsePerson(person, options), person.properties, options));
616
- break;
617
- }
618
- case "propertyVariable":
619
- items.push(parsePropertyVariable(entry.item, options));
620
- break;
621
- case "propertyValue": {
622
- const propertyValue = entry.item;
623
- items.push(withSetItemProperties(parsePropertyValue(propertyValue, options), propertyValue.properties, options));
624
- break;
625
- }
626
- case "resource":
627
- items.push(parseSetResource(entry.item, options));
628
- break;
629
- case "text":
630
- items.push(parseText(entry.item, options));
631
- break;
632
- case "set": items.push(parseSetSet(entry.item, options));
579
+ for (const entry of collectHierarchyEntries(hierarchy, categories)) {
580
+ const parse = ITEM_CATEGORIES[entry.category].parseSetItem;
581
+ if (parse != null) items.push(parse(entry.item, options));
633
582
  }
634
583
  return items;
635
584
  }
636
585
  function normalizeTreeLinkItemsCategory(type) {
637
- const category = normalizeCategory(type);
586
+ const category = normalizeItemCategory(type);
638
587
  if (category === "tree" || category == null) return null;
639
588
  return category;
640
589
  }
641
590
  function normalizeSetLinkItemsCategory(type) {
642
- const category = normalizeCategory(type);
591
+ const category = normalizeItemCategory(type);
643
592
  return category == null ? null : [category];
644
593
  }
645
594
  function parseBaseItemLink(category, rawItem, options) {
@@ -794,41 +743,9 @@ function parseLinks(rawLinks, options) {
794
743
  const links = [];
795
744
  if (rawLinks == null) return links;
796
745
  const hierarchy = rawLinks;
797
- for (const entry of collectHierarchyEntries(hierarchy)) switch (entry.category) {
798
- case "tree":
799
- links.push(parseTreeItemLink(entry.item, options));
800
- break;
801
- case "bibliography":
802
- links.push(parseBibliographyItemLink(entry.item, options));
803
- break;
804
- case "concept":
805
- links.push(parseConceptItemLink(entry.item, options));
806
- break;
807
- case "spatialUnit":
808
- links.push(parseSpatialUnitItemLink(entry.item, options));
809
- break;
810
- case "period":
811
- links.push(parsePeriodItemLink(entry.item, options));
812
- break;
813
- case "person":
814
- links.push(parsePersonItemLink(entry.item, options));
815
- break;
816
- case "propertyVariable":
817
- links.push(parsePropertyVariableItemLink(entry.item, options));
818
- break;
819
- case "propertyValue":
820
- links.push(parsePropertyValueItemLink(entry.item, options));
821
- break;
822
- case "resource":
823
- links.push(parseResourceItemLink(entry.item, options));
824
- break;
825
- case "text":
826
- links.push(parseTextItemLink(entry.item, options));
827
- break;
828
- case "set":
829
- links.push(parseSetItemLink(entry.item, options));
830
- break;
831
- case "dictionaryUnit": links.push(parseDictionaryUnitItemLink(entry.item, options));
746
+ for (const entry of collectHierarchyEntries(hierarchy)) {
747
+ const parse = ITEM_CATEGORIES[entry.category].parseLink;
748
+ if (parse != null) links.push(parse(entry.item, options));
832
749
  }
833
750
  return links;
834
751
  }
@@ -1149,37 +1066,6 @@ function parseText(rawText, options) {
1149
1066
  editions
1150
1067
  };
1151
1068
  }
1152
- function parseMetadataLanguages(rawOchre) {
1153
- const languages = [];
1154
- const metadataLanguages = rawOchre.metadata.language ?? [];
1155
- for (const language of metadataLanguages) {
1156
- const parsedLanguage = parseStringLike(language);
1157
- if (parsedLanguage != null) languages.push(parsedLanguage);
1158
- }
1159
- if (languages.length > 0) return languages;
1160
- if (rawOchre.languages != null) {
1161
- for (const language of rawOchre.languages.split(";")) if (language !== "") languages.push(language);
1162
- }
1163
- return languages.length > 0 ? languages : [...DEFAULT_LANGUAGES];
1164
- }
1165
- function resolveLanguages(requestedLanguages, metadataLanguages) {
1166
- if (requestedLanguages == null || requestedLanguages.length === 0) return metadataLanguages;
1167
- const unsupportedLanguages = [];
1168
- for (const requestedLanguage of requestedLanguages) if (!metadataLanguages.some((metadataLanguage) => metadataLanguage.toLocaleLowerCase("en-US") === requestedLanguage.toLocaleLowerCase("en-US"))) unsupportedLanguages.push(requestedLanguage);
1169
- if (unsupportedLanguages.length > 0) throw new Error(`The following language(s) are not supported by the dataset: ${unsupportedLanguages.toSorted((a, b) => a.localeCompare(b, "en-US")).join(", ")}. Available languages: ${metadataLanguages.toSorted((a, b) => a.localeCompare(b, "en-US")).join(", ")}`, { cause: unsupportedLanguages });
1170
- return requestedLanguages;
1171
- }
1172
- function resolveDefaultLanguage(rawOchre, languages) {
1173
- const metadataLanguages = rawOchre.metadata.language ?? [];
1174
- for (const language of metadataLanguages) {
1175
- const parsedLanguage = parseStringLike(language);
1176
- if (parsedLanguage != null && language.default === "true" && languages.includes(parsedLanguage)) return parsedLanguage;
1177
- }
1178
- for (const language of languages) if (language === DEFAULT_LANGUAGES[0]) return language;
1179
- const firstLanguage = languages[0];
1180
- if (firstLanguage == null) throw new Error("Default language not found", { cause: languages });
1181
- return firstLanguage;
1182
- }
1183
1069
  function parseMetadataPublisher(rawPublisher) {
1184
1070
  const publisher = Array.isArray(rawPublisher) ? rawPublisher[0] : rawPublisher;
1185
1071
  return parseStringLike(publisher) ?? "";
@@ -1211,7 +1097,7 @@ function parseMetadata(rawOchre, options, defaultLanguage) {
1211
1097
  },
1212
1098
  item: rawMetadata.item == null ? null : {
1213
1099
  identification: parseIdentification(rawMetadata.item.identification, metadataOptions),
1214
- category: normalizeCategory(rawMetadata.item.category) ?? rawMetadata.item.category,
1100
+ category: normalizeItemCategory(rawMetadata.item.category) ?? rawMetadata.item.category,
1215
1101
  type: rawMetadata.item.type,
1216
1102
  maxLength: rawMetadata.item.maxLength ?? null
1217
1103
  },
@@ -1231,45 +1117,17 @@ function getSingleTopLevelRawItem(items, category) {
1231
1117
  return items[0];
1232
1118
  }
1233
1119
  function parseTopLevelItem(rawOchre, category, options) {
1234
- const rawItems = rawOchre;
1235
- let parsedItem;
1236
- switch (category) {
1237
- case "tree":
1238
- parsedItem = parseTree(getSingleTopLevelRawItem(rawItems.tree, "tree"), {
1239
- ...options,
1240
- containedItemCategory: normalizeTreeItemCategory(options.containedItemCategory)
1241
- });
1242
- break;
1243
- case "bibliography":
1244
- parsedItem = parseBibliography(getSingleTopLevelRawItem(rawItems.bibliography, "bibliography"), options);
1245
- break;
1246
- case "concept":
1247
- parsedItem = parseConcept(getSingleTopLevelRawItem(rawItems.concept, "concept"), options);
1248
- break;
1249
- case "spatialUnit":
1250
- parsedItem = parseSpatialUnit(getSingleTopLevelRawItem(rawItems.spatialUnit, "spatial unit"), options);
1251
- break;
1252
- case "period":
1253
- parsedItem = parsePeriod(getSingleTopLevelRawItem(rawItems.period, "period"), options);
1254
- break;
1255
- case "person":
1256
- parsedItem = parsePerson(getSingleTopLevelRawItem(rawItems.person, "person"), options);
1257
- break;
1258
- case "propertyVariable":
1259
- parsedItem = parsePropertyVariable(getSingleTopLevelRawItem(rawItems.propertyVariable ?? rawItems.variable, "property variable"), options);
1120
+ const entry = ITEM_CATEGORIES[category];
1121
+ const facts = ITEM_CATEGORY_FACTS[category];
1122
+ let rawCategoryItems;
1123
+ for (const alias of facts.aliases) {
1124
+ const aliasItems = readProperty(rawOchre, alias);
1125
+ if (Array.isArray(aliasItems)) {
1126
+ rawCategoryItems = aliasItems;
1260
1127
  break;
1261
- case "propertyValue":
1262
- parsedItem = parsePropertyValue(getSingleTopLevelRawItem(rawItems.propertyValue ?? rawItems.value, "property value"), options);
1263
- break;
1264
- case "resource":
1265
- parsedItem = parseResource(getSingleTopLevelRawItem(rawItems.resource, "resource"), options);
1266
- break;
1267
- case "text":
1268
- parsedItem = parseText(getSingleTopLevelRawItem(rawItems.text, "text"), options);
1269
- break;
1270
- case "set": parsedItem = parseSet(getSingleTopLevelRawItem(rawItems.set, "set"), options);
1128
+ }
1271
1129
  }
1272
- return parsedItem;
1130
+ return entry.parseEmbedded(getSingleTopLevelRawItem(rawCategoryItems, facts.label), options);
1273
1131
  }
1274
1132
  function parseLinkedItems(rawItems, options) {
1275
1133
  const parserOptions = {
@@ -1300,11 +1158,13 @@ function parseItem(rawData, options) {
1300
1158
  const rawOchre = rawData.result.ochre;
1301
1159
  const metadataLanguages = parseMetadataLanguages(rawOchre);
1302
1160
  const languagesToUse = resolveLanguages(options.languages, metadataLanguages);
1161
+ const defaultLanguage = resolveDefaultLanguage(rawOchre, languagesToUse);
1303
1162
  const parserOptions = {
1304
1163
  languages: languagesToUse,
1164
+ defaultLanguage,
1305
1165
  containedItemCategory: options.containedItemCategory
1306
1166
  };
1307
- const inferredCategory = normalizeCategory(rawOchre.metadata.item?.category) ?? inferTopLevelCategory(rawOchre);
1167
+ const inferredCategory = normalizeItemCategory(rawOchre.metadata.item?.category) ?? inferTopLevelCategory(rawOchre);
1308
1168
  let category = inferredCategory;
1309
1169
  if (options.category != null) {
1310
1170
  if (typeof options.category === "string") category = options.category;
@@ -1313,7 +1173,6 @@ function parseItem(rawData, options) {
1313
1173
  categories: options.category
1314
1174
  } });
1315
1175
  }
1316
- const defaultLanguage = resolveDefaultLanguage(rawOchre, languagesToUse);
1317
1176
  const belongsTo = {
1318
1177
  uuid: rawOchre.uuidBelongsTo,
1319
1178
  abbreviation: rawOchre.belongsTo
@@ -1342,4 +1201,4 @@ function parseItem(rawData, options) {
1342
1201
  };
1343
1202
  }
1344
1203
  //#endregion
1345
- export { getParserOptions, parseBibliographyList, parseGallery, parseIdentification, parseItem, parseLinkedItems, parseLinks, parseMetadata, parseMetadataLanguages, parseNotes, parsePersonList, parseProperties, parseSetItems, parseSimplifiedProperties, parseStringLike, resolveDefaultLanguage, resolveLanguages };
1204
+ export { getParserOptions, parseBibliographyList, parseGallery, parseIdentification, parseItem, parseLinkedItems, parseLinks, parseMetadata, parseNotes, parsePersonList, parseProperties, parseSetItems, parseSimplifiedProperties, parseStringLike };
@@ -0,0 +1,72 @@
1
+ import { XMLMetadata } from "../xml/types.mjs";
2
+ //#region src/parsers/languages.d.ts
3
+ /**
4
+ * Validate language codes while preserving literal tuple inference
5
+ * @param languages - The language codes to validate
6
+ * @returns The same tuple, with its literal types intact
7
+ * @internal
8
+ */
9
+ export declare function parseLanguages<const T extends ReadonlyArray<string>>(languages: T): T;
10
+ /**
11
+ * Define a reusable languages tuple with validation and literal type inference
12
+ *
13
+ * Inline arrays can be passed directly to a fetcher
14
+ * (`fetchItem(uuid, { languages: ["eng", "spa"] })`); use this when the
15
+ * language set is stored separately.
16
+ * @param languages - The language codes to validate
17
+ * @returns The same tuple, with its literal types intact
18
+ */
19
+ export declare function defineLanguages<const TLanguages extends ReadonlyArray<string>>(...languages: TLanguages): TLanguages;
20
+ /**
21
+ * Validate an optional caller-supplied language tuple
22
+ * @param languages - The language codes to validate, or undefined
23
+ * @returns The validated codes, or an empty array when none were requested
24
+ * @internal
25
+ */
26
+ export declare function parseRequestedLanguages(languages: ReadonlyArray<string> | undefined): ReadonlyArray<string>;
27
+ /**
28
+ * Resolve which languages to parse from the content of a payload
29
+ *
30
+ * Requested languages win. Otherwise every `content/@xml:lang` found anywhere
31
+ * beneath the node is used, falling back to {@link DEFAULT_LANGUAGES} when the
32
+ * payload carries no tagged content at all.
33
+ * @param node - The payload node to walk
34
+ * @param requestedLanguages - The languages the caller asked for
35
+ * @returns The languages to parse
36
+ * @internal
37
+ */
38
+ export declare function resolveContentLanguages(node: unknown, requestedLanguages: ReadonlyArray<string>): ReadonlyArray<string>;
39
+ /**
40
+ * Read the languages a dataset declares in its metadata
41
+ * @param rawOchre - The raw OCHRE payload root
42
+ * @param rawOchre.metadata - The payload metadata declaring the languages
43
+ * @param rawOchre.languages - The semicolon-separated fallback language list
44
+ * @returns The declared languages, falling back to {@link DEFAULT_LANGUAGES}
45
+ * @internal
46
+ */
47
+ export declare function parseMetadataLanguages(rawOchre: {
48
+ metadata: XMLMetadata;
49
+ languages?: string;
50
+ }): Array<string>;
51
+ /**
52
+ * Reconcile requested languages against the ones a dataset declares
53
+ * @param requestedLanguages - The languages the caller asked for
54
+ * @param metadataLanguages - The languages the dataset declares
55
+ * @returns The languages to parse
56
+ * @throws When a requested language is not offered by the dataset
57
+ * @internal
58
+ */
59
+ export declare function resolveLanguages<T extends ReadonlyArray<string>>(requestedLanguages: T | undefined, metadataLanguages: Array<string>): T;
60
+ /**
61
+ * Pick the language a dataset treats as its default
62
+ * @param rawOchre - The raw OCHRE payload root
63
+ * @param rawOchre.metadata - The payload metadata declaring the default
64
+ * @param languages - The languages being parsed
65
+ * @returns The default language
66
+ * @throws When `languages` is empty
67
+ * @internal
68
+ */
69
+ export declare function resolveDefaultLanguage<T extends ReadonlyArray<string>>(rawOchre: {
70
+ metadata: XMLMetadata;
71
+ }, languages: T): T[number];
72
+ //#endregion