ochre-sdk 1.0.70 → 1.0.71
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/dist/constants.mjs +2 -0
- package/dist/fetchers/ocr-matches.d.mts +44 -0
- package/dist/fetchers/ocr-matches.mjs +134 -0
- package/dist/fetchers/set/items.mjs +6 -4
- package/dist/fetchers/set/property-values.mjs +6 -4
- package/dist/helpers.d.mts +5 -1
- package/dist/helpers.mjs +5 -1
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +3 -2
- package/dist/parsers/index.d.mts +10 -3
- package/dist/parsers/index.mjs +44 -10
- package/dist/query.d.mts +29 -1
- package/dist/query.mjs +100 -8
- package/dist/schemas.d.mts +14 -3
- package/dist/schemas.mjs +21 -2
- package/dist/types/index.d.mts +27 -1
- package/dist/xml/schemas.d.mts +7 -2
- package/dist/xml/schemas.mjs +19 -1
- package/dist/xml/types.d.mts +19 -1
- package/package.json +1 -1
package/dist/constants.mjs
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
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 };
|
|
@@ -0,0 +1,134 @@
|
|
|
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 };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BELONGS_TO_COLLECTION_UUID, DEFAULT_LANGUAGES, XML_PARSER_OPTIONS } from "../../constants.mjs";
|
|
2
2
|
import { createSchemaValidationError, getErrorOutput, stringLiteral } from "../../utilities.mjs";
|
|
3
|
+
import { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan } from "../../query.mjs";
|
|
3
4
|
import { iso639_3Schema, setItemsParametersSchema } from "../../schemas.mjs";
|
|
4
5
|
import { restoreXMLMetadata } from "../../xml/metadata.mjs";
|
|
5
6
|
import { parseSetItems } from "../../parsers/index.mjs";
|
|
6
7
|
import { XMLSetItemsData } from "../../xml/schemas.mjs";
|
|
7
|
-
import { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan } from "../../query.mjs";
|
|
8
8
|
import * as v from "valibot";
|
|
9
9
|
import { XMLParser } from "fast-xml-parser";
|
|
10
10
|
//#region src/fetchers/set/items.ts
|
|
@@ -138,8 +138,8 @@ function buildXQuery(parameters) {
|
|
|
138
138
|
const { queries, sort, setScopeUuids, belongsToCollectionScopeUuids, page, pageSize } = parameters;
|
|
139
139
|
const startPosition = (page - 1) * pageSize + 1;
|
|
140
140
|
const setScopeDeclaration = `declare variable $setScopeUuids := (${setScopeUuids.map((uuid) => stringLiteral(uuid)).join(", ")});`;
|
|
141
|
-
const baseItemsExpression = "doc()/ochre/set[@uuid = $setScopeUuids]/items/*";
|
|
142
141
|
const compiledQueryPlan = buildQueryPlan({ queries });
|
|
142
|
+
const baseItemsExpression = `doc()/ochre/set[@uuid = $setScopeUuids]/items/*${compiledQueryPlan.itemPredicates}`;
|
|
143
143
|
const itemsQueryExpressions = [];
|
|
144
144
|
const belongsToCollectionQueryExpression = buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID);
|
|
145
145
|
if (compiledQueryPlan.queryExpression != null) itemsQueryExpressions.push(compiledQueryPlan.queryExpression);
|
|
@@ -148,8 +148,10 @@ function buildXQuery(parameters) {
|
|
|
148
148
|
const orderedItemsClause = buildOrderedItemsClause(sort);
|
|
149
149
|
const xqueryDeclarations = ["xquery version \"1.0-ml\";", setScopeDeclaration];
|
|
150
150
|
if (compiledQueryPlan.prolog !== "") xqueryDeclarations.push(compiledQueryPlan.prolog);
|
|
151
|
-
const
|
|
152
|
-
|
|
151
|
+
const letClauses = Array.from(compiledQueryPlan.ocrBindings, (binding) => `let ${binding.name} := ${binding.expression}`);
|
|
152
|
+
if (itemsQueryExpression == null) letClauses.push(`let $items := ${baseItemsExpression}`);
|
|
153
|
+
else letClauses.push(`let $query := ${itemsQueryExpression}`, `let $items := cts:search(${baseItemsExpression}, $query)`);
|
|
154
|
+
const itemsClause = letClauses.join("\n ");
|
|
153
155
|
return `${xqueryDeclarations.join("\n\n")}
|
|
154
156
|
|
|
155
157
|
<ochre>{
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BELONGS_TO_COLLECTION_UUID, DEFAULT_LANGUAGES, XML_PARSER_OPTIONS } from "../../constants.mjs";
|
|
2
2
|
import { createSchemaValidationError, getErrorOutput, stringLiteral } from "../../utilities.mjs";
|
|
3
3
|
import { MultilingualString } from "../../parsers/multilingual.mjs";
|
|
4
|
+
import { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan } from "../../query.mjs";
|
|
4
5
|
import { setPropertyValuesParametersSchema } from "../../schemas.mjs";
|
|
5
6
|
import { parseXMLContent } from "../../parsers/string.mjs";
|
|
6
|
-
import { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan } from "../../query.mjs";
|
|
7
7
|
import * as v from "valibot";
|
|
8
8
|
import { XMLParser } from "fast-xml-parser";
|
|
9
9
|
//#region src/fetchers/set/property-values.ts
|
|
@@ -190,8 +190,8 @@ const responseSchema = v.object({ result: v.object({ ochre: v.object({
|
|
|
190
190
|
function buildXQuery(parameters) {
|
|
191
191
|
const { setScopeUuids, belongsToCollectionScopeUuids, queries, propertyFacetSelectors, attributes, isLimitedToLeafPropertyValues } = parameters;
|
|
192
192
|
const setScopeDeclaration = `declare variable $setScopeUuids := (${setScopeUuids.map((uuid) => stringLiteral(uuid)).join(", ")});`;
|
|
193
|
-
const baseItemsExpression = "doc()/ochre/set[@uuid = $setScopeUuids]/items/*";
|
|
194
193
|
const compiledQueryPlan = buildQueryPlan({ queries: getItemFilterQueriesFromPropertyValueQueries(queries) });
|
|
194
|
+
const baseItemsExpression = `doc()/ochre/set[@uuid = $setScopeUuids]/items/*${compiledQueryPlan.itemPredicates}`;
|
|
195
195
|
const itemsQueryExpressions = [];
|
|
196
196
|
const belongsToCollectionQueryExpression = buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, BELONGS_TO_COLLECTION_UUID);
|
|
197
197
|
if (compiledQueryPlan.queryExpression != null) itemsQueryExpressions.push(compiledQueryPlan.queryExpression);
|
|
@@ -404,8 +404,10 @@ let $period-values :=
|
|
|
404
404
|
)`);
|
|
405
405
|
returnedSequences.push("$period-values");
|
|
406
406
|
}
|
|
407
|
-
const
|
|
408
|
-
|
|
407
|
+
const letClauses = Array.from(compiledQueryPlan.ocrBindings, (binding) => `let ${binding.name} := ${binding.expression}`);
|
|
408
|
+
if (itemsQueryExpression == null) letClauses.push(`let $items := ${baseItemsExpression}`);
|
|
409
|
+
else letClauses.push(`let $query := ${itemsQueryExpression}`, `let $items := cts:search(${baseItemsExpression}, $query)`);
|
|
410
|
+
const itemsClause = letClauses.join("\n ");
|
|
409
411
|
return `${xqueryDeclarations.join("\n\n")}
|
|
410
412
|
|
|
411
413
|
<ochre>{
|
package/dist/helpers.d.mts
CHANGED
|
@@ -7,6 +7,10 @@ type FlattenedItem<U, T extends LanguageCodes> = Omit<U, "properties"> & {
|
|
|
7
7
|
* The default page size to use for fetching paginated items
|
|
8
8
|
*/
|
|
9
9
|
declare const DEFAULT_PAGE_SIZE = 48;
|
|
10
|
+
/**
|
|
11
|
+
* The default cap on OCR matches returned per requested item
|
|
12
|
+
*/
|
|
13
|
+
declare const DEFAULT_MAX_OCR_MATCHES_PER_ITEM = 50;
|
|
10
14
|
/**
|
|
11
15
|
* Flatten the properties of an item
|
|
12
16
|
* @param item - The item whose properties to flatten
|
|
@@ -14,4 +18,4 @@ declare const DEFAULT_PAGE_SIZE = 48;
|
|
|
14
18
|
*/
|
|
15
19
|
declare function flattenItemProperties<U extends ItemCategory = ItemCategory, V extends ContainedItemCategory<U> = ContainedItemCategory<U>, T extends LanguageCodes = LanguageCodes, W extends ItemPayloadKind = "topLevel">(item: Item<U, V, T, W>): FlattenedItem<Item<U, V, T, W>, T>;
|
|
16
20
|
//#endregion
|
|
17
|
-
export { DEFAULT_PAGE_SIZE, flattenItemProperties };
|
|
21
|
+
export { DEFAULT_MAX_OCR_MATCHES_PER_ITEM, DEFAULT_PAGE_SIZE, flattenItemProperties };
|
package/dist/helpers.mjs
CHANGED
|
@@ -5,6 +5,10 @@ import { flattenProperties } from "./utilities.mjs";
|
|
|
5
5
|
*/
|
|
6
6
|
const DEFAULT_PAGE_SIZE = 48;
|
|
7
7
|
/**
|
|
8
|
+
* The default cap on OCR matches returned per requested item
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_MAX_OCR_MATCHES_PER_ITEM = 50;
|
|
11
|
+
/**
|
|
8
12
|
* Flatten the properties of an item
|
|
9
13
|
* @param item - The item whose properties to flatten
|
|
10
14
|
* @returns The item with the properties flattened
|
|
@@ -30,4 +34,4 @@ function flattenItemProperties(item) {
|
|
|
30
34
|
};
|
|
31
35
|
}
|
|
32
36
|
//#endregion
|
|
33
|
-
export { DEFAULT_PAGE_SIZE, flattenItemProperties };
|
|
37
|
+
export { DEFAULT_MAX_OCR_MATCHES_PER_ITEM, DEFAULT_PAGE_SIZE, flattenItemProperties };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { MultilingualOptions, MultilingualString, MultilingualStringEntries, MultilingualStringEntry, MultilingualStringInput, MultilingualStringJSON, MultilingualStringObject, MultilingualStringText } from "./parsers/multilingual.mjs";
|
|
2
2
|
import { AccordionWebBlock, ContextTree, ContextTreeFilterLevel, ContextTreeLevel, ContextTreeLevelItem, ProtectedWebsite, Scope, Style, StylesheetCategory, StylesheetItem, WebAccordionItem, WebBlock, WebBlockByLayout, WebBlockItem, WebBlockLayout, WebElement, WebElementComponent, WebElementComponentName, WebElementComponentOf, WebElementOf, WebImage, WebSidebar, WebTitle, Webpage, Website, WebsiteMetadata, WebsitePropertyQuery, WebsitePropertyQueryNode, WebsiteSegment, WebsiteType } from "./types/website.mjs";
|
|
3
|
-
import { 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, 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 } from "./types/index.mjs";
|
|
3
|
+
import { 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 } from "./types/index.mjs";
|
|
4
4
|
import { fetchGallery } from "./fetchers/gallery.mjs";
|
|
5
5
|
import { fetchItemChildren } from "./fetchers/item-children.mjs";
|
|
6
6
|
import { fetchItemLinks } from "./fetchers/item-links.mjs";
|
|
7
7
|
import { defineLanguages, fetchItem, withLanguages } from "./fetchers/item.mjs";
|
|
8
|
+
import { fetchOcrMatches } from "./fetchers/ocr-matches.mjs";
|
|
8
9
|
import { fetchSetItems } from "./fetchers/set/items.mjs";
|
|
9
10
|
import { fetchSetPropertyValues } from "./fetchers/set/property-values.mjs";
|
|
10
11
|
import { fetchWebsiteMetadata } from "./fetchers/website-metadata.mjs";
|
|
11
12
|
import { fetchWebsite } from "./fetchers/website.mjs";
|
|
12
13
|
import { PropertyOptions, filterProperties, getLeafPropertyValues, getPropertyByVariableLabel, getPropertyByVariableLabelAndValue, getPropertyByVariableLabelAndValueContent, getPropertyByVariableLabelAndValueContents, getPropertyByVariableLabelAndValues, getPropertyByVariableUuid, getPropertyValueByVariableLabel, getPropertyValueByVariableUuid, getPropertyValueContentByVariableLabel, getPropertyValueContentByVariableUuid, getPropertyValueContentsByVariableUuid, getPropertyValuesByVariableLabel, getPropertyValuesByVariableUuid, getUniqueProperties, getUniquePropertyVariableLabels } from "./getters.mjs";
|
|
13
|
-
import { DEFAULT_PAGE_SIZE, flattenItemProperties } from "./helpers.mjs";
|
|
14
|
-
export { type AccordionWebBlock, type AnyBibliography, type AnyConcept, type AnyItem, type AnyPeriod, type AnyPerson, type AnyPropertyValue, type AnyPropertyVariable, type AnyResource, type AnySet, type AnySpatialUnit, type AnyText, type AnyTree, type BaseItem, type BaseItemLink, type BelongsTo, type Bibliography, type BibliographyEntryInfo, type BibliographyItemLink, type BibliographySourceDocument, type Concept, type ConceptItemLink, type ContainedItemCategory, type ContainedItemCategoryFromOption, type ContainedItemCategoryOption, type Context, type ContextItem, type ContextItemCategory, type ContextNode, type ContextTree, type ContextTreeFilterLevel, type ContextTreeLevel, type ContextTreeLevelItem, type Coordinates, type CoordinatesSource, DEFAULT_PAGE_SIZE, type DictionaryUnitItemLink, type EmbeddedBibliography, type EmbeddedConcept, type EmbeddedItem, type EmbeddedPeriod, type EmbeddedPerson, type EmbeddedPropertyValue, type EmbeddedPropertyVariable, type EmbeddedResource, type EmbeddedSet, type EmbeddedSpatialUnit, type EmbeddedText, type EmbeddedTree, type Event, type Gallery, type Heading, type HeadingItemCategory, type Identification, type Image, type ImageMap, type ImageMapArea, type Interpretation, type Item, type ItemCategory, type ItemCategoryFromOption, type ItemCategoryOption, type ItemCategoryWithEmbeddedItems, type ItemContainerCategory, type ItemLink, type ItemLinkCategory, type ItemLinks, type ItemPayloadKind, type ItemProperty, type ItemWithoutEmbeddedItems, type LanguageCodes, type License, type Metadata, type MultilingualOptions, MultilingualString, type MultilingualStringEntries, type MultilingualStringEntry, type MultilingualStringInput, type MultilingualStringJSON, type MultilingualStringObject, type MultilingualStringText, type Note, type Observation, type OcrPage, type OcrPoint, type OcrTextBlock, type OcrTextLine, type OcrWord, type Period, type PeriodItemLink, type Person, type PersonItemLink, type Prettify, type Property, type PropertyLike, PropertyOptions, type PropertyRelation, type PropertyValue, type PropertyValueContent, type PropertyValueDataType, type PropertyValueItemLink, type PropertyValueQueryItem, type PropertyVariable, type PropertyVariableItemLink, type ProtectedWebsite, type Query, type QueryGroup, type QueryLeaf, type QueryablePropertyValueDataType, type RecursiveItemCategory, type Resource, type ResourceItemLink, type Scope, type Section, type Set, type SetAttributeValueQueryItem, type SetBibliography, type SetConcept, type SetItem, type SetItemCategory, type SetItemLink, type SetItemProperty, type SetItemSimplifiedProperty, type SetItemsSort, type SetItemsSortDirection, type SetPeriod, type SetResource, type SetSpatialUnit, type SetTree, type SimplifiedProperty, type SpatialUnit, type SpatialUnitItemLink, type Style, type StylesheetCategory, type StylesheetItem, type Text, type TextItemLink, type TopLevelItem, type Tree, type TreeItemCategory, type TreeItemLink, type WebAccordionItem, type WebBlock, type WebBlockByLayout, type WebBlockItem, type WebBlockLayout, type WebElement, type WebElementComponent, type WebElementComponentName, type WebElementComponentOf, type WebElementOf, type WebImage, type WebSidebar, type WebTitle, type Webpage, type Website, type WebsiteMetadata, type WebsitePropertyQuery, type WebsitePropertyQueryNode, type WebsiteSegment, type WebsiteType, defineLanguages, fetchGallery, fetchItem, fetchItemChildren, fetchItemLinks, fetchSetItems, fetchSetPropertyValues, fetchWebsite, fetchWebsiteMetadata, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByVariableLabel, getPropertyByVariableLabelAndValue, getPropertyByVariableLabelAndValueContent, getPropertyByVariableLabelAndValueContents, getPropertyByVariableLabelAndValues, getPropertyByVariableUuid, getPropertyValueByVariableLabel, getPropertyValueByVariableUuid, getPropertyValueContentByVariableLabel, getPropertyValueContentByVariableUuid, getPropertyValueContentsByVariableUuid, getPropertyValuesByVariableLabel, getPropertyValuesByVariableUuid, getUniqueProperties, getUniquePropertyVariableLabels, withLanguages };
|
|
14
|
+
import { DEFAULT_MAX_OCR_MATCHES_PER_ITEM, DEFAULT_PAGE_SIZE, flattenItemProperties } from "./helpers.mjs";
|
|
15
|
+
export { type AccordionWebBlock, type AnyBibliography, type AnyConcept, type AnyItem, type AnyPeriod, type AnyPerson, type AnyPropertyValue, type AnyPropertyVariable, type AnyResource, type AnySet, type AnySpatialUnit, type AnyText, type AnyTree, type BaseItem, type BaseItemLink, type BelongsTo, type Bibliography, type BibliographyEntryInfo, type BibliographyItemLink, type BibliographySourceDocument, type Concept, type ConceptItemLink, type ContainedItemCategory, type ContainedItemCategoryFromOption, type ContainedItemCategoryOption, type Context, type ContextItem, type ContextItemCategory, type ContextNode, type ContextTree, type ContextTreeFilterLevel, type ContextTreeLevel, type ContextTreeLevelItem, type Coordinates, type CoordinatesSource, DEFAULT_MAX_OCR_MATCHES_PER_ITEM, DEFAULT_PAGE_SIZE, type DictionaryUnitItemLink, type EmbeddedBibliography, type EmbeddedConcept, type EmbeddedItem, type EmbeddedPeriod, type EmbeddedPerson, type EmbeddedPropertyValue, type EmbeddedPropertyVariable, type EmbeddedResource, type EmbeddedSet, type EmbeddedSpatialUnit, type EmbeddedText, type EmbeddedTree, type Event, type Gallery, type Heading, type HeadingItemCategory, type Identification, type Image, type ImageMap, type ImageMapArea, type Interpretation, type Item, type ItemCategory, type ItemCategoryFromOption, type ItemCategoryOption, type ItemCategoryWithEmbeddedItems, type ItemContainerCategory, type ItemLink, type ItemLinkCategory, type ItemLinks, type ItemPayloadKind, type ItemProperty, type ItemWithoutEmbeddedItems, type LanguageCodes, type License, type Metadata, type MultilingualOptions, MultilingualString, type MultilingualStringEntries, type MultilingualStringEntry, type MultilingualStringInput, type MultilingualStringJSON, type MultilingualStringObject, type MultilingualStringText, type Note, type Observation, type OcrMatch, type OcrPage, type OcrPoint, type OcrTextBlock, type OcrTextLine, type OcrWord, type Period, type PeriodItemLink, type Person, type PersonItemLink, type Prettify, type Property, type PropertyLike, PropertyOptions, type PropertyRelation, type PropertyValue, type PropertyValueContent, type PropertyValueDataType, type PropertyValueItemLink, type PropertyValueQueryItem, type PropertyVariable, type PropertyVariableItemLink, type ProtectedWebsite, type Query, type QueryGroup, type QueryLeaf, type QueryablePropertyValueDataType, type RecursiveItemCategory, type Resource, type ResourceItemLink, type Scope, type Section, type Set, type SetAttributeValueQueryItem, type SetBibliography, type SetConcept, type SetItem, type SetItemCategory, type SetItemLink, type SetItemProperty, type SetItemSimplifiedProperty, type SetItemsSort, type SetItemsSortDirection, type SetPeriod, type SetResource, type SetSpatialUnit, type SetTree, type SimplifiedProperty, type SpatialUnit, type SpatialUnitItemLink, type Style, type StylesheetCategory, type StylesheetItem, type Text, type TextItemLink, type TopLevelItem, type Tree, type TreeItemCategory, type TreeItemLink, type WebAccordionItem, type WebBlock, type WebBlockByLayout, type WebBlockItem, type WebBlockLayout, type WebElement, type WebElementComponent, type WebElementComponentName, type WebElementComponentOf, type WebElementOf, type WebImage, type WebSidebar, type WebTitle, type Webpage, type Website, type WebsiteMetadata, type WebsitePropertyQuery, type WebsitePropertyQueryNode, type WebsiteSegment, type WebsiteType, defineLanguages, fetchGallery, fetchItem, fetchItemChildren, fetchItemLinks, fetchOcrMatches, fetchSetItems, fetchSetPropertyValues, fetchWebsite, fetchWebsiteMetadata, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByVariableLabel, getPropertyByVariableLabelAndValue, getPropertyByVariableLabelAndValueContent, getPropertyByVariableLabelAndValueContents, getPropertyByVariableLabelAndValues, getPropertyByVariableUuid, getPropertyValueByVariableLabel, getPropertyValueByVariableUuid, getPropertyValueContentByVariableLabel, getPropertyValueContentByVariableUuid, getPropertyValueContentsByVariableUuid, getPropertyValuesByVariableLabel, getPropertyValuesByVariableUuid, getUniqueProperties, getUniquePropertyVariableLabels, withLanguages };
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { filterProperties, getLeafPropertyValues, getPropertyByVariableLabel, getPropertyByVariableLabelAndValue, getPropertyByVariableLabelAndValueContent, getPropertyByVariableLabelAndValueContents, getPropertyByVariableLabelAndValues, getPropertyByVariableUuid, getPropertyValueByVariableLabel, getPropertyValueByVariableUuid, getPropertyValueContentByVariableLabel, getPropertyValueContentByVariableUuid, getPropertyValueContentsByVariableUuid, getPropertyValuesByVariableLabel, getPropertyValuesByVariableUuid, getUniqueProperties, getUniquePropertyVariableLabels } from "./getters.mjs";
|
|
2
|
-
import { DEFAULT_PAGE_SIZE, flattenItemProperties } from "./helpers.mjs";
|
|
2
|
+
import { DEFAULT_MAX_OCR_MATCHES_PER_ITEM, DEFAULT_PAGE_SIZE, flattenItemProperties } from "./helpers.mjs";
|
|
3
3
|
import { MultilingualString } from "./parsers/multilingual.mjs";
|
|
4
4
|
import { fetchGallery } from "./fetchers/gallery.mjs";
|
|
5
5
|
import { fetchItemChildren } from "./fetchers/item-children.mjs";
|
|
6
6
|
import { fetchItemLinks } from "./fetchers/item-links.mjs";
|
|
7
7
|
import { defineLanguages, fetchItem, withLanguages } from "./fetchers/item.mjs";
|
|
8
|
+
import { fetchOcrMatches } from "./fetchers/ocr-matches.mjs";
|
|
8
9
|
import { fetchSetItems } from "./fetchers/set/items.mjs";
|
|
9
10
|
import { fetchSetPropertyValues } from "./fetchers/set/property-values.mjs";
|
|
10
11
|
import { fetchWebsiteMetadata } from "./fetchers/website-metadata.mjs";
|
|
11
12
|
import { fetchWebsite } from "./fetchers/website.mjs";
|
|
12
|
-
export { DEFAULT_PAGE_SIZE, MultilingualString, defineLanguages, fetchGallery, fetchItem, fetchItemChildren, fetchItemLinks, fetchSetItems, fetchSetPropertyValues, fetchWebsite, fetchWebsiteMetadata, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByVariableLabel, getPropertyByVariableLabelAndValue, getPropertyByVariableLabelAndValueContent, getPropertyByVariableLabelAndValueContents, getPropertyByVariableLabelAndValues, getPropertyByVariableUuid, getPropertyValueByVariableLabel, getPropertyValueByVariableUuid, getPropertyValueContentByVariableLabel, getPropertyValueContentByVariableUuid, getPropertyValueContentsByVariableUuid, getPropertyValuesByVariableLabel, getPropertyValuesByVariableUuid, getUniqueProperties, getUniquePropertyVariableLabels, withLanguages };
|
|
13
|
+
export { DEFAULT_MAX_OCR_MATCHES_PER_ITEM, DEFAULT_PAGE_SIZE, MultilingualString, defineLanguages, fetchGallery, fetchItem, fetchItemChildren, fetchItemLinks, fetchOcrMatches, fetchSetItems, fetchSetPropertyValues, fetchWebsite, fetchWebsiteMetadata, filterProperties, flattenItemProperties, getLeafPropertyValues, getPropertyByVariableLabel, getPropertyByVariableLabelAndValue, getPropertyByVariableLabelAndValueContent, getPropertyByVariableLabelAndValueContents, getPropertyByVariableLabelAndValues, getPropertyByVariableUuid, getPropertyValueByVariableLabel, getPropertyValueByVariableUuid, getPropertyValueContentByVariableLabel, getPropertyValueContentByVariableUuid, getPropertyValueContentsByVariableUuid, getPropertyValuesByVariableLabel, getPropertyValuesByVariableUuid, getUniqueProperties, getUniquePropertyVariableLabels, withLanguages };
|
package/dist/parsers/index.d.mts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import { Webpage } from "../types/website.mjs";
|
|
2
|
-
import { Bibliography, ContainedItemCategoryFromOption, ContainedItemCategoryOption, Gallery, Identification, Item, ItemCategory, ItemCategoryFromOption, ItemCategoryOption, ItemContainerCategory, ItemLinks, Metadata, Note, Person, Property, Resource, SetItem, SetItemCategory, SimplifiedProperty } from "../types/index.mjs";
|
|
3
|
-
import { XMLBibliography, XMLData, XMLDataItem, XMLGalleryData, XMLIdentification, XMLItemLinks, XMLLink, XMLMetadata, XMLNote, XMLPerson, XMLProperty, XMLResource, XMLSetItems, XMLSimplifiedProperty } from "../xml/types.mjs";
|
|
2
|
+
import { Bibliography, ContainedItemCategoryFromOption, ContainedItemCategoryOption, Gallery, Identification, Item, ItemCategory, ItemCategoryFromOption, ItemCategoryOption, ItemContainerCategory, ItemLinks, Metadata, Note, OcrMatch, Person, Property, Resource, SetItem, SetItemCategory, SimplifiedProperty } from "../types/index.mjs";
|
|
3
|
+
import { XMLBibliography, XMLData, XMLDataItem, XMLGalleryData, XMLIdentification, XMLItemLinks, XMLLink, XMLMetadata, XMLNote, XMLOcrMatchItem, XMLPerson, XMLProperty, XMLResource, XMLSetItems, XMLSimplifiedProperty } from "../xml/types.mjs";
|
|
4
4
|
import { ParserOptions, getParserOptions, parseStringLike } from "./helpers.mjs";
|
|
5
5
|
//#region src/parsers/index.d.ts
|
|
6
6
|
type RawOchre = XMLData["result"]["ochre"];
|
|
7
7
|
type ResourceViewParser<T extends ReadonlyArray<string>> = (view: XMLResource["view"], context: Pick<Resource<T, "topLevel">, "belongsTo" | "metadata">) => Webpage<T> | null;
|
|
8
8
|
type SetItemCategoryFromCategories<T extends ReadonlyArray<SetItemCategory> | undefined> = T extends ReadonlyArray<infer U> ? Extract<U, SetItemCategory> : SetItemCategory;
|
|
9
9
|
declare function parseIdentification<T extends ReadonlyArray<string>>(rawIdentification: XMLIdentification, options: ParserOptions<T>): Identification<T>;
|
|
10
|
+
/**
|
|
11
|
+
* Parse OCR matches returned by the OCHRE API
|
|
12
|
+
* @param rawOcrItems - The raw OCR match items
|
|
13
|
+
* @returns The parsed OCR matches, in request order
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
declare function parseOcrMatches(rawOcrItems: Array<XMLOcrMatchItem>): Array<OcrMatch>;
|
|
10
17
|
declare function parseNotes<T extends ReadonlyArray<string>>(rawNotes: {
|
|
11
18
|
note: Array<XMLNote>;
|
|
12
19
|
} | undefined, options: ParserOptions<T>): Array<Note<T>>;
|
|
@@ -61,4 +68,4 @@ declare function parseItem(rawData: XMLData, options: {
|
|
|
61
68
|
parseResourceView?: ResourceViewParser<ReadonlyArray<string>>;
|
|
62
69
|
}): Item<ItemCategory, SetItemCategory, ReadonlyArray<string>>;
|
|
63
70
|
//#endregion
|
|
64
|
-
export { type ParserOptions, RawOchre, getParserOptions, parseBibliographyList, parseGallery, parseIdentification, parseItem, parseLinkedItems, parseLinks, parseMetadata, parseMetadataLanguages, parseNotes, parsePersonList, parseProperties, parseSetItems, parseSimplifiedProperties, parseStringLike, resolveDefaultLanguage, resolveLanguages };
|
|
71
|
+
export { type ParserOptions, RawOchre, getParserOptions, parseBibliographyList, parseGallery, parseIdentification, parseItem, parseLinkedItems, parseLinks, parseMetadata, parseMetadataLanguages, parseNotes, parseOcrMatches, parsePersonList, parseProperties, parseSetItems, parseSimplifiedProperties, parseStringLike, resolveDefaultLanguage, resolveLanguages };
|
package/dist/parsers/index.mjs
CHANGED
|
@@ -443,18 +443,24 @@ function parseOcrVertices(rawVertices) {
|
|
|
443
443
|
}
|
|
444
444
|
return vertices;
|
|
445
445
|
}
|
|
446
|
+
function parseOcrWords(rawWords) {
|
|
447
|
+
return Array.from(rawWords ?? [], (rawWord) => ({
|
|
448
|
+
content: rawWord.CONTENT,
|
|
449
|
+
x: rawWord.HPOS,
|
|
450
|
+
y: rawWord.VPOS,
|
|
451
|
+
width: rawWord.WIDTH,
|
|
452
|
+
height: rawWord.HEIGHT,
|
|
453
|
+
vertices: parseOcrVertices(rawWord.VERTICES)
|
|
454
|
+
}));
|
|
455
|
+
}
|
|
456
|
+
function joinOcrWordContents(words) {
|
|
457
|
+
return Array.from(words, (word) => word.content).join(" ");
|
|
458
|
+
}
|
|
446
459
|
function parseOcrPage(rawPage) {
|
|
447
460
|
const blocks = Array.from(rawPage.TextBlock ?? [], (rawBlock) => ({ lines: Array.from(rawBlock.TextLine ?? [], (rawLine) => {
|
|
448
|
-
const words =
|
|
449
|
-
content: rawWord.CONTENT,
|
|
450
|
-
x: rawWord.HPOS,
|
|
451
|
-
y: rawWord.VPOS,
|
|
452
|
-
width: rawWord.WIDTH,
|
|
453
|
-
height: rawWord.HEIGHT,
|
|
454
|
-
vertices: parseOcrVertices(rawWord.VERTICES)
|
|
455
|
-
}));
|
|
461
|
+
const words = parseOcrWords(rawLine.string);
|
|
456
462
|
return {
|
|
457
|
-
content:
|
|
463
|
+
content: joinOcrWordContents(words),
|
|
458
464
|
words
|
|
459
465
|
};
|
|
460
466
|
}) }));
|
|
@@ -469,6 +475,34 @@ function parseOcrPage(rawPage) {
|
|
|
469
475
|
function parseOcr(rawOcr) {
|
|
470
476
|
return Array.from(rawOcr?.Page ?? [], (rawPage) => parseOcrPage(rawPage));
|
|
471
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* Parse OCR matches returned by the OCHRE API
|
|
480
|
+
* @param rawOcrItems - The raw OCR match items
|
|
481
|
+
* @returns The parsed OCR matches, in request order
|
|
482
|
+
* @internal
|
|
483
|
+
*/
|
|
484
|
+
function parseOcrMatches(rawOcrItems) {
|
|
485
|
+
const matches = [];
|
|
486
|
+
for (const rawOcrItem of rawOcrItems) {
|
|
487
|
+
const rawMatches = rawOcrItem.ocrMatch ?? [];
|
|
488
|
+
for (const rawMatch of rawMatches) {
|
|
489
|
+
const words = parseOcrWords(rawMatch.string);
|
|
490
|
+
matches.push({
|
|
491
|
+
uuid: rawOcrItem.uuid,
|
|
492
|
+
resourceUuid: rawMatch.resourceUuid ?? null,
|
|
493
|
+
page: {
|
|
494
|
+
number: rawMatch.n ?? null,
|
|
495
|
+
fileName: rawMatch.fileName ?? null,
|
|
496
|
+
width: rawMatch.WIDTH ?? null,
|
|
497
|
+
height: rawMatch.HEIGHT ?? null
|
|
498
|
+
},
|
|
499
|
+
content: joinOcrWordContents(words),
|
|
500
|
+
words
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return matches;
|
|
505
|
+
}
|
|
472
506
|
function parseNote(rawNote, options) {
|
|
473
507
|
const authors = Array.from(rawNote.authors?.author ?? [], (author) => parsePerson(author, options));
|
|
474
508
|
const content = rawNote.content == null ? multilingualFromText(parseXMLString(rawNote), options) : parseRequiredContentLike(rawNote, options);
|
|
@@ -1365,4 +1399,4 @@ function parseItem(rawData, options) {
|
|
|
1365
1399
|
};
|
|
1366
1400
|
}
|
|
1367
1401
|
//#endregion
|
|
1368
|
-
export { getParserOptions, parseBibliographyList, parseGallery, parseIdentification, parseItem, parseLinkedItems, parseLinks, parseMetadata, parseMetadataLanguages, parseNotes, parsePersonList, parseProperties, parseSetItems, parseSimplifiedProperties, parseStringLike, resolveDefaultLanguage, resolveLanguages };
|
|
1402
|
+
export { getParserOptions, parseBibliographyList, parseGallery, parseIdentification, parseItem, parseLinkedItems, parseLinks, parseMetadata, parseMetadataLanguages, parseNotes, parseOcrMatches, parsePersonList, parseProperties, parseSetItems, parseSimplifiedProperties, parseStringLike, resolveDefaultLanguage, resolveLanguages };
|
package/dist/query.d.mts
CHANGED
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
import { Query } from "./types/index.mjs";
|
|
2
2
|
//#region src/query.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Error message for OCR queries nested inside an OR group
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
declare const OCR_DISJUNCTION_ERROR_MESSAGE = "OCR queries cannot be nested inside an OR group because they are resolved by a document join instead of a CTS query";
|
|
8
|
+
type OcrUuidBinding = {
|
|
9
|
+
name: string;
|
|
10
|
+
expression: string;
|
|
11
|
+
};
|
|
3
12
|
declare function buildAndCtsQueryExpression(queryExpressions: Array<string>): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Compile one CTS query expression per OCR search term, in word order
|
|
15
|
+
*
|
|
16
|
+
* Highlighting matches each OCR word against these same per-term expressions,
|
|
17
|
+
* so hit locations always agree with what the filter matched.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
declare function buildOcrTermQueryExpressions(parameters: {
|
|
21
|
+
value: string;
|
|
22
|
+
matchMode: "includes" | "exact";
|
|
23
|
+
isCaseSensitive: boolean;
|
|
24
|
+
}): Array<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Whether a query tree nests an OCR leaf inside an OR group
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
29
|
+
declare function hasOcrQueryInDisjunction(query: Query, isInDisjunction?: boolean): boolean;
|
|
4
30
|
declare function buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids: Array<string>, belongsToCollectionPropertyVariableUuid: string): string | null;
|
|
5
31
|
declare function buildQueryPlan(parameters: {
|
|
6
32
|
queries: Query | null;
|
|
7
33
|
}): {
|
|
8
34
|
prolog: string;
|
|
9
35
|
queryExpression: string | null;
|
|
36
|
+
ocrBindings: Array<OcrUuidBinding>;
|
|
37
|
+
itemPredicates: string;
|
|
10
38
|
};
|
|
11
39
|
//#endregion
|
|
12
|
-
export { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan };
|
|
40
|
+
export { OCR_DISJUNCTION_ERROR_MESSAGE, buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildOcrTermQueryExpressions, buildQueryPlan, hasOcrQueryInDisjunction };
|
package/dist/query.mjs
CHANGED
|
@@ -12,6 +12,11 @@ const CTS_INCLUDES_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
|
12
12
|
const CTS_INCLUDES_TOKEN_WORD_REGEX = /^\p{L}+$/u;
|
|
13
13
|
const CTS_INCLUDES_TOKEN_REGEX = /[\p{L}\p{N}*?]+/gu;
|
|
14
14
|
const CTS_EXACT_TEXT_TOKEN_REGEX = /[\p{L}\p{N}]+/gu;
|
|
15
|
+
/**
|
|
16
|
+
* Error message for OCR queries nested inside an OR group
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
const OCR_DISJUNCTION_ERROR_MESSAGE = "OCR queries cannot be nested inside an OR group because they are resolved by a document join instead of a CTS query";
|
|
15
20
|
const CONTENT_TARGET_CONTENT_ELEMENT_PATHS = {
|
|
16
21
|
title: [
|
|
17
22
|
"identification",
|
|
@@ -199,6 +204,9 @@ function buildNestedElementQuery(elementNames, queryExpression) {
|
|
|
199
204
|
function buildNotCtsQueryExpression(queryExpression) {
|
|
200
205
|
return `cts:not-query(${queryExpression})`;
|
|
201
206
|
}
|
|
207
|
+
function buildCtsNearQueryExpression(queryExpressions) {
|
|
208
|
+
return `cts:near-query((${queryExpressions.join(", ")}), ${queryExpressions.length - 1}, ("ordered"))`;
|
|
209
|
+
}
|
|
202
210
|
function buildAndCtsQueryExpressionInternal(queryExpressions) {
|
|
203
211
|
if (queryExpressions.length === 0) return "cts:true-query()";
|
|
204
212
|
if (queryExpressions.length === 1) return queryExpressions[0] ?? "cts:true-query()";
|
|
@@ -472,6 +480,63 @@ function buildItemStringQueryExpression(parameters) {
|
|
|
472
480
|
language
|
|
473
481
|
})]);
|
|
474
482
|
}
|
|
483
|
+
function tokenizeOcrSearchValue(parameters) {
|
|
484
|
+
const { value, matchMode, isCaseSensitive } = parameters;
|
|
485
|
+
const rawTerms = (isCaseSensitive ? value : value.toLowerCase()).match(matchMode === "exact" ? CTS_EXACT_TEXT_TOKEN_REGEX : CTS_INCLUDES_TOKEN_REGEX) ?? [];
|
|
486
|
+
const terms = [];
|
|
487
|
+
for (const term of rawTerms) if (getWildcardStrippedValue(term) !== "") terms.push(term);
|
|
488
|
+
return terms;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Compile one CTS query expression per OCR search term, in word order
|
|
492
|
+
*
|
|
493
|
+
* Highlighting matches each OCR word against these same per-term expressions,
|
|
494
|
+
* so hit locations always agree with what the filter matched.
|
|
495
|
+
* @internal
|
|
496
|
+
*/
|
|
497
|
+
function buildOcrTermQueryExpressions(parameters) {
|
|
498
|
+
const { value, matchMode, isCaseSensitive } = parameters;
|
|
499
|
+
const terms = tokenizeOcrSearchValue({
|
|
500
|
+
value,
|
|
501
|
+
matchMode,
|
|
502
|
+
isCaseSensitive
|
|
503
|
+
});
|
|
504
|
+
const isWholeWordEquality = matchMode === "exact" && terms.length === 1;
|
|
505
|
+
return Array.from(terms, (term) => isWholeWordEquality ? buildCtsElementValueQueryExpression({
|
|
506
|
+
elementName: "string",
|
|
507
|
+
value: term,
|
|
508
|
+
isCaseSensitive
|
|
509
|
+
}) : buildCtsWordQueryExpression({
|
|
510
|
+
value: term,
|
|
511
|
+
matchMode,
|
|
512
|
+
isCaseSensitive,
|
|
513
|
+
queryFamily: "text"
|
|
514
|
+
}));
|
|
515
|
+
}
|
|
516
|
+
function buildOcrQueryExpression(query) {
|
|
517
|
+
const termQueryExpressions = buildOcrTermQueryExpressions(query);
|
|
518
|
+
if (termQueryExpressions.length === 0) return "cts:false-query()";
|
|
519
|
+
return buildNestedElementQuery(["ocr"], termQueryExpressions.length > 1 ? buildCtsNearQueryExpression(termQueryExpressions) : termQueryExpressions[0] ?? "cts:false-query()");
|
|
520
|
+
}
|
|
521
|
+
function registerOcrItemPredicate(context, query) {
|
|
522
|
+
const bindingKey = [
|
|
523
|
+
query.value,
|
|
524
|
+
query.matchMode,
|
|
525
|
+
query.isCaseSensitive ? "case-sensitive" : "case-insensitive"
|
|
526
|
+
].join("|");
|
|
527
|
+
let variableName = context.ocrVariableNamesByKey.get(bindingKey);
|
|
528
|
+
if (variableName == null) {
|
|
529
|
+
variableName = `$ocrUuids${context.nextOcrSerial}`;
|
|
530
|
+
context.nextOcrSerial += 1;
|
|
531
|
+
context.ocrVariableNamesByKey.set(bindingKey, variableName);
|
|
532
|
+
context.ocrBindings.push({
|
|
533
|
+
name: variableName,
|
|
534
|
+
expression: `for $ocrDocument in cts:search(doc(), ${buildOcrQueryExpression(query)})\n return document-uri($ocrDocument)`
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
const itemPredicate = query.isNegated === true ? `[not(@uuid = ${variableName})]` : `[@uuid = ${variableName}]`;
|
|
538
|
+
if (!context.itemPredicates.includes(itemPredicate)) context.itemPredicates.push(itemPredicate);
|
|
539
|
+
}
|
|
475
540
|
function getLeafSearchValue(query) {
|
|
476
541
|
switch (query.target) {
|
|
477
542
|
case "string":
|
|
@@ -552,7 +617,11 @@ function createQueryCompilerContext() {
|
|
|
552
617
|
return {
|
|
553
618
|
nextHelperSerial: 1,
|
|
554
619
|
helperNamesByKey: /* @__PURE__ */ new Map(),
|
|
555
|
-
helperDeclarations: []
|
|
620
|
+
helperDeclarations: [],
|
|
621
|
+
nextOcrSerial: 1,
|
|
622
|
+
ocrVariableNamesByKey: /* @__PURE__ */ new Map(),
|
|
623
|
+
ocrBindings: [],
|
|
624
|
+
itemPredicates: []
|
|
556
625
|
};
|
|
557
626
|
}
|
|
558
627
|
function registerConstantHelper(parameters) {
|
|
@@ -749,11 +818,24 @@ function getQueryGroupChildren(query) {
|
|
|
749
818
|
function getQueryGroupOperator(query) {
|
|
750
819
|
return "and" in query ? "and" : "or";
|
|
751
820
|
}
|
|
821
|
+
function isDisjunctiveQueryGroup(query) {
|
|
822
|
+
return "or" in query && query.or.length > 1;
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Whether a query tree nests an OCR leaf inside an OR group
|
|
826
|
+
* @internal
|
|
827
|
+
*/
|
|
828
|
+
function hasOcrQueryInDisjunction(query, isInDisjunction = false) {
|
|
829
|
+
if (isQueryLeaf(query)) return query.target === "ocr" && isInDisjunction;
|
|
830
|
+
const isChildInDisjunction = isInDisjunction || isDisjunctiveQueryGroup(query);
|
|
831
|
+
for (const childQuery of getQueryGroupChildren(query)) if (hasOcrQueryInDisjunction(childQuery, isChildInDisjunction)) return true;
|
|
832
|
+
return false;
|
|
833
|
+
}
|
|
752
834
|
function getCompatibleIncludesGroupLeaves(query) {
|
|
753
835
|
if (!("or" in query) || query.or.length <= 1) return null;
|
|
754
836
|
const leafQueries = [];
|
|
755
837
|
for (const childQuery of query.or) {
|
|
756
|
-
if (!isQueryLeaf(childQuery)) return null;
|
|
838
|
+
if (!isQueryLeaf(childQuery) || childQuery.target === "ocr") return null;
|
|
757
839
|
leafQueries.push(childQuery);
|
|
758
840
|
}
|
|
759
841
|
const firstQuery = leafQueries[0];
|
|
@@ -814,14 +896,20 @@ function buildIncludesGroupQueryExpression(context, queries) {
|
|
|
814
896
|
bodyExpression: buildOrCtsQueryExpressionInternal(exactMemberHelpers.map((helper) => helper.callExpression))
|
|
815
897
|
}).callExpression, tokenizedQueryExpression]);
|
|
816
898
|
}
|
|
817
|
-
function buildQueryNode(context, query) {
|
|
899
|
+
function buildQueryNode(context, query, isInDisjunction) {
|
|
818
900
|
if (isQueryLeaf(query)) {
|
|
901
|
+
if (query.target === "ocr") {
|
|
902
|
+
if (isInDisjunction) throw new Error(OCR_DISJUNCTION_ERROR_MESSAGE, { cause: query });
|
|
903
|
+
registerOcrItemPredicate(context, query);
|
|
904
|
+
return "cts:true-query()";
|
|
905
|
+
}
|
|
819
906
|
const queryExpression = buildLeafQueryExpression(context, query);
|
|
820
907
|
return query.isNegated === true ? buildNotCtsQueryExpression(queryExpression) : queryExpression;
|
|
821
908
|
}
|
|
822
909
|
const optimizedIncludesGroupQueries = getCompatibleIncludesGroupLeaves(query);
|
|
823
910
|
if (optimizedIncludesGroupQueries != null) return buildIncludesGroupQueryExpression(context, optimizedIncludesGroupQueries);
|
|
824
|
-
const
|
|
911
|
+
const isChildInDisjunction = isInDisjunction || isDisjunctiveQueryGroup(query);
|
|
912
|
+
const childQueryExpressions = Array.from(getQueryGroupChildren(query), (childQuery) => buildQueryNode(context, childQuery, isChildInDisjunction));
|
|
825
913
|
return (getQueryGroupOperator(query) === "and" ? buildAndCtsQueryExpressionInternal : buildOrCtsQueryExpressionInternal)(childQueryExpressions);
|
|
826
914
|
}
|
|
827
915
|
function buildBelongsToCollectionQueryExpression(belongsToCollectionScopeUuids, belongsToCollectionPropertyVariableUuid) {
|
|
@@ -839,14 +927,18 @@ function buildQueryPlan(parameters) {
|
|
|
839
927
|
const { queries } = parameters;
|
|
840
928
|
if (queries == null) return {
|
|
841
929
|
prolog: "",
|
|
842
|
-
queryExpression: null
|
|
930
|
+
queryExpression: null,
|
|
931
|
+
ocrBindings: [],
|
|
932
|
+
itemPredicates: ""
|
|
843
933
|
};
|
|
844
934
|
const context = createQueryCompilerContext();
|
|
845
|
-
const queryExpression = buildQueryNode(context, queries);
|
|
935
|
+
const queryExpression = buildQueryNode(context, queries, false);
|
|
846
936
|
return {
|
|
847
937
|
prolog: context.helperDeclarations.join("\n\n"),
|
|
848
|
-
queryExpression
|
|
938
|
+
queryExpression,
|
|
939
|
+
ocrBindings: context.ocrBindings,
|
|
940
|
+
itemPredicates: context.itemPredicates.join("")
|
|
849
941
|
};
|
|
850
942
|
}
|
|
851
943
|
//#endregion
|
|
852
|
-
export { buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildQueryPlan };
|
|
944
|
+
export { OCR_DISJUNCTION_ERROR_MESSAGE, buildAndCtsQueryExpression, buildBelongsToCollectionQueryExpression, buildOcrTermQueryExpressions, buildQueryPlan, hasOcrQueryInDisjunction };
|
package/dist/schemas.d.mts
CHANGED
|
@@ -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.GenericSchema<unknown, Query>, undefined>, null>;
|
|
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>;
|
|
42
42
|
readonly attributes: v.OptionalSchema<v.ObjectSchema<{
|
|
43
43
|
readonly bibliographies: v.GenericSchema<unknown, boolean>;
|
|
44
44
|
readonly periods: v.GenericSchema<unknown, boolean>;
|
|
@@ -48,6 +48,17 @@ declare const setPropertyValuesParametersSchema: v.ObjectSchema<{
|
|
|
48
48
|
}>;
|
|
49
49
|
readonly isLimitedToLeafPropertyValues: v.GenericSchema<unknown, boolean>;
|
|
50
50
|
}, undefined>;
|
|
51
|
+
/**
|
|
52
|
+
* Schema for validating OCR matches parameters
|
|
53
|
+
* @internal
|
|
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">]>;
|
|
58
|
+
readonly matchMode: v.OptionalSchema<v.PicklistSchema<["includes", "exact"], undefined>, "includes">;
|
|
59
|
+
readonly isCaseSensitive: v.GenericSchema<unknown, boolean>;
|
|
60
|
+
readonly maxMatchesPerItem: v.OptionalSchema<v.GenericSchema<unknown, number>, 50>;
|
|
61
|
+
}, undefined>;
|
|
51
62
|
/**
|
|
52
63
|
* Schema for validating Set items parameters
|
|
53
64
|
* @internal
|
|
@@ -55,7 +66,7 @@ declare const setPropertyValuesParametersSchema: v.ObjectSchema<{
|
|
|
55
66
|
declare const setItemsParametersSchema: v.ObjectSchema<{
|
|
56
67
|
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">]>;
|
|
57
68
|
readonly belongsToCollectionScopeUuids: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.CheckAction<string, "Invalid pseudo-UUID">]>, undefined>, readonly []>;
|
|
58
|
-
readonly queries: v.OptionalSchema<v.NullableSchema<v.GenericSchema<unknown, Query>, undefined>, null>;
|
|
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>;
|
|
59
70
|
readonly sort: v.OptionalSchema<v.VariantSchema<"target", [v.StrictObjectSchema<{
|
|
60
71
|
readonly target: v.LiteralSchema<"none", undefined>;
|
|
61
72
|
}, undefined>, v.StrictObjectSchema<{
|
|
@@ -75,4 +86,4 @@ declare const setItemsParametersSchema: v.ObjectSchema<{
|
|
|
75
86
|
readonly pageSize: v.OptionalSchema<v.GenericSchema<unknown, number>, 48>;
|
|
76
87
|
}, undefined>;
|
|
77
88
|
//#endregion
|
|
78
|
-
export { componentSchema, gallerySchema, iso639_3Schema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
|
|
89
|
+
export { componentSchema, gallerySchema, iso639_3Schema, ocrMatchesParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
|
package/dist/schemas.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isPseudoUuid } from "./utilities.mjs";
|
|
2
2
|
import "./helpers.mjs";
|
|
3
|
+
import { OCR_DISJUNCTION_ERROR_MESSAGE, hasOcrQueryInDisjunction } from "./query.mjs";
|
|
3
4
|
import * as v from "valibot";
|
|
4
5
|
//#region src/schemas.ts
|
|
5
6
|
const positiveNumber = (message) => v.pipe(v.number(), v.minValue(1, message));
|
|
@@ -141,6 +142,13 @@ const setQueryLeafSchema = v.union([
|
|
|
141
142
|
value: v.string(),
|
|
142
143
|
...standardQueryFields
|
|
143
144
|
}),
|
|
145
|
+
v.strictObject({
|
|
146
|
+
target: v.literal("ocr"),
|
|
147
|
+
value: v.string(),
|
|
148
|
+
matchMode: standardQueryFields.matchMode,
|
|
149
|
+
isCaseSensitive: standardQueryFields.isCaseSensitive,
|
|
150
|
+
isNegated: standardQueryFields.isNegated
|
|
151
|
+
}),
|
|
144
152
|
v.strictObject({
|
|
145
153
|
target: v.picklist([
|
|
146
154
|
"title",
|
|
@@ -167,7 +175,7 @@ const setQuerySchema = v.lazy(() => v.union([
|
|
|
167
175
|
* Schema for validating Set queries
|
|
168
176
|
* @internal
|
|
169
177
|
*/
|
|
170
|
-
const setQueriesSchema = v.optional(v.nullable(setQuerySchema), null);
|
|
178
|
+
const setQueriesSchema = v.optional(v.nullable(v.pipe(setQuerySchema, v.check((query) => !hasOcrQueryInDisjunction(query), OCR_DISJUNCTION_ERROR_MESSAGE))), null);
|
|
171
179
|
/**
|
|
172
180
|
* Schema for validating Set items sort
|
|
173
181
|
* @internal
|
|
@@ -214,6 +222,17 @@ const setPropertyValuesParametersSchema = v.object({
|
|
|
214
222
|
isLimitedToLeafPropertyValues: defaultBoolean(false)
|
|
215
223
|
});
|
|
216
224
|
/**
|
|
225
|
+
* Schema for validating OCR matches parameters
|
|
226
|
+
* @internal
|
|
227
|
+
*/
|
|
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")),
|
|
231
|
+
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)
|
|
234
|
+
});
|
|
235
|
+
/**
|
|
217
236
|
* Schema for validating Set items parameters
|
|
218
237
|
* @internal
|
|
219
238
|
*/
|
|
@@ -226,4 +245,4 @@ const setItemsParametersSchema = v.object({
|
|
|
226
245
|
pageSize: v.optional(positiveNumber("Page size must be positive"), 48)
|
|
227
246
|
});
|
|
228
247
|
//#endregion
|
|
229
|
-
export { componentSchema, gallerySchema, iso639_3Schema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
|
|
248
|
+
export { componentSchema, gallerySchema, iso639_3Schema, ocrMatchesParametersSchema, renderOptionsSchema, setItemsParametersSchema, setPropertyValuesParametersSchema, uuidSchema };
|
package/dist/types/index.d.mts
CHANGED
|
@@ -303,6 +303,19 @@ type OcrPage = {
|
|
|
303
303
|
height: number | null;
|
|
304
304
|
blocks: Array<OcrTextBlock>;
|
|
305
305
|
};
|
|
306
|
+
/**
|
|
307
|
+
* A run of adjacent OCR words matching a search value in OCHRE
|
|
308
|
+
*
|
|
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.
|
|
311
|
+
*/
|
|
312
|
+
type OcrMatch = {
|
|
313
|
+
uuid: string;
|
|
314
|
+
resourceUuid: string | null;
|
|
315
|
+
page: Omit<OcrPage, "blocks">;
|
|
316
|
+
content: string;
|
|
317
|
+
words: Array<OcrWord>;
|
|
318
|
+
};
|
|
306
319
|
/**
|
|
307
320
|
* Note in OCHRE
|
|
308
321
|
*/
|
|
@@ -831,6 +844,13 @@ type SetItemsSort = {
|
|
|
831
844
|
};
|
|
832
845
|
/**
|
|
833
846
|
* Represents a leaf query for Set items
|
|
847
|
+
*
|
|
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`.
|
|
834
854
|
*/
|
|
835
855
|
type QueryLeaf = {
|
|
836
856
|
target: "property";
|
|
@@ -897,6 +917,12 @@ type QueryLeaf = {
|
|
|
897
917
|
isCaseSensitive: boolean;
|
|
898
918
|
language: string;
|
|
899
919
|
isNegated?: boolean;
|
|
920
|
+
} | {
|
|
921
|
+
target: "ocr";
|
|
922
|
+
value: string;
|
|
923
|
+
matchMode: "includes" | "exact";
|
|
924
|
+
isCaseSensitive: boolean;
|
|
925
|
+
isNegated?: boolean;
|
|
900
926
|
} | {
|
|
901
927
|
target: "title" | "description" | "image" | "periods" | "bibliography" | "notes";
|
|
902
928
|
value: string;
|
|
@@ -918,4 +944,4 @@ type QueryGroup = {
|
|
|
918
944
|
*/
|
|
919
945
|
type Query = QueryLeaf | QueryGroup;
|
|
920
946
|
//#endregion
|
|
921
|
-
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, 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 };
|
|
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 };
|
package/dist/xml/schemas.d.mts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
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";
|
|
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";
|
|
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>;
|
|
4
9
|
declare const XMLLink: v.GenericSchema<unknown, XMLLink$1>;
|
|
5
10
|
declare const XMLDataItem: v.GenericSchema<unknown, XMLDataItem$1>;
|
|
6
11
|
declare const XMLItemLinksData: v.GenericSchema<unknown, XMLItemLinksData$1>;
|
|
@@ -9,4 +14,4 @@ declare const XMLSetItemsData: v.GenericSchema<unknown, XMLSetItemsData$1>;
|
|
|
9
14
|
declare const XMLData: v.GenericSchema<unknown, XMLData$1>;
|
|
10
15
|
declare const XMLWebsiteData: v.GenericSchema<unknown, XMLWebsiteData$1>;
|
|
11
16
|
//#endregion
|
|
12
|
-
export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLSetItemsData, XMLWebsiteData };
|
|
17
|
+
export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLOcrMatchesData, XMLSetItemsData, XMLWebsiteData };
|
package/dist/xml/schemas.mjs
CHANGED
|
@@ -238,6 +238,24 @@ const XMLOcrPage = v.object({
|
|
|
238
238
|
TextBlock: v.optional(v.array(XMLOcrTextBlock, "XMLOcrPage: TextBlock is array of XMLOcrTextBlock"))
|
|
239
239
|
}, "XMLOcrPage: Shape error");
|
|
240
240
|
const XMLOcr = v.object({ Page: v.optional(v.array(XMLOcrPage, "XMLOcr: Page is array of XMLOcrPage")) }, "XMLOcr: Shape error");
|
|
241
|
+
const XMLOcrMatch = v.object({
|
|
242
|
+
resourceUuid: v.optional(v.string("XMLOcrMatch: resourceUuid is string and optional")),
|
|
243
|
+
n: XMLOptionalNumber,
|
|
244
|
+
fileName: v.optional(v.string("XMLOcrMatch: fileName is string and optional")),
|
|
245
|
+
WIDTH: XMLOptionalNumber,
|
|
246
|
+
HEIGHT: XMLOptionalNumber,
|
|
247
|
+
string: v.optional(v.array(XMLOcrString, "XMLOcrMatch: string is array of XMLOcrString"))
|
|
248
|
+
}, "XMLOcrMatch: Shape error");
|
|
249
|
+
const XMLOcrMatchItem = v.object({
|
|
250
|
+
uuid: v.pipe(v.string("XMLOcrMatchItem: uuid is string and required"), v.check(isPseudoUuid, "XMLOcrMatchItem: uuid is not a valid pseudo-UUID")),
|
|
251
|
+
matchCount: XMLNumber,
|
|
252
|
+
ocrMatch: v.optional(v.array(XMLOcrMatch, "XMLOcrMatchItem: ocrMatch is array of XMLOcrMatch"))
|
|
253
|
+
}, "XMLOcrMatchItem: Shape error");
|
|
254
|
+
/**
|
|
255
|
+
* Schema for validating OCR matches fetched from the OCHRE API
|
|
256
|
+
* @internal
|
|
257
|
+
*/
|
|
258
|
+
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");
|
|
241
259
|
const XMLNote = v.object({
|
|
242
260
|
content: v.optional(XMLContent.entries.content),
|
|
243
261
|
payload: v.optional(v.string("XMLNote: payload is string and optional")),
|
|
@@ -944,4 +962,4 @@ const XMLWebsiteData = v.object({ result: v.object({ ochre: v.object({
|
|
|
944
962
|
tree: v.array(XMLWebsiteTree)
|
|
945
963
|
}, "XMLWebsiteData: ochre is object with website tree") }, "XMLWebsiteData: result is object with ochre") }, "XMLWebsiteData: Shape error");
|
|
946
964
|
//#endregion
|
|
947
|
-
export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLSetItemsData, XMLWebsiteData };
|
|
965
|
+
export { XMLData, XMLDataItem, XMLGalleryData, XMLItemLinksData, XMLLink, XMLOcrMatchesData, XMLSetItemsData, XMLWebsiteData };
|
package/dist/xml/types.d.mts
CHANGED
|
@@ -199,6 +199,24 @@ type XMLOcrPage = {
|
|
|
199
199
|
type XMLOcr = {
|
|
200
200
|
Page?: Array<XMLOcrPage>;
|
|
201
201
|
};
|
|
202
|
+
type XMLOcrMatch = Omit<XMLOcrPage, "TextBlock"> & {
|
|
203
|
+
resourceUuid?: string;
|
|
204
|
+
string?: Array<XMLOcrString>;
|
|
205
|
+
};
|
|
206
|
+
type XMLOcrMatchItem = {
|
|
207
|
+
uuid: string;
|
|
208
|
+
matchCount: XMLNumber;
|
|
209
|
+
ocrMatch?: Array<XMLOcrMatch>;
|
|
210
|
+
};
|
|
211
|
+
type XMLOcrMatchesData = {
|
|
212
|
+
result: {
|
|
213
|
+
ochre: {
|
|
214
|
+
ocrMatches?: {
|
|
215
|
+
ocrItem?: Array<XMLOcrMatchItem>;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
};
|
|
219
|
+
};
|
|
202
220
|
type XMLNote = Partial<XMLContent> & XMLString & {
|
|
203
221
|
noteNo?: XMLNumber;
|
|
204
222
|
title?: string;
|
|
@@ -938,4 +956,4 @@ type XMLWebsiteData = {
|
|
|
938
956
|
};
|
|
939
957
|
};
|
|
940
958
|
//#endregion
|
|
941
|
-
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, XMLOcrPage, XMLOcrString, XMLOcrTextBlock, XMLOcrTextLine, XMLPeriod, XMLPerson, XMLProperty, XMLPropertyRelation, XMLPropertyValue, XMLPropertyVariable, XMLRecursiveItemCategory, XMLResource, XMLSection, XMLSet, XMLSetItems, XMLSetItemsData, XMLSimplifiedProperty, XMLSpatialUnit, XMLString, XMLText, XMLTree, XMLWebsiteContext, XMLWebsiteContextItem, XMLWebsiteContextLevel, XMLWebsiteData, XMLWebsiteFilterContext, XMLWebsiteFilterContextItem, XMLWebsiteOptions, XMLWebsiteProperties, XMLWebsiteResource, XMLWebsiteResourceGroup, XMLWebsiteResourceItem, XMLWebsiteScope, XMLWebsiteSegment, XMLWebsiteStyle, XMLWebsiteTree };
|
|
959
|
+
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, XMLSection, XMLSet, XMLSetItems, XMLSetItemsData, XMLSimplifiedProperty, XMLSpatialUnit, XMLString, XMLText, XMLTree, XMLWebsiteContext, XMLWebsiteContextItem, XMLWebsiteContextLevel, XMLWebsiteData, XMLWebsiteFilterContext, XMLWebsiteFilterContextItem, XMLWebsiteOptions, XMLWebsiteProperties, XMLWebsiteResource, XMLWebsiteResourceGroup, XMLWebsiteResourceItem, XMLWebsiteScope, XMLWebsiteSegment, XMLWebsiteStyle, XMLWebsiteTree };
|