@digitalculture/ochre-sdk 0.4.14 → 0.5.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 CHANGED
@@ -25,7 +25,7 @@ bun add @digitalculture/ochre-sdk
25
25
  From the root directory of the project, run the following command:
26
26
 
27
27
  ```bash
28
- pnpm run dev:ochre-sdk
28
+ pnpm run dev
29
29
  ```
30
30
 
31
31
  ## Build production server
package/dist/index.cjs CHANGED
@@ -42,7 +42,7 @@ __export(index_exports, {
42
42
  parseContext: () => parseContext,
43
43
  parseCoordinates: () => parseCoordinates,
44
44
  parseDocument: () => parseDocument,
45
- parseEmailAndUrl: () => parseEmailAndUrl,
45
+ parseEmail: () => parseEmail,
46
46
  parseEvents: () => parseEvents,
47
47
  parseFakeString: () => parseFakeString,
48
48
  parseIdentification: () => parseIdentification,
@@ -76,7 +76,6 @@ __export(index_exports, {
76
76
  module.exports = __toCommonJS(index_exports);
77
77
 
78
78
  // src/utils/parse.ts
79
- var import_uuid = require("uuid");
80
79
  var import_zod3 = require("zod");
81
80
 
82
81
  // src/utils/fetchers/generic.ts
@@ -125,21 +124,11 @@ var whitespaceSchema = import_zod2.z.string().transform((str) => str.split(" "))
125
124
  )
126
125
  );
127
126
  var emailSchema = import_zod2.z.string().email({ message: "Invalid email" });
128
- var urlSchema = import_zod2.z.string().refine((v) => v ? isUrlValid(v) : false, {
129
- message: "Invalid URL"
130
- });
131
- function isUrlValid(url) {
132
- const pattern = (
133
- // eslint-disable-next-line regexp/no-useless-quantifier, regexp/no-unused-capturing-group
134
- /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\w$&+,:;=-]+@)?[\d.A-Za-z-]+(:\d+)?|(?:www.|[\w$&+,:;=-]+@)[\d.A-Za-z-]+)((?:\/[\w%+./~-]*)?\??[\w%&+.;=@-]*#?\w*)?)/
135
- );
136
- return !!pattern.test(url);
137
- }
138
127
  function getStringItemByLanguage(content, language) {
139
128
  const stringItemToFind = content.find((item) => item.lang === language);
140
129
  return stringItemToFind ?? null;
141
130
  }
142
- function parseEmailAndUrl(string) {
131
+ function parseEmail(string) {
143
132
  const splitString = string.split(" ");
144
133
  const returnSplitString = [];
145
134
  for (const string2 of splitString) {
@@ -155,13 +144,6 @@ function parseEmailAndUrl(string) {
155
144
  );
156
145
  continue;
157
146
  }
158
- const isUrl = urlSchema.safeParse(cleanString).success;
159
- if (isUrl) {
160
- returnSplitString.push(
161
- `${before}<ExternalLink href="${cleanString}">${cleanString}</ExternalLink>${after}`
162
- );
163
- continue;
164
- }
165
147
  returnSplitString.push(string2);
166
148
  }
167
149
  return returnSplitString.join(" ");
@@ -265,7 +247,7 @@ function parseStringItem(item) {
265
247
  }
266
248
  function parseStringDocumentItem(item, footnotes) {
267
249
  if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") {
268
- return parseEmailAndUrl(parseFakeString(item));
250
+ return parseEmail(parseFakeString(item));
269
251
  }
270
252
  if ("whitespace" in item && !("content" in item) && !("string" in item)) {
271
253
  if (item.whitespace === "newline") {
@@ -371,25 +353,16 @@ function parseStringDocumentItem(item, footnotes) {
371
353
  returnString += parseStringDocumentItem(stringItem, footnotes);
372
354
  }
373
355
  if ("whitespace" in item && item.whitespace != null) {
374
- returnString = parseWhitespace(
375
- parseEmailAndUrl(returnString),
376
- item.whitespace
377
- );
356
+ returnString = parseWhitespace(parseEmail(returnString), item.whitespace);
378
357
  }
379
358
  return returnString.replaceAll("&#39;", "'").replaceAll(/^(\d+)\./gm, String.raw`$1\.`);
380
359
  } else {
381
360
  returnString = parseFakeString(item.content);
382
361
  if (item.rend != null) {
383
- returnString = parseRenderOptions(
384
- parseEmailAndUrl(returnString),
385
- item.rend
386
- );
362
+ returnString = parseRenderOptions(parseEmail(returnString), item.rend);
387
363
  }
388
364
  if (item.whitespace != null) {
389
- returnString = parseWhitespace(
390
- parseEmailAndUrl(returnString),
391
- item.whitespace
392
- );
365
+ returnString = parseWhitespace(parseEmail(returnString), item.whitespace);
393
366
  }
394
367
  }
395
368
  return returnString.replaceAll(/^(\d+)\./gm, String.raw`$1\.`);
@@ -786,9 +759,7 @@ function parseDocument(document, language = "eng") {
786
759
  const footnotes = [];
787
760
  const documentWithLanguage = Array.isArray(document) ? document.find((doc) => doc.lang === language) : document;
788
761
  if (typeof documentWithLanguage.string === "string" || typeof documentWithLanguage.string === "number" || typeof documentWithLanguage.string === "boolean") {
789
- returnString += parseEmailAndUrl(
790
- parseFakeString(documentWithLanguage.string)
791
- );
762
+ returnString += parseEmail(parseFakeString(documentWithLanguage.string));
792
763
  } else {
793
764
  const documentItems = Array.isArray(documentWithLanguage.string) ? documentWithLanguage.string : [documentWithLanguage.string];
794
765
  for (const item of documentItems) {
@@ -840,9 +811,9 @@ function parseNotes(notes, language = "eng") {
840
811
  }
841
812
  }
842
813
  if (typeof noteWithLanguage.string === "string" || typeof noteWithLanguage.string === "number" || typeof noteWithLanguage.string === "boolean") {
843
- content = parseEmailAndUrl(parseFakeString(noteWithLanguage.string));
814
+ content = parseEmail(parseFakeString(noteWithLanguage.string));
844
815
  } else {
845
- content = parseEmailAndUrl(parseDocument(noteWithLanguage).content);
816
+ content = parseEmail(parseDocument(noteWithLanguage).content);
846
817
  }
847
818
  returnNotes.push({
848
819
  number: note.noteNo,
@@ -1335,10 +1306,7 @@ var parseWebpageResources = async (webpageResources, type) => {
1335
1306
  if (!resourceProperty) continue;
1336
1307
  switch (type) {
1337
1308
  case "element": {
1338
- const element = await parseWebElement(
1339
- resource,
1340
- resourceProperty.properties
1341
- );
1309
+ const element = await parseWebElement(resource);
1342
1310
  returnElements.push(
1343
1311
  element
1344
1312
  );
@@ -1865,9 +1833,20 @@ async function parseWebElementProperties(componentProperty, elementResource) {
1865
1833
  }
1866
1834
  return properties;
1867
1835
  }
1868
- async function parseWebElement(elementResource, elementProperties) {
1836
+ async function parseWebElement(elementResource) {
1869
1837
  const identification = parseIdentification(elementResource.identification);
1870
- const componentProperty = elementProperties.find(
1838
+ const elementProperties = elementResource.properties?.property ? parseProperties(
1839
+ Array.isArray(elementResource.properties.property) ? elementResource.properties.property : [elementResource.properties.property]
1840
+ ) : [];
1841
+ const presentationProperty = elementProperties.find(
1842
+ (property) => property.label === "presentation"
1843
+ );
1844
+ if (!presentationProperty) {
1845
+ throw new Error(
1846
+ `Presentation property not found for element \u201C${identification.label}\u201D`
1847
+ );
1848
+ }
1849
+ const componentProperty = presentationProperty.properties.find(
1871
1850
  (property) => property.label === "component"
1872
1851
  );
1873
1852
  if (!componentProperty) {
@@ -1931,6 +1910,7 @@ async function parseWebElement(elementResource, elementProperties) {
1931
1910
  }
1932
1911
  return {
1933
1912
  uuid: elementResource.uuid,
1913
+ type: "element",
1934
1914
  title: {
1935
1915
  label: identification.label,
1936
1916
  variant,
@@ -1965,8 +1945,7 @@ async function parseWebpage(webpageResource) {
1965
1945
  (link) => link.type === "image" || link.type === "IIIF"
1966
1946
  );
1967
1947
  const webpageResources = webpageResource.resource ? Array.isArray(webpageResource.resource) ? webpageResource.resource : [webpageResource.resource] : [];
1968
- const blocks = [];
1969
- let elementsToHandle = [];
1948
+ const items = [];
1970
1949
  for (const resource of webpageResources) {
1971
1950
  const resourceProperties = resource.properties ? parseProperties(
1972
1951
  Array.isArray(resource.properties.property) ? resource.properties.property : [resource.properties.property]
@@ -1978,55 +1957,21 @@ async function parseWebpage(webpageResource) {
1978
1957
  if (!resourceType) {
1979
1958
  continue;
1980
1959
  }
1981
- if (resourceType === "element") {
1982
- elementsToHandle.push(resource);
1983
- } else if (resourceType === "block") {
1984
- if (elementsToHandle.length > 0) {
1985
- const elements = await parseWebpageResources(
1986
- elementsToHandle,
1987
- "element"
1988
- );
1989
- const block = {
1990
- uuid: (0, import_uuid.v4)(),
1991
- layout: "vertical",
1992
- blocks: [],
1993
- elements,
1994
- properties: {
1995
- spacing: void 0,
1996
- gap: void 0,
1997
- alignItems: "start",
1998
- justifyContent: "stretch"
1999
- },
2000
- propertiesMobile: null,
2001
- cssStyles: [],
2002
- cssStylesMobile: []
2003
- };
2004
- blocks.push(block);
2005
- elementsToHandle = [];
1960
+ switch (resourceType) {
1961
+ case "element": {
1962
+ const element = await parseWebElement(resource);
1963
+ items.push(element);
1964
+ break;
1965
+ }
1966
+ case "block": {
1967
+ const block = await parseBlock(resource);
1968
+ if (block) {
1969
+ items.push(block);
1970
+ }
1971
+ break;
2006
1972
  }
2007
- const parsedBlocks = await parseWebpageResources([resource], "block");
2008
- blocks.push(...parsedBlocks);
2009
1973
  }
2010
1974
  }
2011
- if (elementsToHandle.length > 0) {
2012
- const elements = await parseWebpageResources(elementsToHandle, "element");
2013
- const block = {
2014
- uuid: (0, import_uuid.v4)(),
2015
- layout: "vertical",
2016
- blocks: [],
2017
- elements,
2018
- properties: {
2019
- spacing: void 0,
2020
- gap: void 0,
2021
- alignItems: "start",
2022
- justifyContent: "stretch"
2023
- },
2024
- propertiesMobile: null,
2025
- cssStyles: [],
2026
- cssStylesMobile: []
2027
- };
2028
- blocks.push(block);
2029
- }
2030
1975
  const webpages = webpageResource.resource ? await parseWebpageResources(
2031
1976
  Array.isArray(webpageResource.resource) ? webpageResource.resource : [webpageResource.resource],
2032
1977
  "page"
@@ -2091,7 +2036,7 @@ async function parseWebpage(webpageResource) {
2091
2036
  return {
2092
2037
  title: identification.label,
2093
2038
  slug,
2094
- blocks,
2039
+ items,
2095
2040
  properties: {
2096
2041
  displayedInHeader,
2097
2042
  width,
@@ -2118,9 +2063,9 @@ async function parseWebpages(webpageResources) {
2118
2063
  async function parseBlock(blockResource) {
2119
2064
  const returnBlock = {
2120
2065
  uuid: blockResource.uuid,
2066
+ type: "block",
2121
2067
  layout: "vertical",
2122
- blocks: [],
2123
- elements: [],
2068
+ items: [],
2124
2069
  properties: {
2125
2070
  spacing: void 0,
2126
2071
  gap: void 0,
@@ -2180,20 +2125,35 @@ async function parseBlock(blockResource) {
2180
2125
  returnBlock.propertiesMobile = propertiesMobile;
2181
2126
  }
2182
2127
  }
2183
- const blockBlocks = blockResource.resource ? await parseWebpageResources(
2184
- Array.isArray(blockResource.resource) ? blockResource.resource : [blockResource.resource],
2185
- "block"
2186
- ) : [];
2187
- for (const block of blockBlocks) {
2188
- returnBlock.blocks.push(block);
2189
- }
2190
- const blockElements = blockResource.resource ? await parseWebpageResources(
2191
- Array.isArray(blockResource.resource) ? blockResource.resource : [blockResource.resource],
2192
- "element"
2193
- ) : [];
2194
- for (const element of blockElements) {
2195
- returnBlock.elements.push(element);
2128
+ const blockResources = blockResource.resource ? Array.isArray(blockResource.resource) ? blockResource.resource : [blockResource.resource] : [];
2129
+ const blockItems = [];
2130
+ for (const resource of blockResources) {
2131
+ const resourceProperties = resource.properties ? parseProperties(
2132
+ Array.isArray(resource.properties.property) ? resource.properties.property : [resource.properties.property]
2133
+ ) : [];
2134
+ const resourceType = getPropertyValueByLabel(
2135
+ resourceProperties,
2136
+ "presentation"
2137
+ );
2138
+ if (!resourceType) {
2139
+ continue;
2140
+ }
2141
+ switch (resourceType) {
2142
+ case "element": {
2143
+ const element = await parseWebElement(resource);
2144
+ blockItems.push(element);
2145
+ break;
2146
+ }
2147
+ case "block": {
2148
+ const block = await parseBlock(resource);
2149
+ if (block) {
2150
+ blockItems.push(block);
2151
+ }
2152
+ break;
2153
+ }
2154
+ }
2196
2155
  }
2156
+ returnBlock.items = blockItems;
2197
2157
  const blockCssStyles = blockProperties.find(
2198
2158
  (property) => property.label === "presentation" && property.values[0]?.content === "css"
2199
2159
  )?.properties;
@@ -2427,15 +2387,7 @@ async function parseWebsite(websiteTree, projectName, website) {
2427
2387
  }
2428
2388
  const sidebarResources = sidebarResource.resource ? Array.isArray(sidebarResource.resource) ? sidebarResource.resource : [sidebarResource.resource] : [];
2429
2389
  for (const resource of sidebarResources) {
2430
- const sidebarResourceProperties = resource.properties ? parseProperties(
2431
- Array.isArray(resource.properties.property) ? resource.properties.property : [resource.properties.property]
2432
- ) : [];
2433
- const element = await parseWebElement(
2434
- resource,
2435
- sidebarResourceProperties.find(
2436
- (property) => property.label === "presentation" && property.values[0]?.content === "element"
2437
- )?.properties ?? []
2438
- );
2390
+ const element = await parseWebElement(resource);
2439
2391
  sidebarElements.push(element);
2440
2392
  }
2441
2393
  }
@@ -2743,7 +2695,7 @@ async function fetchWebsite(abbreviation) {
2743
2695
  parseContext,
2744
2696
  parseCoordinates,
2745
2697
  parseDocument,
2746
- parseEmailAndUrl,
2698
+ parseEmail,
2747
2699
  parseEvents,
2748
2700
  parseFakeString,
2749
2701
  parseIdentification,
package/dist/index.d.cts CHANGED
@@ -440,7 +440,7 @@ type Webpage = {
440
440
  title: string;
441
441
  slug: string;
442
442
  properties: WebpageProperties;
443
- blocks: Array<WebBlock>;
443
+ items: Array<WebElement | WebBlock>;
444
444
  webpages: Array<Webpage>;
445
445
  };
446
446
  /**
@@ -460,6 +460,7 @@ type WebpageProperties = {
460
460
  */
461
461
  type WebElement = {
462
462
  uuid: string;
463
+ type: "element";
463
464
  title: {
464
465
  label: string;
465
466
  variant: "default" | "simple";
@@ -588,9 +589,9 @@ type Style = {
588
589
  */
589
590
  type WebBlock = {
590
591
  uuid: string;
592
+ type: "block";
591
593
  layout: "vertical" | "horizontal" | "grid";
592
- blocks: Array<WebBlock>;
593
- elements: Array<WebElement>;
594
+ items: Array<WebElement | WebBlock>;
594
595
  properties: {
595
596
  /**
596
597
  * valid `gridTemplateColumns` or `gridTemplateRows` CSS property value
@@ -1796,19 +1797,18 @@ declare function parseConcepts(concepts: Array<OchreConcept> | Array<OchreNested
1796
1797
  declare function parseWebsite(websiteTree: OchreTree, projectName: FakeString, website: FakeString | null): Promise<Website>;
1797
1798
 
1798
1799
  /**
1799
- * Parses email addresses and URLs in a string into HTML links
1800
+ * Parses email addresses in a string into HTML links
1800
1801
  *
1801
1802
  * @param string - Input string to parse
1802
- * @returns String with emails and URLs converted to HTML links
1803
+ * @returns String with emails converted to HTML links
1803
1804
  *
1804
1805
  * @example
1805
1806
  * ```ts
1806
- * const parsed = parseEmailAndUrl("Contact us at info@example.com or visit www.example.com");
1807
- * // Returns: "Contact us at <ExternalLink href="mailto:info@example.com">info@example.com</ExternalLink>
1808
- * // or visit <ExternalLink href="www.example.com">www.example.com</ExternalLink>"
1807
+ * const parsed = parseEmail("Contact us at info@example.com");
1808
+ * // Returns: "Contact us at <ExternalLink href="mailto:info@example.com">info@example.com</ExternalLink>"
1809
1809
  * ```
1810
1810
  */
1811
- declare function parseEmailAndUrl(string: string): string;
1811
+ declare function parseEmail(string: string): string;
1812
1812
  /**
1813
1813
  * Converts a FakeString (string|number|boolean) to a proper string
1814
1814
  *
@@ -1847,4 +1847,4 @@ declare function parseStringDocumentItem(item: OchreStringRichTextItem, footnote
1847
1847
  */
1848
1848
  declare function parseStringContent(content: OchreStringContent, language?: string): string;
1849
1849
 
1850
- export { type Bibliography, type Concept, type Context, type ContextItem, type ContextNode, type Coordinates, type Data, type Document, type Event, type Footnote, type Gallery, type Identification, type Image, type ImageMap, type ImageMapArea, type Interpretation, type License, type Link, type Metadata, type NestedConcept, type NestedResource, type NestedSpatialUnit, type Note, type Observation, type Period, type Person, type Property, type PropertyValue, type PropertyValueType, type Resource, type Set, type SpatialUnit, type Style, type Tree, type WebBlock, type WebElement, type WebElementComponent, type WebImage, type Webpage, type WebpageProperties, type Website, type WebsiteProperties, fetchBibliography, fetchByUuid, fetchConcept, fetchGallery, fetchPeriod, fetchResource, fetchSet, fetchSpatialUnit, fetchTree, fetchWebsite, filterProperties, getAllPropertyLabels, getPropertyByLabel, getPropertyValueByLabel, getPropertyValuesByLabel, parseBibliographies, parseBibliography, parseConcept, parseConcepts, parseContext, parseCoordinates, parseDocument, parseEmailAndUrl, parseEvents, parseFakeString, parseIdentification, parseImage, parseImageMap, parseInterpretations, parseLanguages, parseLicense, parseLink, parseLinks, parseMetadata, parseNotes, parseObservation, parseObservations, parsePeriod, parsePeriods, parsePerson, parsePersons, parseProperties, parseResource, parseResources, parseSet, parseSpatialUnit, parseSpatialUnits, parseStringContent, parseStringDocumentItem, parseStringItem, parseTree, parseWebsite };
1850
+ export { type Bibliography, type Concept, type Context, type ContextItem, type ContextNode, type Coordinates, type Data, type Document, type Event, type Footnote, type Gallery, type Identification, type Image, type ImageMap, type ImageMapArea, type Interpretation, type License, type Link, type Metadata, type NestedConcept, type NestedResource, type NestedSpatialUnit, type Note, type Observation, type Period, type Person, type Property, type PropertyValue, type PropertyValueType, type Resource, type Set, type SpatialUnit, type Style, type Tree, type WebBlock, type WebElement, type WebElementComponent, type WebImage, type Webpage, type WebpageProperties, type Website, type WebsiteProperties, fetchBibliography, fetchByUuid, fetchConcept, fetchGallery, fetchPeriod, fetchResource, fetchSet, fetchSpatialUnit, fetchTree, fetchWebsite, filterProperties, getAllPropertyLabels, getPropertyByLabel, getPropertyValueByLabel, getPropertyValuesByLabel, parseBibliographies, parseBibliography, parseConcept, parseConcepts, parseContext, parseCoordinates, parseDocument, parseEmail, parseEvents, parseFakeString, parseIdentification, parseImage, parseImageMap, parseInterpretations, parseLanguages, parseLicense, parseLink, parseLinks, parseMetadata, parseNotes, parseObservation, parseObservations, parsePeriod, parsePeriods, parsePerson, parsePersons, parseProperties, parseResource, parseResources, parseSet, parseSpatialUnit, parseSpatialUnits, parseStringContent, parseStringDocumentItem, parseStringItem, parseTree, parseWebsite };
package/dist/index.d.ts CHANGED
@@ -440,7 +440,7 @@ type Webpage = {
440
440
  title: string;
441
441
  slug: string;
442
442
  properties: WebpageProperties;
443
- blocks: Array<WebBlock>;
443
+ items: Array<WebElement | WebBlock>;
444
444
  webpages: Array<Webpage>;
445
445
  };
446
446
  /**
@@ -460,6 +460,7 @@ type WebpageProperties = {
460
460
  */
461
461
  type WebElement = {
462
462
  uuid: string;
463
+ type: "element";
463
464
  title: {
464
465
  label: string;
465
466
  variant: "default" | "simple";
@@ -588,9 +589,9 @@ type Style = {
588
589
  */
589
590
  type WebBlock = {
590
591
  uuid: string;
592
+ type: "block";
591
593
  layout: "vertical" | "horizontal" | "grid";
592
- blocks: Array<WebBlock>;
593
- elements: Array<WebElement>;
594
+ items: Array<WebElement | WebBlock>;
594
595
  properties: {
595
596
  /**
596
597
  * valid `gridTemplateColumns` or `gridTemplateRows` CSS property value
@@ -1796,19 +1797,18 @@ declare function parseConcepts(concepts: Array<OchreConcept> | Array<OchreNested
1796
1797
  declare function parseWebsite(websiteTree: OchreTree, projectName: FakeString, website: FakeString | null): Promise<Website>;
1797
1798
 
1798
1799
  /**
1799
- * Parses email addresses and URLs in a string into HTML links
1800
+ * Parses email addresses in a string into HTML links
1800
1801
  *
1801
1802
  * @param string - Input string to parse
1802
- * @returns String with emails and URLs converted to HTML links
1803
+ * @returns String with emails converted to HTML links
1803
1804
  *
1804
1805
  * @example
1805
1806
  * ```ts
1806
- * const parsed = parseEmailAndUrl("Contact us at info@example.com or visit www.example.com");
1807
- * // Returns: "Contact us at <ExternalLink href="mailto:info@example.com">info@example.com</ExternalLink>
1808
- * // or visit <ExternalLink href="www.example.com">www.example.com</ExternalLink>"
1807
+ * const parsed = parseEmail("Contact us at info@example.com");
1808
+ * // Returns: "Contact us at <ExternalLink href="mailto:info@example.com">info@example.com</ExternalLink>"
1809
1809
  * ```
1810
1810
  */
1811
- declare function parseEmailAndUrl(string: string): string;
1811
+ declare function parseEmail(string: string): string;
1812
1812
  /**
1813
1813
  * Converts a FakeString (string|number|boolean) to a proper string
1814
1814
  *
@@ -1847,4 +1847,4 @@ declare function parseStringDocumentItem(item: OchreStringRichTextItem, footnote
1847
1847
  */
1848
1848
  declare function parseStringContent(content: OchreStringContent, language?: string): string;
1849
1849
 
1850
- export { type Bibliography, type Concept, type Context, type ContextItem, type ContextNode, type Coordinates, type Data, type Document, type Event, type Footnote, type Gallery, type Identification, type Image, type ImageMap, type ImageMapArea, type Interpretation, type License, type Link, type Metadata, type NestedConcept, type NestedResource, type NestedSpatialUnit, type Note, type Observation, type Period, type Person, type Property, type PropertyValue, type PropertyValueType, type Resource, type Set, type SpatialUnit, type Style, type Tree, type WebBlock, type WebElement, type WebElementComponent, type WebImage, type Webpage, type WebpageProperties, type Website, type WebsiteProperties, fetchBibliography, fetchByUuid, fetchConcept, fetchGallery, fetchPeriod, fetchResource, fetchSet, fetchSpatialUnit, fetchTree, fetchWebsite, filterProperties, getAllPropertyLabels, getPropertyByLabel, getPropertyValueByLabel, getPropertyValuesByLabel, parseBibliographies, parseBibliography, parseConcept, parseConcepts, parseContext, parseCoordinates, parseDocument, parseEmailAndUrl, parseEvents, parseFakeString, parseIdentification, parseImage, parseImageMap, parseInterpretations, parseLanguages, parseLicense, parseLink, parseLinks, parseMetadata, parseNotes, parseObservation, parseObservations, parsePeriod, parsePeriods, parsePerson, parsePersons, parseProperties, parseResource, parseResources, parseSet, parseSpatialUnit, parseSpatialUnits, parseStringContent, parseStringDocumentItem, parseStringItem, parseTree, parseWebsite };
1850
+ export { type Bibliography, type Concept, type Context, type ContextItem, type ContextNode, type Coordinates, type Data, type Document, type Event, type Footnote, type Gallery, type Identification, type Image, type ImageMap, type ImageMapArea, type Interpretation, type License, type Link, type Metadata, type NestedConcept, type NestedResource, type NestedSpatialUnit, type Note, type Observation, type Period, type Person, type Property, type PropertyValue, type PropertyValueType, type Resource, type Set, type SpatialUnit, type Style, type Tree, type WebBlock, type WebElement, type WebElementComponent, type WebImage, type Webpage, type WebpageProperties, type Website, type WebsiteProperties, fetchBibliography, fetchByUuid, fetchConcept, fetchGallery, fetchPeriod, fetchResource, fetchSet, fetchSpatialUnit, fetchTree, fetchWebsite, filterProperties, getAllPropertyLabels, getPropertyByLabel, getPropertyValueByLabel, getPropertyValuesByLabel, parseBibliographies, parseBibliography, parseConcept, parseConcepts, parseContext, parseCoordinates, parseDocument, parseEmail, parseEvents, parseFakeString, parseIdentification, parseImage, parseImageMap, parseInterpretations, parseLanguages, parseLicense, parseLink, parseLinks, parseMetadata, parseNotes, parseObservation, parseObservations, parsePeriod, parsePeriods, parsePerson, parsePersons, parseProperties, parseResource, parseResources, parseSet, parseSpatialUnit, parseSpatialUnits, parseStringContent, parseStringDocumentItem, parseStringItem, parseTree, parseWebsite };
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  // src/utils/parse.ts
2
- import { v4 as uuidv4 } from "uuid";
3
2
  import { z as z3 } from "zod";
4
3
 
5
4
  // src/utils/fetchers/generic.ts
@@ -48,21 +47,11 @@ var whitespaceSchema = z2.string().transform((str) => str.split(" ")).pipe(
48
47
  )
49
48
  );
50
49
  var emailSchema = z2.string().email({ message: "Invalid email" });
51
- var urlSchema = z2.string().refine((v) => v ? isUrlValid(v) : false, {
52
- message: "Invalid URL"
53
- });
54
- function isUrlValid(url) {
55
- const pattern = (
56
- // eslint-disable-next-line regexp/no-useless-quantifier, regexp/no-unused-capturing-group
57
- /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\w$&+,:;=-]+@)?[\d.A-Za-z-]+(:\d+)?|(?:www.|[\w$&+,:;=-]+@)[\d.A-Za-z-]+)((?:\/[\w%+./~-]*)?\??[\w%&+.;=@-]*#?\w*)?)/
58
- );
59
- return !!pattern.test(url);
60
- }
61
50
  function getStringItemByLanguage(content, language) {
62
51
  const stringItemToFind = content.find((item) => item.lang === language);
63
52
  return stringItemToFind ?? null;
64
53
  }
65
- function parseEmailAndUrl(string) {
54
+ function parseEmail(string) {
66
55
  const splitString = string.split(" ");
67
56
  const returnSplitString = [];
68
57
  for (const string2 of splitString) {
@@ -78,13 +67,6 @@ function parseEmailAndUrl(string) {
78
67
  );
79
68
  continue;
80
69
  }
81
- const isUrl = urlSchema.safeParse(cleanString).success;
82
- if (isUrl) {
83
- returnSplitString.push(
84
- `${before}<ExternalLink href="${cleanString}">${cleanString}</ExternalLink>${after}`
85
- );
86
- continue;
87
- }
88
70
  returnSplitString.push(string2);
89
71
  }
90
72
  return returnSplitString.join(" ");
@@ -188,7 +170,7 @@ function parseStringItem(item) {
188
170
  }
189
171
  function parseStringDocumentItem(item, footnotes) {
190
172
  if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") {
191
- return parseEmailAndUrl(parseFakeString(item));
173
+ return parseEmail(parseFakeString(item));
192
174
  }
193
175
  if ("whitespace" in item && !("content" in item) && !("string" in item)) {
194
176
  if (item.whitespace === "newline") {
@@ -294,25 +276,16 @@ function parseStringDocumentItem(item, footnotes) {
294
276
  returnString += parseStringDocumentItem(stringItem, footnotes);
295
277
  }
296
278
  if ("whitespace" in item && item.whitespace != null) {
297
- returnString = parseWhitespace(
298
- parseEmailAndUrl(returnString),
299
- item.whitespace
300
- );
279
+ returnString = parseWhitespace(parseEmail(returnString), item.whitespace);
301
280
  }
302
281
  return returnString.replaceAll("&#39;", "'").replaceAll(/^(\d+)\./gm, String.raw`$1\.`);
303
282
  } else {
304
283
  returnString = parseFakeString(item.content);
305
284
  if (item.rend != null) {
306
- returnString = parseRenderOptions(
307
- parseEmailAndUrl(returnString),
308
- item.rend
309
- );
285
+ returnString = parseRenderOptions(parseEmail(returnString), item.rend);
310
286
  }
311
287
  if (item.whitespace != null) {
312
- returnString = parseWhitespace(
313
- parseEmailAndUrl(returnString),
314
- item.whitespace
315
- );
288
+ returnString = parseWhitespace(parseEmail(returnString), item.whitespace);
316
289
  }
317
290
  }
318
291
  return returnString.replaceAll(/^(\d+)\./gm, String.raw`$1\.`);
@@ -709,9 +682,7 @@ function parseDocument(document, language = "eng") {
709
682
  const footnotes = [];
710
683
  const documentWithLanguage = Array.isArray(document) ? document.find((doc) => doc.lang === language) : document;
711
684
  if (typeof documentWithLanguage.string === "string" || typeof documentWithLanguage.string === "number" || typeof documentWithLanguage.string === "boolean") {
712
- returnString += parseEmailAndUrl(
713
- parseFakeString(documentWithLanguage.string)
714
- );
685
+ returnString += parseEmail(parseFakeString(documentWithLanguage.string));
715
686
  } else {
716
687
  const documentItems = Array.isArray(documentWithLanguage.string) ? documentWithLanguage.string : [documentWithLanguage.string];
717
688
  for (const item of documentItems) {
@@ -763,9 +734,9 @@ function parseNotes(notes, language = "eng") {
763
734
  }
764
735
  }
765
736
  if (typeof noteWithLanguage.string === "string" || typeof noteWithLanguage.string === "number" || typeof noteWithLanguage.string === "boolean") {
766
- content = parseEmailAndUrl(parseFakeString(noteWithLanguage.string));
737
+ content = parseEmail(parseFakeString(noteWithLanguage.string));
767
738
  } else {
768
- content = parseEmailAndUrl(parseDocument(noteWithLanguage).content);
739
+ content = parseEmail(parseDocument(noteWithLanguage).content);
769
740
  }
770
741
  returnNotes.push({
771
742
  number: note.noteNo,
@@ -1258,10 +1229,7 @@ var parseWebpageResources = async (webpageResources, type) => {
1258
1229
  if (!resourceProperty) continue;
1259
1230
  switch (type) {
1260
1231
  case "element": {
1261
- const element = await parseWebElement(
1262
- resource,
1263
- resourceProperty.properties
1264
- );
1232
+ const element = await parseWebElement(resource);
1265
1233
  returnElements.push(
1266
1234
  element
1267
1235
  );
@@ -1788,9 +1756,20 @@ async function parseWebElementProperties(componentProperty, elementResource) {
1788
1756
  }
1789
1757
  return properties;
1790
1758
  }
1791
- async function parseWebElement(elementResource, elementProperties) {
1759
+ async function parseWebElement(elementResource) {
1792
1760
  const identification = parseIdentification(elementResource.identification);
1793
- const componentProperty = elementProperties.find(
1761
+ const elementProperties = elementResource.properties?.property ? parseProperties(
1762
+ Array.isArray(elementResource.properties.property) ? elementResource.properties.property : [elementResource.properties.property]
1763
+ ) : [];
1764
+ const presentationProperty = elementProperties.find(
1765
+ (property) => property.label === "presentation"
1766
+ );
1767
+ if (!presentationProperty) {
1768
+ throw new Error(
1769
+ `Presentation property not found for element \u201C${identification.label}\u201D`
1770
+ );
1771
+ }
1772
+ const componentProperty = presentationProperty.properties.find(
1794
1773
  (property) => property.label === "component"
1795
1774
  );
1796
1775
  if (!componentProperty) {
@@ -1854,6 +1833,7 @@ async function parseWebElement(elementResource, elementProperties) {
1854
1833
  }
1855
1834
  return {
1856
1835
  uuid: elementResource.uuid,
1836
+ type: "element",
1857
1837
  title: {
1858
1838
  label: identification.label,
1859
1839
  variant,
@@ -1888,8 +1868,7 @@ async function parseWebpage(webpageResource) {
1888
1868
  (link) => link.type === "image" || link.type === "IIIF"
1889
1869
  );
1890
1870
  const webpageResources = webpageResource.resource ? Array.isArray(webpageResource.resource) ? webpageResource.resource : [webpageResource.resource] : [];
1891
- const blocks = [];
1892
- let elementsToHandle = [];
1871
+ const items = [];
1893
1872
  for (const resource of webpageResources) {
1894
1873
  const resourceProperties = resource.properties ? parseProperties(
1895
1874
  Array.isArray(resource.properties.property) ? resource.properties.property : [resource.properties.property]
@@ -1901,55 +1880,21 @@ async function parseWebpage(webpageResource) {
1901
1880
  if (!resourceType) {
1902
1881
  continue;
1903
1882
  }
1904
- if (resourceType === "element") {
1905
- elementsToHandle.push(resource);
1906
- } else if (resourceType === "block") {
1907
- if (elementsToHandle.length > 0) {
1908
- const elements = await parseWebpageResources(
1909
- elementsToHandle,
1910
- "element"
1911
- );
1912
- const block = {
1913
- uuid: uuidv4(),
1914
- layout: "vertical",
1915
- blocks: [],
1916
- elements,
1917
- properties: {
1918
- spacing: void 0,
1919
- gap: void 0,
1920
- alignItems: "start",
1921
- justifyContent: "stretch"
1922
- },
1923
- propertiesMobile: null,
1924
- cssStyles: [],
1925
- cssStylesMobile: []
1926
- };
1927
- blocks.push(block);
1928
- elementsToHandle = [];
1883
+ switch (resourceType) {
1884
+ case "element": {
1885
+ const element = await parseWebElement(resource);
1886
+ items.push(element);
1887
+ break;
1888
+ }
1889
+ case "block": {
1890
+ const block = await parseBlock(resource);
1891
+ if (block) {
1892
+ items.push(block);
1893
+ }
1894
+ break;
1929
1895
  }
1930
- const parsedBlocks = await parseWebpageResources([resource], "block");
1931
- blocks.push(...parsedBlocks);
1932
1896
  }
1933
1897
  }
1934
- if (elementsToHandle.length > 0) {
1935
- const elements = await parseWebpageResources(elementsToHandle, "element");
1936
- const block = {
1937
- uuid: uuidv4(),
1938
- layout: "vertical",
1939
- blocks: [],
1940
- elements,
1941
- properties: {
1942
- spacing: void 0,
1943
- gap: void 0,
1944
- alignItems: "start",
1945
- justifyContent: "stretch"
1946
- },
1947
- propertiesMobile: null,
1948
- cssStyles: [],
1949
- cssStylesMobile: []
1950
- };
1951
- blocks.push(block);
1952
- }
1953
1898
  const webpages = webpageResource.resource ? await parseWebpageResources(
1954
1899
  Array.isArray(webpageResource.resource) ? webpageResource.resource : [webpageResource.resource],
1955
1900
  "page"
@@ -2014,7 +1959,7 @@ async function parseWebpage(webpageResource) {
2014
1959
  return {
2015
1960
  title: identification.label,
2016
1961
  slug,
2017
- blocks,
1962
+ items,
2018
1963
  properties: {
2019
1964
  displayedInHeader,
2020
1965
  width,
@@ -2041,9 +1986,9 @@ async function parseWebpages(webpageResources) {
2041
1986
  async function parseBlock(blockResource) {
2042
1987
  const returnBlock = {
2043
1988
  uuid: blockResource.uuid,
1989
+ type: "block",
2044
1990
  layout: "vertical",
2045
- blocks: [],
2046
- elements: [],
1991
+ items: [],
2047
1992
  properties: {
2048
1993
  spacing: void 0,
2049
1994
  gap: void 0,
@@ -2103,20 +2048,35 @@ async function parseBlock(blockResource) {
2103
2048
  returnBlock.propertiesMobile = propertiesMobile;
2104
2049
  }
2105
2050
  }
2106
- const blockBlocks = blockResource.resource ? await parseWebpageResources(
2107
- Array.isArray(blockResource.resource) ? blockResource.resource : [blockResource.resource],
2108
- "block"
2109
- ) : [];
2110
- for (const block of blockBlocks) {
2111
- returnBlock.blocks.push(block);
2112
- }
2113
- const blockElements = blockResource.resource ? await parseWebpageResources(
2114
- Array.isArray(blockResource.resource) ? blockResource.resource : [blockResource.resource],
2115
- "element"
2116
- ) : [];
2117
- for (const element of blockElements) {
2118
- returnBlock.elements.push(element);
2051
+ const blockResources = blockResource.resource ? Array.isArray(blockResource.resource) ? blockResource.resource : [blockResource.resource] : [];
2052
+ const blockItems = [];
2053
+ for (const resource of blockResources) {
2054
+ const resourceProperties = resource.properties ? parseProperties(
2055
+ Array.isArray(resource.properties.property) ? resource.properties.property : [resource.properties.property]
2056
+ ) : [];
2057
+ const resourceType = getPropertyValueByLabel(
2058
+ resourceProperties,
2059
+ "presentation"
2060
+ );
2061
+ if (!resourceType) {
2062
+ continue;
2063
+ }
2064
+ switch (resourceType) {
2065
+ case "element": {
2066
+ const element = await parseWebElement(resource);
2067
+ blockItems.push(element);
2068
+ break;
2069
+ }
2070
+ case "block": {
2071
+ const block = await parseBlock(resource);
2072
+ if (block) {
2073
+ blockItems.push(block);
2074
+ }
2075
+ break;
2076
+ }
2077
+ }
2119
2078
  }
2079
+ returnBlock.items = blockItems;
2120
2080
  const blockCssStyles = blockProperties.find(
2121
2081
  (property) => property.label === "presentation" && property.values[0]?.content === "css"
2122
2082
  )?.properties;
@@ -2350,15 +2310,7 @@ async function parseWebsite(websiteTree, projectName, website) {
2350
2310
  }
2351
2311
  const sidebarResources = sidebarResource.resource ? Array.isArray(sidebarResource.resource) ? sidebarResource.resource : [sidebarResource.resource] : [];
2352
2312
  for (const resource of sidebarResources) {
2353
- const sidebarResourceProperties = resource.properties ? parseProperties(
2354
- Array.isArray(resource.properties.property) ? resource.properties.property : [resource.properties.property]
2355
- ) : [];
2356
- const element = await parseWebElement(
2357
- resource,
2358
- sidebarResourceProperties.find(
2359
- (property) => property.label === "presentation" && property.values[0]?.content === "element"
2360
- )?.properties ?? []
2361
- );
2313
+ const element = await parseWebElement(resource);
2362
2314
  sidebarElements.push(element);
2363
2315
  }
2364
2316
  }
@@ -2665,7 +2617,7 @@ export {
2665
2617
  parseContext,
2666
2618
  parseCoordinates,
2667
2619
  parseDocument,
2668
- parseEmailAndUrl,
2620
+ parseEmail,
2669
2621
  parseEvents,
2670
2622
  parseFakeString,
2671
2623
  parseIdentification,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitalculture/ochre-sdk",
3
- "version": "0.4.14",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Node.js library for working with OCHRE (Online Cultural and Historical Research Environment) data",
@@ -45,17 +45,17 @@
45
45
  "zod": "^3.24.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@antfu/eslint-config": "^4.3.0",
48
+ "@antfu/eslint-config": "^4.10.1",
49
49
  "@arethetypeswrong/cli": "^0.17.4",
50
50
  "@changesets/cli": "^2.28.1",
51
51
  "@total-typescript/ts-reset": "^0.6.1",
52
- "@types/node": "^22.13.5",
53
- "eslint": "^9.21.0",
52
+ "@types/node": "^22.13.10",
53
+ "eslint": "^9.22.0",
54
54
  "eslint-plugin-unused-imports": "^4.1.4",
55
- "prettier": "^3.5.2",
55
+ "prettier": "^3.5.3",
56
56
  "tsup": "^8.4.0",
57
- "typescript": "^5.7.3",
58
- "vitest": "^3.0.7"
57
+ "typescript": "^5.8.2",
58
+ "vitest": "^3.0.9"
59
59
  },
60
60
  "scripts": {
61
61
  "dev": "tsup src/index.ts --watch",