ochre-sdk 1.0.65 → 1.0.67

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.
@@ -13,7 +13,7 @@ function getLabelContentLanguages(content) {
13
13
  return languages.length > 0 ? languages : [...DEFAULT_LANGUAGES];
14
14
  }
15
15
  function parsePropertyValueLabelText(text) {
16
- if (text == null || text === "") return null;
16
+ if (text === "" || text == null) return null;
17
17
  return text === "<unassigned>" ? null : text;
18
18
  }
19
19
  function parsePropertyValueLabel(content, text) {
@@ -23,7 +23,7 @@ function parsePropertyValueLabel(content, text) {
23
23
  return MultilingualString.fromObject({ [DEFAULT_LANGUAGES[0]]: parsedText });
24
24
  }
25
25
  function parsePropertyValueBooleanContent(rawValue) {
26
- if (rawValue == null || rawValue === "") return null;
26
+ if (rawValue === "" || rawValue == null) return null;
27
27
  return rawValue.toLocaleLowerCase("en-US") === "true";
28
28
  }
29
29
  function normalizePropertyValueDataType(dataType) {
@@ -242,7 +242,7 @@ function isResourceWrapper(value) {
242
242
  function sourceOrderSort(left, right) {
243
243
  const leftIndex = getXMLSourceIndex(left.item);
244
244
  const rightIndex = getXMLSourceIndex(right.item);
245
- if (leftIndex != null && rightIndex != null && leftIndex !== rightIndex) return leftIndex - rightIndex;
245
+ if (leftIndex !== rightIndex && leftIndex != null && rightIndex != null) return leftIndex - rightIndex;
246
246
  return left.fallbackIndex - right.fallbackIndex;
247
247
  }
248
248
  function collectHierarchyEntries(hierarchy, categories) {
@@ -297,7 +297,7 @@ function normalizeSetItemCategories(containedItemCategory) {
297
297
  return uniqueCategories;
298
298
  }
299
299
  function normalizeTreeItemCategory(containedItemCategory) {
300
- if (containedItemCategory != null && typeof containedItemCategory !== "string") throw new Error("Tree containedItemCategory must be a single category", { cause: containedItemCategory });
300
+ if (typeof containedItemCategory !== "string" && containedItemCategory != null) throw new Error("Tree containedItemCategory must be a single category", { cause: containedItemCategory });
301
301
  if (containedItemCategory === "tree") throw new Error("Tree containedItemCategory cannot be \"tree\"", { cause: containedItemCategory });
302
302
  return containedItemCategory;
303
303
  }
@@ -306,7 +306,7 @@ function resolveTreeItemCategory(rawTree, containedItemCategory) {
306
306
  if (inferredCategories.length > 1) throw new Error(`Expected Tree items to contain one category, received ${inferredCategories.join(", ")}`, { cause: inferredCategories });
307
307
  const inferredCategory = inferredCategories[0] ?? null;
308
308
  if (inferredCategory === "tree") throw new Error("Tree items cannot contain category \"tree\"", { cause: inferredCategory });
309
- if (containedItemCategory != null && inferredCategory != null && containedItemCategory !== inferredCategory) throw new Error(`Tree containedItemCategory "${containedItemCategory}" does not match XML items category "${inferredCategory}"`, { cause: {
309
+ if (containedItemCategory !== inferredCategory && containedItemCategory != null && inferredCategory != null) throw new Error(`Tree containedItemCategory "${containedItemCategory}" does not match XML items category "${inferredCategory}"`, { cause: {
310
310
  containedItemCategory,
311
311
  inferredCategory
312
312
  } });
@@ -456,7 +456,7 @@ function parseNotes(rawNotes, options) {
456
456
  return Array.from(rawNotes?.note ?? [], (note) => parseNote(note, options));
457
457
  }
458
458
  function parsePropertyDataType(dataType) {
459
- if (dataType == null || dataType === "") return "string";
459
+ if (dataType === "" || dataType == null) return "string";
460
460
  const normalizedDataType = dataType.startsWith("xs:") ? dataType.slice(3) : dataType;
461
461
  for (const propertyDataType of PROPERTY_DATA_TYPES) if (normalizedDataType === propertyDataType) return propertyDataType;
462
462
  throw new Error(`Invalid property value data type: ${dataType}`, { cause: dataType });
@@ -645,7 +645,7 @@ function parseSetItemHierarchy(hierarchy, options, categories) {
645
645
  }
646
646
  function normalizeTreeLinkItemsCategory(type) {
647
647
  const category = normalizeCategory(type);
648
- if (category == null || category === "tree") return null;
648
+ if (category === "tree" || category == null) return null;
649
649
  return category;
650
650
  }
651
651
  function normalizeSetLinkItemsCategory(type) {
@@ -139,7 +139,7 @@ function getDistinctTooltipContent(content, textContent) {
139
139
  return content === textContent ? void 0 : content;
140
140
  }
141
141
  function createMDXStringAttribute(name, value) {
142
- if (value == null || value === "") return "";
142
+ if (value === "" || value == null) return "";
143
143
  return ` ${name}=${MDX_QUOTED_ATTRIBUTE_ESCAPE_REGEX.test(value) ? `{${JSON.stringify(value)}}` : `"${value}"`}`;
144
144
  }
145
145
  function getPropertyValueUuid(property) {
@@ -324,7 +324,7 @@ function getXMLRichTextLinks(item) {
324
324
  for (const rawLinks of linkGroups) {
325
325
  if (!Array.isArray(rawLinks)) continue;
326
326
  for (const rawLink of rawLinks) {
327
- if (!(isXMLRichTextLink(rawLink) && !isTextAnnotationMarkerLink(rawLink))) continue;
327
+ if (!isXMLRichTextLink(rawLink) || isTextAnnotationMarkerLink(rawLink)) continue;
328
328
  links.push({
329
329
  link: rawLink,
330
330
  fallbackIndex
@@ -335,7 +335,7 @@ function getXMLRichTextLinks(item) {
335
335
  links.sort((left, right) => {
336
336
  const leftIndex = getXMLSourceIndex(left.link);
337
337
  const rightIndex = getXMLSourceIndex(right.link);
338
- if (leftIndex != null && rightIndex != null && leftIndex !== rightIndex) return leftIndex - rightIndex;
338
+ if (leftIndex !== rightIndex && leftIndex != null && rightIndex != null) return leftIndex - rightIndex;
339
339
  return left.fallbackIndex - right.fallbackIndex;
340
340
  });
341
341
  const sortedLinks = [];
@@ -41,7 +41,7 @@ function cleanWebsitePageSlug(slug) {
41
41
  return slug?.replace(SEGMENT_UNIQUE_SLUG_PREFIX_REGEX, "") ?? null;
42
42
  }
43
43
  function prefixSlug(slug, slugPrefix) {
44
- if (slugPrefix == null || slugPrefix === "") return slug;
44
+ if (slugPrefix === "" || slugPrefix == null) return slug;
45
45
  if (slug === "") return slugPrefix;
46
46
  return `${slugPrefix}/${slug}`;
47
47
  }
@@ -126,7 +126,7 @@ function parseResponsiveCssStyles(properties) {
126
126
  * @returns Parsed bounds object
127
127
  */
128
128
  function parseBounds(bounds) {
129
- const [southWest, northEast] = bounds.trim().startsWith("[") ? parseJsonBounds(bounds) : bounds.split(";").map((pair) => pair.split(",").map((coordinate) => Number(coordinate.trim())));
129
+ const [southWest, northEast] = bounds.trimStart().startsWith("[") ? parseJsonBounds(bounds) : bounds.split(";").map((pair) => pair.split(",").map((coordinate) => Number(coordinate.trim())));
130
130
  if (southWest?.length !== 2 || northEast?.length !== 2 || southWest.some((coordinate) => Number.isNaN(coordinate)) || northEast.some((coordinate) => Number.isNaN(coordinate))) throw new Error(`Invalid bounds: ${bounds}`, { cause: bounds });
131
131
  return [[southWest[0], southWest[1]], [northEast[0], northEast[1]]];
132
132
  }
@@ -248,8 +248,6 @@ const COLLECTION_PROPERTY_DEFAULTS = {
248
248
  variant: "slide",
249
249
  paginationVariant: "default",
250
250
  loadingVariant: "skeleton",
251
- imageLayout: "start",
252
- isImagePlaceholderDisplayed: true,
253
251
  minimumColumnCount: null,
254
252
  maximumColumnCount: null,
255
253
  expectedItemCount: null,
@@ -258,29 +256,51 @@ const COLLECTION_PROPERTY_DEFAULTS = {
258
256
  isInteractive: true
259
257
  };
260
258
  /**
259
+ * Default values for a collection's image display properties, merged separately
260
+ * from {@link COLLECTION_PROPERTY_DEFAULTS} because overrides of the nested
261
+ * "image" object are themselves partial.
262
+ */
263
+ const COLLECTION_IMAGE_DEFAULTS = {
264
+ layout: "start",
265
+ fit: "fit",
266
+ alignment: null,
267
+ isPlaceholderDisplayed: true
268
+ };
269
+ /**
261
270
  * Reads the collection display properties explicitly set on a reader, omitting
262
271
  * any that are unset. The "collection" component merges these over
263
- * {@link COLLECTION_PROPERTY_DEFAULTS}, while the "query" component uses them as
264
- * partial overrides for its embedded collection.
272
+ * {@link COLLECTION_PROPERTY_DEFAULTS} and {@link COLLECTION_IMAGE_DEFAULTS},
273
+ * while the "query" component uses them as partial overrides for its embedded
274
+ * collection.
265
275
  */
266
276
  function parseCollectionPropertyOverrides(reader) {
267
277
  const overrides = {};
278
+ const imageOverrides = {};
268
279
  function read(key, label) {
269
280
  const value = reader.value(label);
270
281
  if (value != null) overrides[key] = value;
271
282
  }
283
+ function readImage(key, label) {
284
+ const value = reader.value(label);
285
+ if (value != null) imageOverrides[key] = value;
286
+ }
272
287
  read("variant", "variant");
273
288
  read("paginationVariant", "pagination-variant");
274
289
  read("loadingVariant", "loading-variant");
275
- read("imageLayout", "image-layout");
276
- read("isImagePlaceholderDisplayed", "image-placeholder-displayed");
277
290
  read("minimumColumnCount", "minimum-column-count");
278
291
  read("maximumColumnCount", "maximum-column-count");
279
292
  read("expectedItemCount", "item-count");
280
293
  read("isSortDisplayed", "sort-displayed");
281
294
  read("isUsingQueryParams", "is-using-query-params");
282
295
  read("isInteractive", "is-interactive");
283
- return overrides;
296
+ readImage("layout", "image-layout");
297
+ readImage("fit", "image-fit");
298
+ readImage("alignment", "image-alignment");
299
+ readImage("isPlaceholderDisplayed", "image-placeholder-displayed");
300
+ return Object.keys(imageOverrides).length > 0 ? {
301
+ ...overrides,
302
+ image: imageOverrides
303
+ } : overrides;
284
304
  }
285
305
  /**
286
306
  * Parses the "use-property" values defining which item properties a collection
@@ -444,12 +464,17 @@ function parseWebElementProperties(componentProperty, elementResource, options,
444
464
  const isFilterSidebarDisplayed = componentReader.valueOr("filter-sidebar-displayed", false);
445
465
  const filterSidebarSort = componentReader.valueOr("filter-sidebar-sort", "default");
446
466
  const componentOptions = parseWebsiteOptions(elementResource.options, options);
467
+ const propertyOverrides = parseCollectionPropertyOverrides(componentReader);
447
468
  properties = {
448
469
  component: "collection",
449
470
  linkUuids: setLinks.map((link) => link.uuid),
450
471
  displayedProperties: parseCollectionDisplayedProperties(componentReader),
451
472
  ...COLLECTION_PROPERTY_DEFAULTS,
452
- ...parseCollectionPropertyOverrides(componentReader),
473
+ ...propertyOverrides,
474
+ image: {
475
+ ...COLLECTION_IMAGE_DEFAULTS,
476
+ ...propertyOverrides.image
477
+ },
453
478
  filter: {
454
479
  isSidebarDisplayed: isFilterSidebarDisplayed,
455
480
  isResultsBarDisplayed: isFilterResultsBarDisplayed,
@@ -1254,7 +1279,7 @@ function parseContextItem(contextItemToParse, options) {
1254
1279
  const levels = [];
1255
1280
  const levelsToParse = contextItemToParse.levels?.level ?? [];
1256
1281
  for (const level of levelsToParse) {
1257
- const [rawVariableUuid = "", rawValueUuid] = level.payload.split(",");
1282
+ const [rawVariableUuid = "", rawValueUuid] = level.payload.split(",", 2);
1258
1283
  const valueUuid = rawValueUuid == null || rawValueUuid.trim() === "null" ? null : rawValueUuid.trim();
1259
1284
  type = level.dataType ?? type;
1260
1285
  levels.push({
package/dist/query.mjs CHANGED
@@ -99,7 +99,7 @@ function buildWordQueryOptionsExpression(parameters) {
99
99
  if (matchMode === "exact") options.push("unstemmed", "unwildcarded");
100
100
  else if (queryFamily === "text") {
101
101
  options.push(isStemmed ? "stemmed" : "unstemmed", isWildcarded ? "wildcarded" : "unwildcarded");
102
- if (isStemmed && language != null && language !== "") options.push(`lang=${language}`);
102
+ if (isStemmed && language !== "" && language != null) options.push(`lang=${language}`);
103
103
  }
104
104
  return `(${options.map((option) => stringLiteral(option)).join(", ")})`;
105
105
  }
@@ -319,8 +319,12 @@ type WebElementComponent<T extends LanguageCodes = LanguageCodes> = {
319
319
  variant: "slide" | "table" | "card" | "tile" | "showcase";
320
320
  paginationVariant: "default" | "numeric";
321
321
  loadingVariant: "spinner" | "skeleton" | "animation" | "none";
322
- imageLayout: "top" | "bottom" | "start" | "end" | null;
323
- isImagePlaceholderDisplayed: boolean;
322
+ image: {
323
+ layout: "top" | "bottom" | "start" | "end" | null;
324
+ fit: "fill" | "fit";
325
+ alignment: "top" | "center" | "bottom" | null;
326
+ isPlaceholderDisplayed: boolean;
327
+ };
324
328
  minimumColumnCount: number | null;
325
329
  maximumColumnCount: number | null;
326
330
  expectedItemCount: number | null;
@@ -409,7 +413,11 @@ type WebElementComponent<T extends LanguageCodes = LanguageCodes> = {
409
413
  };
410
414
  collectionProperties: Prettify<Partial<Omit<Extract<WebElementComponent<T>, {
411
415
  component: "collection";
412
- }>, "component" | "linkUuids" | "options">>>;
416
+ }>, "component" | "linkUuids" | "options" | "image"> & {
417
+ image: Partial<Extract<WebElementComponent<T>, {
418
+ component: "collection";
419
+ }>["image"]>;
420
+ }>>;
413
421
  } | {
414
422
  component: "search-bar";
415
423
  queryVariant: "submit" | "change";
@@ -24,7 +24,7 @@ function parseXMLNumber(value) {
24
24
  }
25
25
  function parseOptionalXMLNumber(value) {
26
26
  const payload = getXMLStringPayload(value);
27
- return payload == null || payload === "" ? void 0 : Number(payload);
27
+ return payload === "" || payload == null ? void 0 : Number(payload);
28
28
  }
29
29
  const ITEM_CATEGORIES = [
30
30
  "tree",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ochre-sdk",
3
- "version": "1.0.65",
3
+ "version": "1.0.67",
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",
@@ -51,13 +51,13 @@
51
51
  "valibot": "^1.4.2"
52
52
  },
53
53
  "devDependencies": {
54
- "@antfu/eslint-config": "^9.1.0",
54
+ "@antfu/eslint-config": "^9.2.0",
55
55
  "@types/node": "^24.13.3",
56
56
  "bumpp": "^12.0.0",
57
- "eslint": "^10.7.0",
58
- "knip": "^6.27.0",
59
- "oxfmt": "^0.59.0",
60
- "tsdown": "^0.22.12",
57
+ "eslint": "^10.8.0",
58
+ "knip": "^6.29.0",
59
+ "oxfmt": "^0.60.0",
60
+ "tsdown": "^0.22.14",
61
61
  "typescript": "^6.0.3",
62
62
  "vitest": "^4.1.10"
63
63
  },