ochre-sdk 1.0.72 → 1.0.73

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.
@@ -38,7 +38,7 @@ declare const renderOptionsSchema: v.SchemaWithPipe<readonly [v.StringSchema<und
38
38
  declare const setPropertyValuesParametersSchema: v.ObjectSchema<{
39
39
  readonly setScopeUuids: v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>, undefined>, v.MinLengthAction<string[], 1, "At least one set scope UUID is required">]>;
40
40
  readonly belongsToCollectionScopeUuids: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>, undefined>, readonly []>;
41
- readonly queries: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.GenericSchema<unknown, Query>, v.CheckAction<Query, "OCR queries cannot be nested inside an OR group because they are resolved by a document join instead of a CTS query">]>, undefined>, null>;
41
+ readonly queries: v.OptionalSchema<v.NullableSchema<v.GenericSchema<unknown, Query>, undefined>, null>;
42
42
  readonly attributes: v.OptionalSchema<v.ObjectSchema<{
43
43
  readonly bibliographies: v.GenericSchema<unknown, boolean>;
44
44
  readonly periods: v.GenericSchema<unknown, boolean>;
@@ -49,15 +49,14 @@ declare const setPropertyValuesParametersSchema: v.ObjectSchema<{
49
49
  readonly isLimitedToLeafPropertyValues: v.GenericSchema<unknown, boolean>;
50
50
  }, undefined>;
51
51
  /**
52
- * Schema for validating OCR matches parameters
52
+ * Schema for validating the parameters for the item OCR data fetching function
53
53
  * @internal
54
54
  */
55
- declare const ocrMatchesParametersSchema: v.ObjectSchema<{
56
- readonly uuids: v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>, undefined>, v.MinLengthAction<string[], 1, "At least one UUID is required">]>;
57
- readonly value: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, "A search value is required">]>;
55
+ declare const itemOcrDataParametersSchema: v.ObjectSchema<{
56
+ readonly uuid: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>;
57
+ readonly value: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "A search value is required">]>;
58
58
  readonly matchMode: v.OptionalSchema<v.PicklistSchema<["includes", "exact"], undefined>, "includes">;
59
59
  readonly isCaseSensitive: v.GenericSchema<unknown, boolean>;
60
- readonly maxMatchesPerItem: v.OptionalSchema<v.GenericSchema<unknown, number>, 50>;
61
60
  }, undefined>;
62
61
  /**
63
62
  * Schema for validating Set items parameters
@@ -66,7 +65,7 @@ declare const ocrMatchesParametersSchema: v.ObjectSchema<{
66
65
  declare const setItemsParametersSchema: v.ObjectSchema<{
67
66
  readonly setScopeUuids: v.SchemaWithPipe<readonly [v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>, undefined>, v.MinLengthAction<string[], 1, "At least one set scope UUID is required">]>;
68
67
  readonly belongsToCollectionScopeUuids: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>, undefined>, readonly []>;
69
- readonly queries: v.OptionalSchema<v.NullableSchema<v.SchemaWithPipe<readonly [v.GenericSchema<unknown, Query>, v.CheckAction<Query, "OCR queries cannot be nested inside an OR group because they are resolved by a document join instead of a CTS query">]>, undefined>, null>;
68
+ readonly queries: v.OptionalSchema<v.NullableSchema<v.GenericSchema<unknown, Query>, undefined>, null>;
70
69
  readonly sort: v.OptionalSchema<v.VariantSchema<"target", [v.StrictObjectSchema<{
71
70
  readonly target: v.LiteralSchema<"none", undefined>;
72
71
  }, undefined>, v.StrictObjectSchema<{
@@ -86,4 +85,4 @@ declare const setItemsParametersSchema: v.ObjectSchema<{
86
85
  readonly pageSize: v.OptionalSchema<v.GenericSchema<unknown, number>, 48>;
87
86
  }, undefined>;
88
87
  //#endregion
89
- export { componentSchema, gallerySchema, iso639_3Schema, ocrMatchesParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
88
+ export { componentSchema, gallerySchema, iso639_3Schema, itemOcrDataParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
package/dist/schemas.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { isPseudoUuid } from "./utilities.mjs";
2
2
  import "./helpers.mjs";
3
- import { OCR_DISJUNCTION_ERROR_MESSAGE, hasOcrQueryInDisjunction } from "./query.mjs";
4
3
  import * as v from "valibot";
5
4
  //#region src/schemas.ts
6
5
  const positiveNumber = (message) => v.pipe(v.number(), v.minValue(1, message));
@@ -143,7 +142,7 @@ const setQueryLeafSchema = v.union([
143
142
  ...standardQueryFields
144
143
  }),
145
144
  v.strictObject({
146
- target: v.literal("ocr"),
145
+ target: v.literal("ocrText"),
147
146
  value: v.string(),
148
147
  matchMode: standardQueryFields.matchMode,
149
148
  isCaseSensitive: standardQueryFields.isCaseSensitive,
@@ -175,7 +174,7 @@ const setQuerySchema = v.lazy(() => v.union([
175
174
  * Schema for validating Set queries
176
175
  * @internal
177
176
  */
178
- const setQueriesSchema = v.optional(v.nullable(v.pipe(setQuerySchema, v.check((query) => !hasOcrQueryInDisjunction(query), OCR_DISJUNCTION_ERROR_MESSAGE))), null);
177
+ const setQueriesSchema = v.optional(v.nullable(setQuerySchema), null);
179
178
  /**
180
179
  * Schema for validating Set items sort
181
180
  * @internal
@@ -222,15 +221,14 @@ const setPropertyValuesParametersSchema = v.object({
222
221
  isLimitedToLeafPropertyValues: defaultBoolean(false)
223
222
  });
224
223
  /**
225
- * Schema for validating OCR matches parameters
224
+ * Schema for validating the parameters for the item OCR data fetching function
226
225
  * @internal
227
226
  */
228
- const ocrMatchesParametersSchema = v.object({
229
- uuids: v.pipe(v.array(uuidSchema), v.minLength(1, "At least one UUID is required")),
230
- value: v.pipe(v.string(), v.minLength(1, "A search value is required")),
227
+ const itemOcrDataParametersSchema = v.object({
228
+ uuid: uuidSchema,
229
+ value: v.pipe(v.string(), v.check((value) => value.trim() !== "", "A search value is required")),
231
230
  matchMode: v.optional(v.picklist(["includes", "exact"]), "includes"),
232
- isCaseSensitive: defaultBoolean(false),
233
- maxMatchesPerItem: v.optional(positiveNumber("Max matches per item must be positive"), 50)
231
+ isCaseSensitive: defaultBoolean(false)
234
232
  });
235
233
  /**
236
234
  * Schema for validating Set items parameters
@@ -245,4 +243,4 @@ const setItemsParametersSchema = v.object({
245
243
  pageSize: v.optional(positiveNumber("Page size must be positive"), 48)
246
244
  });
247
245
  //#endregion
248
- export { componentSchema, gallerySchema, iso639_3Schema, ocrMatchesParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
246
+ export { componentSchema, gallerySchema, iso639_3Schema, itemOcrDataParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
@@ -263,58 +263,29 @@ type ImageMap = {
263
263
  height: number;
264
264
  };
265
265
  /**
266
- * Vertex of an OCR word's bounding polygon in OCHRE
267
- */
268
- type OcrPoint = {
269
- x: number;
270
- y: number;
271
- };
272
- /**
273
- * Word recognized within an OCR text line in OCHRE
274
- */
275
- type OcrWord = {
276
- content: string;
277
- x: number;
278
- y: number;
279
- width: number;
280
- height: number;
281
- vertices: Array<OcrPoint>;
282
- };
283
- /**
284
- * Text line of an OCR text block in OCHRE
285
- */
286
- type OcrTextLine = {
287
- content: string;
288
- words: Array<OcrWord>;
289
- };
290
- /**
291
- * Text block of an OCR page in OCHRE
292
- */
293
- type OcrTextBlock = {
294
- lines: Array<OcrTextLine>;
295
- };
296
- /**
297
- * OCR page of a resource in OCHRE
298
- */
299
- type OcrPage = {
300
- number: number | null;
301
- fileName: string | null;
302
- width: number | null;
303
- height: number | null;
304
- blocks: Array<OcrTextBlock>;
305
- };
306
- /**
307
- * A run of adjacent OCR words matching a search value in OCHRE
266
+ * Positioned OCR string in OCHRE
267
+ *
268
+ * OCHRE gives no guarantee about the node hierarchy inside a Resource's
269
+ * `<ocr>` layer, so only `<string>` nodes are parsed, at whatever depth they
270
+ * occur. `x` and `y` come from `HPOS` and `VPOS` and locate the top-left
271
+ * corner of the string's box, while `vertices` is its full bounding polygon,
272
+ * which is not necessarily rectangular. Every geometry attribute is optional
273
+ * in the source, so each one is null when absent or unparseable.
308
274
  *
309
- * `uuid` is the requested resource, while `resourceUuid` is the resource that
310
- * owns the OCR page — they differ when the OCR lives on a child page resource.
275
+ * `resourceUuid` is the Resource that owns the OCR layer, which differs from
276
+ * the requested item when the OCR lives on a child Resource.
311
277
  */
312
- type OcrMatch = {
313
- uuid: string;
278
+ type OcrString = {
314
279
  resourceUuid: string | null;
315
- page: Omit<OcrPage, "blocks">;
316
280
  content: string;
317
- words: Array<OcrWord>;
281
+ x: number | null;
282
+ y: number | null;
283
+ width: number | null;
284
+ height: number | null;
285
+ vertices: Array<{
286
+ x: number;
287
+ y: number;
288
+ }>;
318
289
  };
319
290
  /**
320
291
  * Note in OCHRE
@@ -734,7 +705,6 @@ type Resource<T extends LanguageCodes = LanguageCodes, U extends ItemPayloadKind
734
705
  image: Image<T> | null;
735
706
  document: MultilingualString<T> | null;
736
707
  imageMap: ImageMap | null;
737
- ocr: Array<OcrPage>;
738
708
  coordinates: Array<Coordinates<T>>;
739
709
  periods: Array<Period<T, "embedded">>;
740
710
  links: ItemLinks<T>;
@@ -845,12 +815,12 @@ type SetItemsSort = {
845
815
  /**
846
816
  * Represents a leaf query for Set items
847
817
  *
848
- * The `ocr` target matches the OCR text layer of resources. Because OCR is not
849
- * carried by Set item projections, it is resolved by a document join rather
850
- * than a CTS term, which means `ocr` leaves compose with `and` and `isNegated`
851
- * but cannot be nested inside an `or` group. Both match modes are adjacency
852
- * based: `includes` allows stemming and wildcards, `exact` requires whole OCR
853
- * words. OCR carries no language, so `ocr` leaves take no `language`.
818
+ * The `ocrText` target matches the OCR text layer of Resource items. Because
819
+ * Set item projections do not carry `<ocrText>`, it is resolved by a document
820
+ * join rather than a CTS term, so it composes with `and`, `or`, and `isNegated`
821
+ * at the cost of one extra search branch per distinct OCR text value in a
822
+ * disjunction. OCR text carries no language, so `ocrText` leaves take no
823
+ * `language`.
854
824
  */
855
825
  type QueryLeaf = {
856
826
  target: "property";
@@ -918,7 +888,7 @@ type QueryLeaf = {
918
888
  language: string;
919
889
  isNegated?: boolean;
920
890
  } | {
921
- target: "ocr";
891
+ target: "ocrText";
922
892
  value: string;
923
893
  matchMode: "includes" | "exact";
924
894
  isCaseSensitive: boolean;
@@ -944,4 +914,4 @@ type QueryGroup = {
944
914
  */
945
915
  type Query = QueryLeaf | QueryGroup;
946
916
  //#endregion
947
- export { AnyBibliography, AnyConcept, AnyItem, AnyPeriod, AnyPerson, AnyPropertyValue, AnyPropertyVariable, AnyResource, AnySet, AnySpatialUnit, AnyText, AnyTree, BaseItem, BaseItemLink, BelongsTo, Bibliography, BibliographyEntryInfo, BibliographyItemLink, BibliographySourceDocument, Concept, ConceptItemLink, ContainedItemCategory, ContainedItemCategoryFromOption, ContainedItemCategoryOption, Context, ContextItem, ContextItemCategory, ContextNode, Coordinates, CoordinatesSource, DictionaryUnitItemLink, EmbeddedBibliography, EmbeddedConcept, EmbeddedItem, EmbeddedPeriod, EmbeddedPerson, EmbeddedPropertyValue, EmbeddedPropertyVariable, EmbeddedResource, EmbeddedSet, EmbeddedSpatialUnit, EmbeddedText, EmbeddedTree, Event, Gallery, Heading, HeadingItemCategory, Identification, Image, ImageMap, ImageMapArea, Interpretation, Item, ItemCategory, ItemCategoryFromOption, ItemCategoryOption, ItemCategoryWithEmbeddedItems, ItemContainerCategory, ItemLink, ItemLinkCategory, ItemLinks, ItemPayloadKind, ItemProperty, ItemWithoutEmbeddedItems, LanguageCodes, License, Metadata, Note, Observation, OcrMatch, OcrPage, OcrPoint, OcrTextBlock, OcrTextLine, OcrWord, Period, PeriodItemLink, Person, PersonItemLink, Prettify, Property, PropertyLike, PropertyRelation, PropertyValue, PropertyValueContent, PropertyValueDataType, PropertyValueItemLink, PropertyValueQueryItem, PropertyVariable, PropertyVariableItemLink, Query, QueryGroup, QueryLeaf, QueryablePropertyValueDataType, RecursiveItemCategory, Resource, ResourceItemLink, Section, Set, SetAttributeValueQueryItem, SetBibliography, SetConcept, SetItem, SetItemCategory, SetItemLink, SetItemProperty, SetItemSimplifiedProperty, SetItemsSort, SetItemsSortDirection, SetPeriod, SetResource, SetSpatialUnit, SetTree, SimplifiedProperty, SpatialUnit, SpatialUnitItemLink, Text, TextItemLink, TopLevelItem, Tree, TreeItemCategory, TreeItemLink };
917
+ export { AnyBibliography, AnyConcept, AnyItem, AnyPeriod, AnyPerson, AnyPropertyValue, AnyPropertyVariable, AnyResource, AnySet, AnySpatialUnit, AnyText, AnyTree, BaseItem, BaseItemLink, BelongsTo, Bibliography, BibliographyEntryInfo, BibliographyItemLink, BibliographySourceDocument, Concept, ConceptItemLink, ContainedItemCategory, ContainedItemCategoryFromOption, ContainedItemCategoryOption, Context, ContextItem, ContextItemCategory, ContextNode, Coordinates, CoordinatesSource, DictionaryUnitItemLink, EmbeddedBibliography, EmbeddedConcept, EmbeddedItem, EmbeddedPeriod, EmbeddedPerson, EmbeddedPropertyValue, EmbeddedPropertyVariable, EmbeddedResource, EmbeddedSet, EmbeddedSpatialUnit, EmbeddedText, EmbeddedTree, Event, Gallery, Heading, HeadingItemCategory, Identification, Image, ImageMap, ImageMapArea, Interpretation, Item, ItemCategory, ItemCategoryFromOption, ItemCategoryOption, ItemCategoryWithEmbeddedItems, ItemContainerCategory, ItemLink, ItemLinkCategory, ItemLinks, ItemPayloadKind, ItemProperty, ItemWithoutEmbeddedItems, LanguageCodes, License, Metadata, Note, Observation, OcrString, Period, PeriodItemLink, Person, PersonItemLink, Prettify, Property, PropertyLike, PropertyRelation, PropertyValue, PropertyValueContent, PropertyValueDataType, PropertyValueItemLink, PropertyValueQueryItem, PropertyVariable, PropertyVariableItemLink, Query, QueryGroup, QueryLeaf, QueryablePropertyValueDataType, RecursiveItemCategory, Resource, ResourceItemLink, Section, Set, SetAttributeValueQueryItem, SetBibliography, SetConcept, SetItem, SetItemCategory, SetItemLink, SetItemProperty, SetItemSimplifiedProperty, SetItemsSort, SetItemsSortDirection, SetPeriod, SetResource, SetSpatialUnit, SetTree, SimplifiedProperty, SpatialUnit, SpatialUnitItemLink, Text, TextItemLink, TopLevelItem, Tree, TreeItemCategory, TreeItemLink };
@@ -20,6 +20,30 @@ declare function isPseudoUuid(value: string): boolean;
20
20
  * @returns The escaped string literal
21
21
  */
22
22
  declare function stringLiteral(value: string): string;
23
+ /**
24
+ * XQuery prolog declaring `local:omit-supplemental`, which drops every element
25
+ * carrying `supplemental="true"` from a node sequence, at any depth.
26
+ *
27
+ * Subtrees without a supplemental descendant are returned by reference, so
28
+ * nodes are only copied along the path leading to an omitted element. The
29
+ * lookahead walks the attribute axis (`//@supplemental`) rather than testing
30
+ * every element, which measures around three times faster on large documents.
31
+ *
32
+ * Must be declared before any query body that calls {@link omitSupplemental}.
33
+ */
34
+ declare const SUPPLEMENTAL_XQUERY_PROLOG = "declare function local:omit-supplemental($nodes as node()*) as node()* {\n for $node in $nodes\n return\n if ($node instance of element())\n then\n if ($node/@supplemental = \"true\")\n then ()\n else if (empty($node//@supplemental[. = \"true\"]))\n then $node\n else element { node-name($node) } {\n $node/@*,\n local:omit-supplemental($node/node())\n }\n else $node\n};";
35
+ /**
36
+ * Wrap an XQuery node expression so supplemental nodes are omitted from it
37
+ * @param expression - The XQuery expression returning the nodes to filter
38
+ * @returns The wrapped XQuery expression
39
+ */
40
+ declare function omitSupplemental(expression: string): string;
41
+ /**
42
+ * XQuery predicate keeping only nodes that are neither supplemental themselves
43
+ * nor nested inside a supplemental node. Use it when aggregating over nodes
44
+ * instead of returning them.
45
+ */
46
+ declare const NOT_SUPPLEMENTAL_PREDICATE = "[not(ancestor-or-self::*[@supplemental = \"true\"])]";
23
47
  /**
24
48
  * Flatten a properties array
25
49
  * @param properties - The properties to flatten
@@ -28,4 +52,4 @@ declare function stringLiteral(value: string): string;
28
52
  */
29
53
  declare function flattenProperties<T extends LanguageCodes = LanguageCodes>(properties: ReadonlyArray<Property<T> | SetItemProperty<T>>): Array<SetItemProperty<T>>;
30
54
  //#endregion
31
- export { createSchemaValidationError, flattenProperties, getErrorOutput, isPseudoUuid, stringLiteral };
55
+ export { NOT_SUPPLEMENTAL_PREDICATE, SUPPLEMENTAL_XQUERY_PROLOG, createSchemaValidationError, flattenProperties, getErrorOutput, isPseudoUuid, omitSupplemental, stringLiteral };
@@ -151,6 +151,46 @@ function stringLiteral(value) {
151
151
  return `"${value.replaceAll("\"", "\"\"")}"`;
152
152
  }
153
153
  /**
154
+ * XQuery prolog declaring `local:omit-supplemental`, which drops every element
155
+ * carrying `supplemental="true"` from a node sequence, at any depth.
156
+ *
157
+ * Subtrees without a supplemental descendant are returned by reference, so
158
+ * nodes are only copied along the path leading to an omitted element. The
159
+ * lookahead walks the attribute axis (`//@supplemental`) rather than testing
160
+ * every element, which measures around three times faster on large documents.
161
+ *
162
+ * Must be declared before any query body that calls {@link omitSupplemental}.
163
+ */
164
+ const SUPPLEMENTAL_XQUERY_PROLOG = `declare function local:omit-supplemental($nodes as node()*) as node()* {
165
+ for $node in $nodes
166
+ return
167
+ if ($node instance of element())
168
+ then
169
+ if ($node/@supplemental = "true")
170
+ then ()
171
+ else if (empty($node//@supplemental[. = "true"]))
172
+ then $node
173
+ else element { node-name($node) } {
174
+ $node/@*,
175
+ local:omit-supplemental($node/node())
176
+ }
177
+ else $node
178
+ };`;
179
+ /**
180
+ * Wrap an XQuery node expression so supplemental nodes are omitted from it
181
+ * @param expression - The XQuery expression returning the nodes to filter
182
+ * @returns The wrapped XQuery expression
183
+ */
184
+ function omitSupplemental(expression) {
185
+ return `local:omit-supplemental(${expression})`;
186
+ }
187
+ /**
188
+ * XQuery predicate keeping only nodes that are neither supplemental themselves
189
+ * nor nested inside a supplemental node. Use it when aggregating over nodes
190
+ * instead of returning them.
191
+ */
192
+ const NOT_SUPPLEMENTAL_PREDICATE = "[not(ancestor-or-self::*[@supplemental = \"true\"])]";
193
+ /**
154
194
  * Flatten a properties array
155
195
  * @param properties - The properties to flatten
156
196
  * @returns The flattened properties
@@ -169,4 +209,4 @@ function flattenProperties(properties) {
169
209
  return result;
170
210
  }
171
211
  //#endregion
172
- export { createSchemaValidationError, flattenProperties, getErrorOutput, isPseudoUuid, stringLiteral };
212
+ export { NOT_SUPPLEMENTAL_PREDICATE, SUPPLEMENTAL_XQUERY_PROLOG, createSchemaValidationError, flattenProperties, getErrorOutput, isPseudoUuid, omitSupplemental, stringLiteral };
@@ -1,11 +1,6 @@
1
- import { XMLData as XMLData$1, XMLDataItem as XMLDataItem$1, XMLGalleryData as XMLGalleryData$1, XMLItemLinksData as XMLItemLinksData$1, XMLLink as XMLLink$1, XMLOcrMatchesData as XMLOcrMatchesData$1, XMLSetItemsData as XMLSetItemsData$1, XMLWebsiteData as XMLWebsiteData$1 } from "./types.mjs";
1
+ import { XMLData as XMLData$1, XMLDataItem as XMLDataItem$1, XMLGalleryData as XMLGalleryData$1, XMLItemLinksData as XMLItemLinksData$1, XMLLink as XMLLink$1, XMLSetItemsData as XMLSetItemsData$1, XMLWebsiteData as XMLWebsiteData$1 } from "./types.mjs";
2
2
  import * as v from "valibot";
3
3
  //#region src/xml/schemas.d.ts
4
- /**
5
- * Schema for validating OCR matches fetched from the OCHRE API
6
- * @internal
7
- */
8
- declare const XMLOcrMatchesData: v.GenericSchema<unknown, XMLOcrMatchesData$1>;
9
4
  declare const XMLLink: v.GenericSchema<unknown, XMLLink$1>;
10
5
  declare const XMLDataItem: v.GenericSchema<unknown, XMLDataItem$1>;
11
6
  declare const XMLItemLinksData: v.GenericSchema<unknown, XMLItemLinksData$1>;
@@ -14,4 +9,4 @@ declare const XMLSetItemsData: v.GenericSchema<unknown, XMLSetItemsData$1>;
14
9
  declare const XMLData: v.GenericSchema<unknown, XMLData$1>;
15
10
  declare const XMLWebsiteData: v.GenericSchema<unknown, XMLWebsiteData$1>;
16
11
  //#endregion
17
- export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLOcrMatchesData, XMLSetItemsData, XMLWebsiteData };
12
+ export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLSetItemsData, XMLWebsiteData };
@@ -224,42 +224,6 @@ const XMLImageMap = v.object({
224
224
  width: XMLNumber,
225
225
  height: XMLNumber
226
226
  }, "XMLImageMap: Shape error");
227
- const XMLOcrString = v.object({
228
- HPOS: XMLNumber,
229
- VPOS: XMLNumber,
230
- WIDTH: XMLNumber,
231
- HEIGHT: XMLNumber,
232
- CONTENT: v.string("XMLOcrString: CONTENT is string and required"),
233
- VERTICES: v.optional(v.string("XMLOcrString: VERTICES is string and optional"))
234
- }, "XMLOcrString: Shape error");
235
- const XMLOcrTextLine = v.object({ string: v.optional(v.array(XMLOcrString, "XMLOcrTextLine: string is array of XMLOcrString")) }, "XMLOcrTextLine: Shape error");
236
- const XMLOcrTextBlock = v.object({ TextLine: v.optional(v.array(XMLOcrTextLine, "XMLOcrTextBlock: TextLine is array of XMLOcrTextLine")) }, "XMLOcrTextBlock: Shape error");
237
- const XMLOcrPage = v.object({
238
- n: XMLOptionalNumber,
239
- fileName: v.optional(v.string("XMLOcrPage: fileName is string and optional")),
240
- WIDTH: XMLOptionalNumber,
241
- HEIGHT: XMLOptionalNumber,
242
- TextBlock: v.optional(v.array(XMLOcrTextBlock, "XMLOcrPage: TextBlock is array of XMLOcrTextBlock"))
243
- }, "XMLOcrPage: Shape error");
244
- const XMLOcr = v.object({ Page: v.optional(v.array(XMLOcrPage, "XMLOcr: Page is array of XMLOcrPage")) }, "XMLOcr: Shape error");
245
- const XMLOcrMatch = v.object({
246
- resourceUuid: v.optional(v.string("XMLOcrMatch: resourceUuid is string and optional")),
247
- n: XMLOptionalNumber,
248
- fileName: v.optional(v.string("XMLOcrMatch: fileName is string and optional")),
249
- WIDTH: XMLOptionalNumber,
250
- HEIGHT: XMLOptionalNumber,
251
- string: v.optional(v.array(XMLOcrString, "XMLOcrMatch: string is array of XMLOcrString"))
252
- }, "XMLOcrMatch: Shape error");
253
- const XMLOcrMatchItem = v.object({
254
- uuid: v.pipe(v.string("XMLOcrMatchItem: uuid is string and required"), v.check(isPseudoUuid, "XMLOcrMatchItem: uuid is not a valid pseudo-UUID")),
255
- matchCount: XMLNumber,
256
- ocrMatch: v.optional(v.array(XMLOcrMatch, "XMLOcrMatchItem: ocrMatch is array of XMLOcrMatch"))
257
- }, "XMLOcrMatchItem: Shape error");
258
- /**
259
- * Schema for validating OCR matches fetched from the OCHRE API
260
- * @internal
261
- */
262
- const XMLOcrMatchesData = v.object({ result: v.object({ ochre: v.object({ ocrMatches: v.optional(v.object({ ocrItem: v.optional(v.array(XMLOcrMatchItem, "XMLOcrMatchesData: ocrItem is array of XMLOcrMatchItem")) })) }) }) }, "XMLOcrMatchesData: Shape error");
263
227
  const XMLNote = v.object({
264
228
  content: v.optional(XMLContent.entries.content),
265
229
  payload: v.optional(v.string("XMLNote: payload is string and optional")),
@@ -680,7 +644,6 @@ const XMLResource = v.object({
680
644
  width: XMLOptionalNumber,
681
645
  image: v.optional(XMLImage),
682
646
  imagemap: v.optional(XMLImageMap),
683
- ocr: v.optional(XMLOcr),
684
647
  document: v.optional(XMLContent),
685
648
  coordinates: v.optional(XMLCoordinates),
686
649
  periods: v.optional(v.object({ period: v.array(XMLPeriod) })),
@@ -832,7 +795,6 @@ const XMLWebsiteResource = v.lazy(() => v.object({
832
795
  width: XMLOptionalNumber,
833
796
  image: v.optional(XMLImage),
834
797
  imagemap: v.optional(XMLImageMap),
835
- ocr: v.optional(XMLOcr),
836
798
  document: v.optional(XMLContent),
837
799
  coordinates: v.optional(XMLCoordinates),
838
800
  periods: v.optional(v.object({ period: v.array(XMLPeriod) })),
@@ -966,4 +928,4 @@ const XMLWebsiteData = v.object({ result: v.object({ ochre: v.object({
966
928
  tree: v.array(XMLWebsiteTree)
967
929
  }, "XMLWebsiteData: ochre is object with website tree") }, "XMLWebsiteData: result is object with ochre") }, "XMLWebsiteData: Shape error");
968
930
  //#endregion
969
- export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLOcrMatchesData, XMLSetItemsData, XMLWebsiteData };
931
+ export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLSetItemsData, XMLWebsiteData };
@@ -182,48 +182,6 @@ type XMLImageMap = {
182
182
  width: XMLNumber;
183
183
  height: XMLNumber;
184
184
  };
185
- type XMLOcrString = {
186
- HPOS: XMLNumber;
187
- VPOS: XMLNumber;
188
- WIDTH: XMLNumber;
189
- HEIGHT: XMLNumber;
190
- CONTENT: string;
191
- VERTICES?: string;
192
- };
193
- type XMLOcrTextLine = {
194
- string?: Array<XMLOcrString>;
195
- };
196
- type XMLOcrTextBlock = {
197
- TextLine?: Array<XMLOcrTextLine>;
198
- };
199
- type XMLOcrPage = {
200
- n?: XMLNumber;
201
- fileName?: string;
202
- WIDTH?: XMLNumber;
203
- HEIGHT?: XMLNumber;
204
- TextBlock?: Array<XMLOcrTextBlock>;
205
- };
206
- type XMLOcr = {
207
- Page?: Array<XMLOcrPage>;
208
- };
209
- type XMLOcrMatch = Omit<XMLOcrPage, "TextBlock"> & {
210
- resourceUuid?: string;
211
- string?: Array<XMLOcrString>;
212
- };
213
- type XMLOcrMatchItem = {
214
- uuid: string;
215
- matchCount: XMLNumber;
216
- ocrMatch?: Array<XMLOcrMatch>;
217
- };
218
- type XMLOcrMatchesData = {
219
- result: {
220
- ochre: {
221
- ocrMatches?: {
222
- ocrItem?: Array<XMLOcrMatchItem>;
223
- };
224
- };
225
- };
226
- };
227
185
  type XMLNote = Partial<XMLContent> & XMLString & {
228
186
  noteNo?: XMLNumber;
229
187
  title?: string;
@@ -605,7 +563,6 @@ type XMLResource = XMLBaseItem & {
605
563
  width?: XMLNumber;
606
564
  image?: XMLImage;
607
565
  imagemap?: XMLImageMap;
608
- ocr?: XMLOcr;
609
566
  document?: XMLContent;
610
567
  coordinates?: XMLCoordinates;
611
568
  periods?: {
@@ -963,4 +920,4 @@ type XMLWebsiteData = {
963
920
  };
964
921
  };
965
922
  //#endregion
966
- export { XMLBaseItem, XMLBibliography, XMLBoolean, XMLConcept, XMLContent, XMLContext, XMLContextGroup, XMLContextItem, XMLContextValue, XMLCoordinate, XMLCoordinates, XMLCoordinatesSource, XMLData, XMLDataItem, XMLDictionaryUnit, XMLEmptyContext, XMLEvent, XMLGallery, XMLGalleryData, XMLHeading, XMLHeadingItemCategory, XMLIdentification, XMLImage, XMLImageMap, XMLImageMapArea, XMLInterpretation, XMLItemCategory, XMLItemLinks, XMLItemLinksData, XMLLicense, XMLLink, XMLLinkedBaseItem, XMLLinkedBibliography, XMLLinkedConcept, XMLLinkedPeriod, XMLLinkedPerson, XMLLinkedPropertyValue, XMLLinkedPropertyVariable, XMLLinkedResource, XMLLinkedSet, XMLLinkedSpatialUnit, XMLLinkedText, XMLLinkedTree, XMLMetadata, XMLNote, XMLNumber, XMLObservation, XMLOcr, XMLOcrMatch, XMLOcrMatchItem, XMLOcrMatchesData, XMLOcrPage, XMLOcrString, XMLOcrTextBlock, XMLOcrTextLine, XMLPeriod, XMLPerson, XMLProperty, XMLPropertyRelation, XMLPropertyValue, XMLPropertyVariable, XMLRecursiveItemCategory, XMLResource, XMLRichTextEnvelope, XMLSection, XMLSet, XMLSetItems, XMLSetItemsData, XMLSimplifiedProperty, XMLSpatialUnit, XMLString, XMLText, XMLTree, XMLWebsiteContext, XMLWebsiteContextItem, XMLWebsiteContextLevel, XMLWebsiteData, XMLWebsiteFilterContext, XMLWebsiteFilterContextItem, XMLWebsiteOptions, XMLWebsiteProperties, XMLWebsiteResource, XMLWebsiteResourceGroup, XMLWebsiteResourceItem, XMLWebsiteScope, XMLWebsiteSegment, XMLWebsiteStyle, XMLWebsiteTree };
923
+ export { XMLBaseItem, XMLBibliography, XMLBoolean, XMLConcept, XMLContent, XMLContext, XMLContextGroup, XMLContextItem, XMLContextValue, XMLCoordinate, XMLCoordinates, XMLCoordinatesSource, XMLData, XMLDataItem, XMLDictionaryUnit, XMLEmptyContext, XMLEvent, XMLGallery, XMLGalleryData, XMLHeading, XMLHeadingItemCategory, XMLIdentification, XMLImage, XMLImageMap, XMLImageMapArea, XMLInterpretation, XMLItemCategory, XMLItemLinks, XMLItemLinksData, XMLLicense, XMLLink, XMLLinkedBaseItem, XMLLinkedBibliography, XMLLinkedConcept, XMLLinkedPeriod, XMLLinkedPerson, XMLLinkedPropertyValue, XMLLinkedPropertyVariable, XMLLinkedResource, XMLLinkedSet, XMLLinkedSpatialUnit, XMLLinkedText, XMLLinkedTree, XMLMetadata, XMLNote, XMLNumber, XMLObservation, XMLPeriod, XMLPerson, XMLProperty, XMLPropertyRelation, XMLPropertyValue, XMLPropertyVariable, XMLRecursiveItemCategory, XMLResource, XMLRichTextEnvelope, XMLSection, XMLSet, XMLSetItems, XMLSetItemsData, XMLSimplifiedProperty, XMLSpatialUnit, XMLString, XMLText, XMLTree, XMLWebsiteContext, XMLWebsiteContextItem, XMLWebsiteContextLevel, XMLWebsiteData, XMLWebsiteFilterContext, XMLWebsiteFilterContextItem, XMLWebsiteOptions, XMLWebsiteProperties, XMLWebsiteResource, XMLWebsiteResourceGroup, XMLWebsiteResourceItem, XMLWebsiteScope, XMLWebsiteSegment, XMLWebsiteStyle, XMLWebsiteTree };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ochre-sdk",
3
- "version": "1.0.72",
3
+ "version": "1.0.73",
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",
@@ -53,7 +53,7 @@
53
53
  "devDependencies": {
54
54
  "@antfu/eslint-config": "^9.2.0",
55
55
  "@types/node": "^24.13.3",
56
- "bumpp": "^12.1.1",
56
+ "bumpp": "^12.2.0",
57
57
  "eslint": "^10.8.0",
58
58
  "knip": "^6.31.0",
59
59
  "oxfmt": "^0.62.0",
@@ -1,44 +0,0 @@
1
- import { OcrMatch } from "../types/index.mjs";
2
- import { FetchFunction } from "../parsers/helpers.mjs";
3
- //#region src/fetchers/ocr-matches.d.ts
4
- /**
5
- * Fetches the locations of OCR text matches within OCHRE resources
6
- *
7
- * Matching mirrors the `ocr` Set item query target, so the same value and match
8
- * mode that selected an item will locate its hits. `matchCountsByUuid` reports
9
- * the untruncated count, which can exceed the returned matches when
10
- * `maxMatchesPerItem` caps them.
11
- *
12
- * @param parameters - The parameters for the fetch
13
- * @param parameters.uuids - The resource UUIDs to search, typically from a filtered Set item fetch
14
- * @param parameters.value - The search value
15
- * @param parameters.matchMode - Whether to match loosely (stemming and wildcards) or on whole OCR words, defaults to "includes"
16
- * @param parameters.isCaseSensitive - Whether matching is case sensitive, defaults to false
17
- * @param parameters.maxMatchesPerItem - The cap on returned matches per requested UUID, defaults to 50
18
- * @param options - Options for the fetch
19
- * @param options.fetch - The fetch function to use
20
- * @returns The OCR matches, or null if the fetch/parse fails
21
- */
22
- declare function fetchOcrMatches(parameters: {
23
- uuids: Array<string>;
24
- value: string;
25
- matchMode?: "includes" | "exact";
26
- isCaseSensitive?: boolean;
27
- maxMatchesPerItem?: number;
28
- }, options?: {
29
- fetch?: FetchFunction;
30
- }): Promise<{
31
- matches: Array<OcrMatch>;
32
- matchesByUuid: Record<string, Array<OcrMatch>>;
33
- matchCountsByUuid: Record<string, number>;
34
- error: null;
35
- detailedError: null;
36
- } | {
37
- matches: null;
38
- matchesByUuid: null;
39
- matchCountsByUuid: null;
40
- error: string;
41
- detailedError: string;
42
- }>;
43
- //#endregion
44
- export { fetchOcrMatches };
@@ -1,134 +0,0 @@
1
- import { XML_PARSER_OPTIONS } from "../constants.mjs";
2
- import { createSchemaValidationError, getErrorOutput, stringLiteral } from "../utilities.mjs";
3
- import { buildOcrTermQueryExpressions } from "../query.mjs";
4
- import { ocrMatchesParametersSchema } from "../schemas.mjs";
5
- import { restoreXMLMetadata } from "../xml/metadata.mjs";
6
- import { parseOcrMatches } from "../parsers/index.mjs";
7
- import { XMLOcrMatchesData } from "../xml/schemas.mjs";
8
- import * as v from "valibot";
9
- import { XMLParser } from "fast-xml-parser";
10
- //#region src/fetchers/ocr-matches.ts
11
- /**
12
- * Build an XQuery string to fetch OCR match locations from the OCHRE API
13
- *
14
- * Each OCR word is matched with `cts:contains` against the same per-term CTS
15
- * queries the Set item filter compiles, so hit locations always agree with what
16
- * the filter matched — including stemming and wildcards, which cannot be
17
- * reproduced outside MarkLogic.
18
- *
19
- * @param parameters - The parameters for the fetch
20
- * @param parameters.uuids - The resource UUIDs to search
21
- * @param parameters.termQueryExpressions - One CTS query expression per search term, in word order
22
- * @param parameters.maxMatchesPerItem - The cap on returned matches per requested UUID
23
- * @returns An XQuery string
24
- */
25
- function buildXQuery(parameters) {
26
- const { uuids, termQueryExpressions, maxMatchesPerItem } = parameters;
27
- return `xquery version "1.0-ml";
28
-
29
- declare variable $uuids := (${Array.from(uuids, (uuid) => stringLiteral(uuid)).join(", ")});
30
-
31
- declare variable $termQueries := (
32
- ${termQueryExpressions.join(",\n ")}
33
- );
34
-
35
- declare variable $termCount := ${termQueryExpressions.length};
36
-
37
- <ochre>{
38
- <ocrMatches>{
39
- for $uuid in $uuids
40
- let $matches :=
41
- for $page in doc($uuid)//ocr/Page
42
- let $words := $page//TextLine/string
43
- let $wordCount := count($words)
44
- let $resourceUuid := string($page/ancestor::resource[1]/@uuid)
45
- for $word at $index in $words
46
- where $index + $termCount - 1 le $wordCount
47
- and (every $offset in (1 to $termCount)
48
- satisfies cts:contains($words[$index + $offset - 1], $termQueries[$offset]))
49
- return <ocrMatch resourceUuid="{$resourceUuid}">{
50
- $page/@n, $page/@fileName, $page/@WIDTH, $page/@HEIGHT,
51
- subsequence($words, $index, $termCount)
52
- }</ocrMatch>
53
- return <ocrItem uuid="{$uuid}" matchCount="{count($matches)}">{
54
- subsequence($matches, 1, ${maxMatchesPerItem})
55
- }</ocrItem>
56
- }</ocrMatches>
57
- }</ochre>`;
58
- }
59
- /**
60
- * Fetches the locations of OCR text matches within OCHRE resources
61
- *
62
- * Matching mirrors the `ocr` Set item query target, so the same value and match
63
- * mode that selected an item will locate its hits. `matchCountsByUuid` reports
64
- * the untruncated count, which can exceed the returned matches when
65
- * `maxMatchesPerItem` caps them.
66
- *
67
- * @param parameters - The parameters for the fetch
68
- * @param parameters.uuids - The resource UUIDs to search, typically from a filtered Set item fetch
69
- * @param parameters.value - The search value
70
- * @param parameters.matchMode - Whether to match loosely (stemming and wildcards) or on whole OCR words, defaults to "includes"
71
- * @param parameters.isCaseSensitive - Whether matching is case sensitive, defaults to false
72
- * @param parameters.maxMatchesPerItem - The cap on returned matches per requested UUID, defaults to 50
73
- * @param options - Options for the fetch
74
- * @param options.fetch - The fetch function to use
75
- * @returns The OCR matches, or null if the fetch/parse fails
76
- */
77
- async function fetchOcrMatches(parameters, options) {
78
- try {
79
- const { uuids, value, matchMode, isCaseSensitive, maxMatchesPerItem } = v.parse(ocrMatchesParametersSchema, parameters);
80
- const termQueryExpressions = buildOcrTermQueryExpressions({
81
- value,
82
- matchMode,
83
- isCaseSensitive
84
- });
85
- if (termQueryExpressions.length === 0) return {
86
- matches: [],
87
- matchesByUuid: {},
88
- matchCountsByUuid: {},
89
- error: null,
90
- detailedError: null
91
- };
92
- const response = await (options?.fetch ?? fetch)("https://ochre.lib.uchicago.edu/ochre/v2/ochre.php?xquery&xsl=none&lang=\"*\"", {
93
- method: "POST",
94
- body: buildXQuery({
95
- uuids,
96
- termQueryExpressions,
97
- maxMatchesPerItem
98
- }),
99
- headers: { "Content-Type": "application/xquery" }
100
- });
101
- if (!response.ok) throw new Error(`OCHRE API responded with status: ${response.status}`, { cause: response.statusText });
102
- const dataRaw = await response.text();
103
- const data = new XMLParser(XML_PARSER_OPTIONS).parse(dataRaw);
104
- const { success, issues, output } = v.safeParse(XMLOcrMatchesData, data);
105
- if (!success) throw createSchemaValidationError("Failed to parse OCHRE OCR matches", issues);
106
- restoreXMLMetadata(output, data);
107
- const rawOcrItems = output.result.ochre.ocrMatches?.ocrItem ?? [];
108
- const matches = parseOcrMatches(rawOcrItems);
109
- const matchesByUuid = {};
110
- const matchCountsByUuid = {};
111
- for (const uuid of uuids) {
112
- matchesByUuid[uuid] = [];
113
- matchCountsByUuid[uuid] = 0;
114
- }
115
- for (const rawOcrItem of rawOcrItems) matchCountsByUuid[rawOcrItem.uuid] = rawOcrItem.matchCount;
116
- for (const match of matches) matchesByUuid[match.uuid]?.push(match);
117
- return {
118
- matches,
119
- matchesByUuid,
120
- matchCountsByUuid,
121
- error: null,
122
- detailedError: null
123
- };
124
- } catch (error) {
125
- return {
126
- matches: null,
127
- matchesByUuid: null,
128
- matchCountsByUuid: null,
129
- ...getErrorOutput(error, "Unknown error")
130
- };
131
- }
132
- }
133
- //#endregion
134
- export { fetchOcrMatches };