structural-codes-viewer 0.1.0-alpha.1 → 0.1.0-alpha.2
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/LICENSE +501 -0
- package/NOTICE +16 -0
- package/README.md +119 -63
- package/package-dist/CorpusContent.d.ts +44 -9
- package/package-dist/CorpusContent.js +452 -26
- package/package-dist/CorpusContent.js.map +1 -1
- package/package-dist/NormativeViewer.d.ts +23 -2
- package/package-dist/NormativeViewer.js +1699 -234
- package/package-dist/NormativeViewer.js.map +1 -1
- package/package-dist/ReferenceTools.d.ts +49 -0
- package/package-dist/ReferenceTools.js +14 -0
- package/package-dist/ReferenceTools.js.map +1 -0
- package/package-dist/annotations/AnnotationUi.d.ts +57 -0
- package/package-dist/annotations/AnnotationUi.js +114 -0
- package/package-dist/annotations/AnnotationUi.js.map +1 -0
- package/package-dist/annotations/annotationTargets.d.ts +39 -0
- package/package-dist/annotations/annotationTargets.js +94 -0
- package/package-dist/annotations/annotationTargets.js.map +1 -0
- package/package-dist/annotations/exportImport.d.ts +6 -0
- package/package-dist/annotations/exportImport.js +30 -0
- package/package-dist/annotations/exportImport.js.map +1 -0
- package/package-dist/annotations/index.d.ts +4 -0
- package/package-dist/annotations/index.js +5 -0
- package/package-dist/annotations/index.js.map +1 -0
- package/package-dist/annotations/indexedDb.d.ts +21 -0
- package/package-dist/annotations/indexedDb.js +210 -0
- package/package-dist/annotations/indexedDb.js.map +1 -0
- package/package-dist/annotations/schema.d.ts +8 -0
- package/package-dist/annotations/schema.js +102 -0
- package/package-dist/annotations/schema.js.map +1 -0
- package/package-dist/annotations/types.d.ts +52 -0
- package/package-dist/annotations/types.js +18 -0
- package/package-dist/annotations/types.js.map +1 -0
- package/package-dist/chatntc/canonicalization.d.ts +15 -0
- package/package-dist/chatntc/canonicalization.js +107 -0
- package/package-dist/chatntc/canonicalization.js.map +1 -0
- package/package-dist/chatntc/directives.d.ts +2 -0
- package/package-dist/chatntc/directives.js +38 -0
- package/package-dist/chatntc/directives.js.map +1 -0
- package/package-dist/chatntc/evidence.d.ts +17 -0
- package/package-dist/chatntc/evidence.js +116 -0
- package/package-dist/chatntc/evidence.js.map +1 -0
- package/package-dist/chatntc/index.d.ts +10 -0
- package/package-dist/chatntc/index.js +9 -0
- package/package-dist/chatntc/index.js.map +1 -0
- package/package-dist/chatntc/issueCategories.d.ts +2 -0
- package/package-dist/chatntc/issueCategories.js +11 -0
- package/package-dist/chatntc/issueCategories.js.map +1 -0
- package/package-dist/chatntc/policy.d.ts +35 -0
- package/package-dist/chatntc/policy.js +36 -0
- package/package-dist/chatntc/policy.js.map +1 -0
- package/package-dist/chatntc/provider.d.ts +42 -0
- package/package-dist/chatntc/provider.js +2 -0
- package/package-dist/chatntc/provider.js.map +1 -0
- package/package-dist/chatntc/responseContract.d.ts +52 -0
- package/package-dist/chatntc/responseContract.js +73 -0
- package/package-dist/chatntc/responseContract.js.map +1 -0
- package/package-dist/chatntc/retrieval.d.ts +5 -0
- package/package-dist/chatntc/retrieval.js +220 -0
- package/package-dist/chatntc/retrieval.js.map +1 -0
- package/package-dist/chatntc/types.d.ts +240 -0
- package/package-dist/chatntc/types.js +2 -0
- package/package-dist/chatntc/types.js.map +1 -0
- package/package-dist/chatntc/validation.d.ts +8 -0
- package/package-dist/chatntc/validation.js +299 -0
- package/package-dist/chatntc/validation.js.map +1 -0
- package/package-dist/chatntc/viewerArtifacts.d.ts +14 -0
- package/package-dist/chatntc/viewerArtifacts.js +168 -0
- package/package-dist/chatntc/viewerArtifacts.js.map +1 -0
- package/package-dist/chatntc-history/index.d.ts +2 -0
- package/package-dist/chatntc-history/index.js +3 -0
- package/package-dist/chatntc-history/index.js.map +1 -0
- package/package-dist/chatntc-history/indexedDb.d.ts +27 -0
- package/package-dist/chatntc-history/indexedDb.js +258 -0
- package/package-dist/chatntc-history/indexedDb.js.map +1 -0
- package/package-dist/chatntc-history/schema.d.ts +5 -0
- package/package-dist/chatntc-history/schema.js +102 -0
- package/package-dist/chatntc-history/schema.js.map +1 -0
- package/package-dist/chatntc-history/types.d.ts +78 -0
- package/package-dist/chatntc-history/types.js +23 -0
- package/package-dist/chatntc-history/types.js.map +1 -0
- package/package-dist/chatntc-ui/ChatNTCHistoryPanel.d.ts +9 -0
- package/package-dist/chatntc-ui/ChatNTCHistoryPanel.js +239 -0
- package/package-dist/chatntc-ui/ChatNTCHistoryPanel.js.map +1 -0
- package/package-dist/chatntc-ui/ChatNTCIcons.d.ts +10 -0
- package/package-dist/chatntc-ui/ChatNTCIcons.js +20 -0
- package/package-dist/chatntc-ui/ChatNTCIcons.js.map +1 -0
- package/package-dist/chatntc-ui/ChatNTCLoadingSkeleton.d.ts +1 -0
- package/package-dist/chatntc-ui/ChatNTCLoadingSkeleton.js +5 -0
- package/package-dist/chatntc-ui/ChatNTCLoadingSkeleton.js.map +1 -0
- package/package-dist/chatntc-ui/ChatNTCMarkdown.d.ts +14 -0
- package/package-dist/chatntc-ui/ChatNTCMarkdown.js +112 -0
- package/package-dist/chatntc-ui/ChatNTCMarkdown.js.map +1 -0
- package/package-dist/chatntc-ui/ChatNTCPanel.d.ts +29 -0
- package/package-dist/chatntc-ui/ChatNTCPanel.js +241 -0
- package/package-dist/chatntc-ui/ChatNTCPanel.js.map +1 -0
- package/package-dist/chatntc-ui/historyMessages.d.ts +5 -0
- package/package-dist/chatntc-ui/historyMessages.js +53 -0
- package/package-dist/chatntc-ui/historyMessages.js.map +1 -0
- package/package-dist/chatntc-ui/index.d.ts +3 -0
- package/package-dist/chatntc-ui/index.js +4 -0
- package/package-dist/chatntc-ui/index.js.map +1 -0
- package/package-dist/chatntc-ui/transport.d.ts +51 -0
- package/package-dist/chatntc-ui/transport.js +9 -0
- package/package-dist/chatntc-ui/transport.js.map +1 -0
- package/package-dist/chunkNavigation.d.ts +12 -0
- package/package-dist/chunkNavigation.js +44 -0
- package/package-dist/chunkNavigation.js.map +1 -0
- package/package-dist/corpusData.d.ts +176 -33
- package/package-dist/corpusData.js +52 -0
- package/package-dist/corpusData.js.map +1 -1
- package/package-dist/crossReferences.d.ts +46 -0
- package/package-dist/crossReferences.js +198 -0
- package/package-dist/crossReferences.js.map +1 -0
- package/package-dist/generate-artifacts.mjs +47 -12
- package/package-dist/globalScrubber.d.ts +10 -0
- package/package-dist/globalScrubber.js +85 -0
- package/package-dist/globalScrubber.js.map +1 -0
- package/package-dist/permalinks.d.ts +22 -0
- package/package-dist/permalinks.js +36 -0
- package/package-dist/permalinks.js.map +1 -0
- package/package-dist/searchClient.d.ts +22 -0
- package/package-dist/searchClient.js +133 -0
- package/package-dist/searchClient.js.map +1 -0
- package/package-dist/searchEngine.d.ts +68 -0
- package/package-dist/searchEngine.js +558 -0
- package/package-dist/searchEngine.js.map +1 -0
- package/package-dist/searchWorker.d.ts +1 -0
- package/package-dist/searchWorker.js +32 -0
- package/package-dist/searchWorker.js.map +1 -0
- package/package-dist/styles.css +927 -182
- package/package-dist/tableCaptions.d.mts +3 -0
- package/package-dist/tableCaptions.mjs +35 -0
- package/package-dist/tableCaptions.mjs.map +1 -0
- package/package.json +61 -15
|
@@ -3,6 +3,8 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { copyFile, mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname, join, relative, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
+
import { buildSearchIndexPayload } from "./searchEngine.js";
|
|
7
|
+
import { buildCrossReferenceIndexPayload } from "./crossReferences.js";
|
|
6
8
|
|
|
7
9
|
const documentOrder = ["ntc2018", "circ2019"];
|
|
8
10
|
const maxInitialChunkBytes = 1_500_000;
|
|
@@ -61,8 +63,39 @@ function assignChunkKeys(units) {
|
|
|
61
63
|
}
|
|
62
64
|
function publicUnit(document, unit) { return { ...unit, document }; }
|
|
63
65
|
function unitSummary(document, unit, chunkPath) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
return { id: unit.id, document, kind: unit.kind, numbering: unit.numbering, title: unit.title, hierarchy: unit.hierarchy, validity: unit.validity, reviewStatus: unit.review.status, chunkPath };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function compactSearchText(parts) {
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
return parts.flatMap((part) => {
|
|
72
|
+
const text = String(part ?? "").replace(/\s+/gu, " ").trim();
|
|
73
|
+
const key = text.normalize("NFKC").toLocaleLowerCase("it");
|
|
74
|
+
if (!text || seen.has(key)) return [];
|
|
75
|
+
seen.add(key);
|
|
76
|
+
return [text];
|
|
77
|
+
}).join(" ");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function searchableAssetText(kind, asset) {
|
|
81
|
+
const label = kind === "formula" ? "Formula" : kind === "table" ? "Tabella" : "Figura";
|
|
82
|
+
const identity = asset.officialNumber ? `${label} ${asset.officialNumber}` : label;
|
|
83
|
+
if (kind === "formula") return identity;
|
|
84
|
+
if (kind === "figure") return compactSearchText([identity, asset.caption, asset.alt]);
|
|
85
|
+
const cells = [...asset.headers, ...asset.rows, ...(asset.footerRows ?? [])].flat().map((cell) => cell.text);
|
|
86
|
+
return compactSearchText([identity, asset.caption, ...cells, ...asset.notes]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function searchSegments(unit, assetById) {
|
|
90
|
+
return unit.blocks.flatMap((block) => {
|
|
91
|
+
const segments = [];
|
|
92
|
+
if (block.text?.normalized && block.blockId !== unit.titleBlockId) segments.push({ blockId: block.blockId, text: block.text.normalized });
|
|
93
|
+
if (block.assetId) {
|
|
94
|
+
const found = assetById.get(block.assetId);
|
|
95
|
+
if (found) segments.push({ blockId: block.blockId, assetId: block.assetId, assetKind: found.kind, officialNumber: found.asset.officialNumber, text: searchableAssetText(found.kind, found.asset) });
|
|
96
|
+
}
|
|
97
|
+
return segments;
|
|
98
|
+
});
|
|
66
99
|
}
|
|
67
100
|
|
|
68
101
|
export async function generateArtifacts({ sourcePackage = "structural-codes", outputDirectory = join(process.cwd(), "public", "data", "codes"), assetOutputDirectory = join(process.cwd(), "public", "assets") } = {}) {
|
|
@@ -74,16 +107,16 @@ export async function generateArtifacts({ sourcePackage = "structural-codes", ou
|
|
|
74
107
|
const assetManifestDirectory = join(sourceRoot, "corpus", "assets");
|
|
75
108
|
const sourceRegistryFile = join(sourceRoot, "sources", "registry", "sources.v2.json");
|
|
76
109
|
const packageFile = join(sourceRoot, "package.json");
|
|
77
|
-
const legacyOutput = join(dirname(outputDirectory), "corpus.json");
|
|
78
110
|
const figureOutput = assetOutputDirectory;
|
|
79
111
|
const [corpusManifest, sourceRegistry, packageManifest] = await Promise.all([json(corpusManifestFile), json(sourceRegistryFile), json(packageFile)]);
|
|
80
112
|
const assetManifestFiles = (await readdir(assetManifestDirectory, { recursive: true })).filter((file) => file.endsWith(".json")).sort((left, right) => left.localeCompare(right, "it", { numeric: true }));
|
|
81
113
|
const assetManifests = await Promise.all(assetManifestFiles.map((file) => json(join(assetManifestDirectory, file))));
|
|
82
114
|
const assetCollections = { formulas: assetManifests.flatMap(({ formulas }) => formulas), tables: assetManifests.flatMap(({ tables }) => tables), figures: assetManifests.flatMap(({ figures }) => figures) };
|
|
83
115
|
const assetsById = Object.fromEntries(Object.entries(assetCollections).map(([kind, assets]) => [kind, new Map(assets.map((asset) => [asset.id, asset]))]));
|
|
116
|
+
const searchableAssetById = new Map(Object.entries(assetCollections).flatMap(([collection, assets]) => assets.map((asset) => [asset.id, { kind: collection === "formulas" ? "formula" : collection === "tables" ? "table" : "figure", asset }])));
|
|
84
117
|
const unitsByDocument = Object.fromEntries(await Promise.all(documentOrder.map(async (document) => [document, await loadUnits(corpusRoot, document)])));
|
|
85
118
|
const allUnits = documentOrder.flatMap((document) => unitsByDocument[document].map((unit) => publicUnit(document, unit)));
|
|
86
|
-
await Promise.all([rm(outputDirectory, { recursive: true, force: true }), rm(
|
|
119
|
+
await Promise.all([rm(outputDirectory, { recursive: true, force: true }), rm(figureOutput, { recursive: true, force: true })]);
|
|
87
120
|
const chunkPathByUnit = new Map();
|
|
88
121
|
const documentIndexes = {};
|
|
89
122
|
const chunkInventory = [];
|
|
@@ -119,8 +152,9 @@ export async function generateArtifacts({ sourcePackage = "structural-codes", ou
|
|
|
119
152
|
const relationsWritten = await writeJson(join(outputDirectory, "relations.json"), { formatVersion: 2, sourceOfTruth: "explicit-corpus-relations", inferredRelationsIncluded: false, relations });
|
|
120
153
|
const ntcByNumber = new Map(unitsByDocument.ntc2018.map((unit) => [unit.numbering.official, unit]));
|
|
121
154
|
const diagnostics = unitsByDocument.circ2019.flatMap((unit) => { const candidate = ntcByNumber.get(unit.numbering.official.replace(/^C/iu, "")); if (!candidate || unit.relations.some((relation) => relation.targetUnitId === candidate.id)) return []; return [{ kind: "suggested-relation", status: "diagnostic-only-not-canonical", reason: "same-numbering", sourceUnitId: unit.id, targetUnitId: candidate.id, sourceChunkPath: chunkPathByUnit.get(unit.id), targetChunkPath: chunkPathByUnit.get(candidate.id) }]; });
|
|
122
|
-
const diagnosticsWritten = await writeJson(join(outputDirectory, "relation-diagnostics.json"), { formatVersion: 2, warning: "Suggerimenti diagnostici non
|
|
123
|
-
const searchWritten = await writeJson(join(outputDirectory, "search-index.json"),
|
|
155
|
+
const diagnosticsWritten = await writeJson(join(outputDirectory, "relation-diagnostics.json"), { formatVersion: 2, warning: "Suggerimenti diagnostici non confermati: non sono usati dalla vista combinata.", suggestions: diagnostics });
|
|
156
|
+
const searchWritten = await writeJson(join(outputDirectory, "search-index.json"), buildSearchIndexPayload(allUnits.map((unit) => ({ id: unit.id, document: unit.document, numbering: unit.numbering.official, title: unit.title, titleBlockId: unit.titleBlockId, chunkPath: chunkPathByUnit.get(unit.id), segments: searchSegments(unit, searchableAssetById) }))));
|
|
157
|
+
const crossReferenceWritten = await writeJson(join(outputDirectory, "cross-reference-index.json"), buildCrossReferenceIndexPayload({ units: allUnits, assetCollections }));
|
|
124
158
|
const manifestationBySourceId = new Map(sourceRegistry.works.flatMap((work) => work.manifestations.map((manifestation) => [manifestation.sourceId, { manifestation, work }])));
|
|
125
159
|
for (const document of documentOrder) {
|
|
126
160
|
const manifestDocument = corpusManifest.documents[document];
|
|
@@ -128,15 +162,16 @@ export async function generateArtifacts({ sourcePackage = "structural-codes", ou
|
|
|
128
162
|
if (!source) throw new Error(`sourceId non risolto: ${manifestDocument.sourceId}`);
|
|
129
163
|
Object.assign(documentIndexes[document], { sourceId: manifestDocument.sourceId, sourceUrl: source.manifestation.officialUrl, publicationUrl: source.work.publication.eliUri, localSourcePath: source.manifestation.localFile, sourceSha256: source.manifestation.sha256, pages: manifestDocument.pages, blocks: unitsByDocument[document].reduce((total, unit) => total + unit.blocks.filter((block) => block.text).length, 0) });
|
|
130
164
|
}
|
|
131
|
-
const reviewedStatuses = new Set(["source-checked", "double-reviewed", "published", "superseded"]);
|
|
132
165
|
const corpusFingerprintSha256 = sha256(JSON.stringify({ corpusManifest, unitsByDocument, assetManifests }));
|
|
133
|
-
const artifactFingerprintSha256 = sha256(JSON.stringify({ chunkInventory, indexes: documentIndexes, relations: relationsWritten.sha256, diagnostics: diagnosticsWritten.sha256, search: searchWritten.sha256 }));
|
|
134
|
-
const manifest = { formatVersion: 2, generatedAt: corpusManifest.asOf, structuralCodesVersion: packageManifest.version, schemaVersion: allUnits[0]?.schemaVersion ?? null, assetSchemaVersion: assetManifests[0]?.schemaVersion ?? null, status: corpusManifest.status, disclaimer: corpusManifest.disclaimer, corpusFingerprintSha256, generatedArtifactFingerprintSha256: artifactFingerprintSha256, stats: { units: allUnits.length, blocks: allUnits.reduce((total, unit) => total + unit.blocks.filter((block) => block.text).length, 0), explicitRelations: relations.length, proposedRelations: relations.filter((relation) => relation.review.status === "proposed").length, suggestedRelationDiagnostics: diagnostics.length,
|
|
166
|
+
const artifactFingerprintSha256 = sha256(JSON.stringify({ chunkInventory, indexes: documentIndexes, relations: relationsWritten.sha256, diagnostics: diagnosticsWritten.sha256, search: searchWritten.sha256, crossReferences: crossReferenceWritten.sha256 }));
|
|
167
|
+
const manifest = { formatVersion: 2, generatedAt: corpusManifest.asOf, structuralCodesVersion: packageManifest.version, schemaVersion: allUnits[0]?.schemaVersion ?? null, assetSchemaVersion: assetManifests[0]?.schemaVersion ?? null, status: corpusManifest.status, disclaimer: corpusManifest.disclaimer, corpusFingerprintSha256, generatedArtifactFingerprintSha256: artifactFingerprintSha256, stats: { units: allUnits.length, blocks: allUnits.reduce((total, unit) => total + unit.blocks.filter((block) => block.text).length, 0), explicitRelations: relations.length, proposedRelations: relations.filter((relation) => relation.review.status === "proposed").length, suggestedRelationDiagnostics: diagnostics.length, assetUnits: allUnits.filter((unit) => unit.assets.formulaIds.length > 0 || unit.assets.tableIds.length > 0 || unit.assets.figureIds.length > 0).length, formulas: assetCollections.formulas.length, tables: assetCollections.tables.length, figures: assetCollections.figures.length, chunks: chunkInventory.length }, documents: documentIndexes, relationsPath: "/data/codes/relations.json", relationDiagnosticsPath: "/data/codes/relation-diagnostics.json", searchIndexPath: "/data/codes/search-index.json", crossReferenceIndexPath: "/data/codes/cross-reference-index.json", chunks: chunkInventory };
|
|
135
168
|
const manifestWritten = await writeJson(join(outputDirectory, "manifest.json"), manifest);
|
|
136
169
|
let copiedFigureBytes = 0;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
const tableCellImages = assetCollections.tables.flatMap((table) => [...table.headers, ...table.rows].flat().flatMap((cell) => cell.image ? [cell.image] : []));
|
|
171
|
+
const imagesByPath = new Map([...assetCollections.figures, ...tableCellImages].map((entry) => [entry.imagePath, entry]));
|
|
172
|
+
for (const image of imagesByPath.values()) {
|
|
173
|
+
const source = join(sourceRoot, "corpus", "assets", image.imagePath);
|
|
174
|
+
const destination = join(figureOutput, image.imagePath);
|
|
140
175
|
await mkdir(dirname(destination), { recursive: true });
|
|
141
176
|
await copyFile(source, destination);
|
|
142
177
|
copiedFigureBytes += (await stat(source)).size;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function buildGlobalScrubberEntries(entries: any, maximumLevel?: number): any;
|
|
2
|
+
export function globalScrubberEntryAtRatio(entries: any, ratio: any): any;
|
|
3
|
+
export function globalScrubberRatioForId(entries: any, id: any, fallbackRatio?: number): any;
|
|
4
|
+
export function resolveGlobalScrubberActiveId(entries: any, activeId: any, activeBaseNumber: any): any;
|
|
5
|
+
export function globalScrubberKeyboardIndex(currentIndex: any, key: any, entryCount: any): number;
|
|
6
|
+
export function createGlobalScrubberDragSession(entries: any, onCommit: any): {
|
|
7
|
+
preview(ratio: any): any;
|
|
8
|
+
commit(): any;
|
|
9
|
+
cancel(): void;
|
|
10
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
function clampRatio(value) {
|
|
2
|
+
if (!Number.isFinite(value))
|
|
3
|
+
return 0;
|
|
4
|
+
return Math.max(0, Math.min(1, value));
|
|
5
|
+
}
|
|
6
|
+
export function buildGlobalScrubberEntries(entries, maximumLevel = Number.POSITIVE_INFINITY) {
|
|
7
|
+
const visibleEntries = Number.isFinite(maximumLevel) ? entries.filter((entry) => entry.level <= maximumLevel) : entries;
|
|
8
|
+
const lastIndex = Math.max(0, visibleEntries.length - 1);
|
|
9
|
+
return visibleEntries.map((entry, index) => (Object.assign(Object.assign({}, entry), { index, ratio: lastIndex === 0 ? 0 : index / lastIndex })));
|
|
10
|
+
}
|
|
11
|
+
export function globalScrubberEntryAtRatio(entries, ratio) {
|
|
12
|
+
var _a;
|
|
13
|
+
if (entries.length === 0)
|
|
14
|
+
return null;
|
|
15
|
+
const index = Math.round(clampRatio(ratio) * (entries.length - 1));
|
|
16
|
+
return (_a = entries[index]) !== null && _a !== void 0 ? _a : null;
|
|
17
|
+
}
|
|
18
|
+
export function globalScrubberRatioForId(entries, id, fallbackRatio = 0) {
|
|
19
|
+
var _a;
|
|
20
|
+
if (entries.length < 2)
|
|
21
|
+
return 0;
|
|
22
|
+
const entry = entries.find((candidate) => candidate.id === id);
|
|
23
|
+
return (_a = entry === null || entry === void 0 ? void 0 : entry.ratio) !== null && _a !== void 0 ? _a : clampRatio(fallbackRatio);
|
|
24
|
+
}
|
|
25
|
+
export function resolveGlobalScrubberActiveId(entries, activeId, activeBaseNumber) {
|
|
26
|
+
var _a;
|
|
27
|
+
if (activeId && entries.some((entry) => entry.id === activeId))
|
|
28
|
+
return activeId;
|
|
29
|
+
if (!activeBaseNumber)
|
|
30
|
+
return null;
|
|
31
|
+
const exactEntry = entries.find((entry) => entry.baseNumber === activeBaseNumber);
|
|
32
|
+
if (exactEntry)
|
|
33
|
+
return exactEntry.id;
|
|
34
|
+
let closestAncestor = null;
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
if (!activeBaseNumber.startsWith(`${entry.baseNumber}.`))
|
|
37
|
+
continue;
|
|
38
|
+
if (!closestAncestor || entry.baseNumber.length > closestAncestor.baseNumber.length)
|
|
39
|
+
closestAncestor = entry;
|
|
40
|
+
}
|
|
41
|
+
return (_a = closestAncestor === null || closestAncestor === void 0 ? void 0 : closestAncestor.id) !== null && _a !== void 0 ? _a : null;
|
|
42
|
+
}
|
|
43
|
+
export function globalScrubberKeyboardIndex(currentIndex, key, entryCount) {
|
|
44
|
+
if (entryCount <= 0)
|
|
45
|
+
return -1;
|
|
46
|
+
const lastIndex = entryCount - 1;
|
|
47
|
+
const safeIndex = Math.max(0, Math.min(lastIndex, currentIndex));
|
|
48
|
+
const pageStep = Math.max(1, Math.round(entryCount * 0.1));
|
|
49
|
+
if (key === "Home")
|
|
50
|
+
return 0;
|
|
51
|
+
if (key === "End")
|
|
52
|
+
return lastIndex;
|
|
53
|
+
if (key === "ArrowUp")
|
|
54
|
+
return Math.max(0, safeIndex - 1);
|
|
55
|
+
if (key === "ArrowDown")
|
|
56
|
+
return Math.min(lastIndex, safeIndex + 1);
|
|
57
|
+
if (key === "PageUp")
|
|
58
|
+
return Math.max(0, safeIndex - pageStep);
|
|
59
|
+
if (key === "PageDown")
|
|
60
|
+
return Math.min(lastIndex, safeIndex + pageStep);
|
|
61
|
+
return safeIndex;
|
|
62
|
+
}
|
|
63
|
+
export function createGlobalScrubberDragSession(entries, onCommit) {
|
|
64
|
+
let current = null;
|
|
65
|
+
let finished = false;
|
|
66
|
+
return {
|
|
67
|
+
preview(ratio) {
|
|
68
|
+
if (!finished)
|
|
69
|
+
current = globalScrubberEntryAtRatio(entries, ratio);
|
|
70
|
+
return current;
|
|
71
|
+
},
|
|
72
|
+
commit() {
|
|
73
|
+
if (finished)
|
|
74
|
+
return null;
|
|
75
|
+
finished = true;
|
|
76
|
+
if (current)
|
|
77
|
+
onCommit(current);
|
|
78
|
+
return current;
|
|
79
|
+
},
|
|
80
|
+
cancel() {
|
|
81
|
+
finished = true;
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=globalScrubber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globalScrubber.js","sourceRoot":"","sources":["../shared/globalScrubber.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ViewerMode } from "./corpusData";
|
|
2
|
+
export type ViewerTarget = {
|
|
3
|
+
kind: "unit";
|
|
4
|
+
unitId: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: "block";
|
|
7
|
+
unitId: string;
|
|
8
|
+
blockId: string;
|
|
9
|
+
} | {
|
|
10
|
+
kind: "asset";
|
|
11
|
+
unitId: string;
|
|
12
|
+
assetId: string;
|
|
13
|
+
assetKind?: "formula" | "table" | "figure";
|
|
14
|
+
};
|
|
15
|
+
export declare function targetFromUrl(url: URL): ViewerTarget | null;
|
|
16
|
+
export declare function urlForViewerTarget(currentUrl: string | URL, mode: ViewerMode, defaultMode: ViewerMode, target: ViewerTarget): URL;
|
|
17
|
+
export declare function citationForTarget({ documentLabel, unitNumber, targetLabel, permalink }: {
|
|
18
|
+
documentLabel: string;
|
|
19
|
+
unitNumber: string;
|
|
20
|
+
targetLabel?: string | null;
|
|
21
|
+
permalink: string;
|
|
22
|
+
}): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export function targetFromUrl(url) {
|
|
2
|
+
const unitId = url.searchParams.get("unit");
|
|
3
|
+
if (!unitId)
|
|
4
|
+
return null;
|
|
5
|
+
const assetId = url.searchParams.get("asset");
|
|
6
|
+
if (assetId) {
|
|
7
|
+
const kind = url.searchParams.get("assetKind");
|
|
8
|
+
const assetKind = kind === "formula" || kind === "table" || kind === "figure" ? kind : undefined;
|
|
9
|
+
return { kind: "asset", unitId, assetId, assetKind };
|
|
10
|
+
}
|
|
11
|
+
const blockId = url.searchParams.get("block");
|
|
12
|
+
return blockId ? { kind: "block", unitId, blockId } : { kind: "unit", unitId };
|
|
13
|
+
}
|
|
14
|
+
export function urlForViewerTarget(currentUrl, mode, defaultMode, target) {
|
|
15
|
+
const url = new URL(currentUrl);
|
|
16
|
+
if (mode === defaultMode)
|
|
17
|
+
url.searchParams.delete("mode");
|
|
18
|
+
else
|
|
19
|
+
url.searchParams.set("mode", mode);
|
|
20
|
+
url.searchParams.set("unit", target.unitId);
|
|
21
|
+
url.searchParams.delete("block");
|
|
22
|
+
url.searchParams.delete("asset");
|
|
23
|
+
url.searchParams.delete("assetKind");
|
|
24
|
+
if (target.kind === "block")
|
|
25
|
+
url.searchParams.set("block", target.blockId);
|
|
26
|
+
if (target.kind === "asset") {
|
|
27
|
+
url.searchParams.set("asset", target.assetId);
|
|
28
|
+
if (target.assetKind)
|
|
29
|
+
url.searchParams.set("assetKind", target.assetKind);
|
|
30
|
+
}
|
|
31
|
+
return url;
|
|
32
|
+
}
|
|
33
|
+
export function citationForTarget({ documentLabel, unitNumber, targetLabel, permalink }) {
|
|
34
|
+
return `${documentLabel}, § ${unitNumber}${targetLabel ? `, ${targetLabel}` : ""} — ${permalink}`;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=permalinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permalinks.js","sourceRoot":"","sources":["../shared/permalinks.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,aAAa,CAAC,GAAQ;IACpC,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACjG,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IACvD,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,UAAwB,EAAE,IAAgB,EAAE,WAAuB,EAAE,MAAoB;IAC1H,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAChC,IAAI,IAAI,KAAK,WAAW;QAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;;QACrD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACxC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,MAAM,CAAC,SAAS;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAiG;IACpL,OAAO,GAAG,aAAa,OAAO,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,SAAS,EAAE,CAAC;AACpG,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type CorpusManifest, type DocumentLookup, type SearchResult, type ViewerMode } from "./corpusData";
|
|
2
|
+
type SearchStatus = "idle" | "loading" | "ready" | "error";
|
|
3
|
+
export declare function resolveExactSearch(query: string, mode: ViewerMode, lookup: DocumentLookup | null, circLookup: DocumentLookup | null): SearchResult[] | null;
|
|
4
|
+
export declare function useViewerSearch({ query, mode, manifest, dataBaseUrl, lookup, circLookup, maxResults, debounceMs }: {
|
|
5
|
+
query: string;
|
|
6
|
+
mode: ViewerMode;
|
|
7
|
+
manifest: CorpusManifest | null;
|
|
8
|
+
dataBaseUrl: string;
|
|
9
|
+
lookup: DocumentLookup | null;
|
|
10
|
+
circLookup: DocumentLookup | null;
|
|
11
|
+
maxResults: number;
|
|
12
|
+
debounceMs?: number;
|
|
13
|
+
}): {
|
|
14
|
+
queryReady: boolean;
|
|
15
|
+
results: SearchResult[];
|
|
16
|
+
status: SearchStatus;
|
|
17
|
+
source: "exact" | "worker";
|
|
18
|
+
durationMs: number | null;
|
|
19
|
+
errorMessage: string | undefined;
|
|
20
|
+
indexRequested: boolean;
|
|
21
|
+
};
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { parseNormativeReference, resolveDataPath, } from "./corpusData";
|
|
3
|
+
function resultForSummary(summary) {
|
|
4
|
+
const prefix = summary.numbering.official;
|
|
5
|
+
return {
|
|
6
|
+
id: summary.id,
|
|
7
|
+
document: summary.document,
|
|
8
|
+
numbering: prefix,
|
|
9
|
+
title: summary.title,
|
|
10
|
+
chunkPath: summary.chunkPath,
|
|
11
|
+
snippet: `${prefix} — ${summary.title}`,
|
|
12
|
+
highlights: [[0, prefix.length]],
|
|
13
|
+
score: 9000000,
|
|
14
|
+
matchKind: "number-exact",
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function resolveExactSearch(query, mode, lookup, circLookup) {
|
|
18
|
+
var _a;
|
|
19
|
+
const reference = parseNormativeReference(query);
|
|
20
|
+
if (!reference)
|
|
21
|
+
return null;
|
|
22
|
+
let summary;
|
|
23
|
+
if (reference.documentHint === "circ2019") {
|
|
24
|
+
if (mode !== "ntc")
|
|
25
|
+
summary = circLookup === null || circLookup === void 0 ? void 0 : circLookup.unitByNumbering.get(reference.numbering);
|
|
26
|
+
}
|
|
27
|
+
else if (mode === "circ")
|
|
28
|
+
summary = circLookup === null || circLookup === void 0 ? void 0 : circLookup.unitByNumbering.get(reference.numbering);
|
|
29
|
+
else
|
|
30
|
+
summary = (_a = lookup === null || lookup === void 0 ? void 0 : lookup.unitByNumbering.get(reference.numbering)) !== null && _a !== void 0 ? _a : (mode === "combined" ? circLookup === null || circLookup === void 0 ? void 0 : circLookup.unitByNumbering.get(reference.numbering) : undefined);
|
|
31
|
+
return summary ? [resultForSummary(summary)] : [];
|
|
32
|
+
}
|
|
33
|
+
function useDebouncedValue(value, delayMs) {
|
|
34
|
+
const [debounced, setDebounced] = useState(value);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const timer = window.setTimeout(() => setDebounced(value), delayMs);
|
|
37
|
+
return () => window.clearTimeout(timer);
|
|
38
|
+
}, [delayMs, value]);
|
|
39
|
+
return debounced;
|
|
40
|
+
}
|
|
41
|
+
export function useViewerSearch({ query, mode, manifest, dataBaseUrl, lookup, circLookup, maxResults, debounceMs = 80 }) {
|
|
42
|
+
const maximum = Math.max(1, Math.min(50, maxResults));
|
|
43
|
+
const debouncedQuery = useDebouncedValue(query, debounceMs);
|
|
44
|
+
const exactResults = useMemo(() => resolveExactSearch(query, mode, lookup, circLookup), [circLookup, lookup, mode, query]);
|
|
45
|
+
const [workerResponse, setWorkerResponse] = useState(null);
|
|
46
|
+
const [indexRequested, setIndexRequested] = useState(false);
|
|
47
|
+
const workerRef = useRef(null);
|
|
48
|
+
const requestIdRef = useRef(0);
|
|
49
|
+
useEffect(() => () => { var _a; return (_a = workerRef.current) === null || _a === void 0 ? void 0 : _a.terminate(); }, []);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!manifest || exactResults !== null || debouncedQuery.trim().length < 2) {
|
|
52
|
+
requestIdRef.current += 1;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const scheduleFailure = (errorMessage) => {
|
|
56
|
+
const timer = window.setTimeout(() => {
|
|
57
|
+
setWorkerResponse({ query: debouncedQuery, mode, status: "error", results: [], durationMs: null, errorMessage });
|
|
58
|
+
}, 0);
|
|
59
|
+
return () => window.clearTimeout(timer);
|
|
60
|
+
};
|
|
61
|
+
let worker = workerRef.current;
|
|
62
|
+
if (!worker) {
|
|
63
|
+
if (typeof Worker === "undefined") {
|
|
64
|
+
return scheduleFailure("Web Worker non disponibile in questo browser.");
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
worker = new Worker(new URL("./searchWorker.js", import.meta.url), { type: "module", name: "structural-codes-search" });
|
|
68
|
+
}
|
|
69
|
+
catch (_a) {
|
|
70
|
+
return scheduleFailure("Avvio del Web Worker non riuscito.");
|
|
71
|
+
}
|
|
72
|
+
workerRef.current = worker;
|
|
73
|
+
}
|
|
74
|
+
const requestId = ++requestIdRef.current;
|
|
75
|
+
const activeWorker = worker;
|
|
76
|
+
const onMessage = ({ data }) => {
|
|
77
|
+
if (data.requestId !== requestIdRef.current || data.requestId !== requestId)
|
|
78
|
+
return;
|
|
79
|
+
setIndexRequested(true);
|
|
80
|
+
if (data.type === "error") {
|
|
81
|
+
setWorkerResponse({ query: debouncedQuery, mode, status: "error", results: [], durationMs: null, errorMessage: data.message });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
setWorkerResponse({ query: data.query, mode: data.mode, status: "ready", results: data.results, durationMs: data.durationMs });
|
|
85
|
+
};
|
|
86
|
+
const onError = () => {
|
|
87
|
+
if (requestId !== requestIdRef.current)
|
|
88
|
+
return;
|
|
89
|
+
activeWorker.terminate();
|
|
90
|
+
if (workerRef.current === activeWorker)
|
|
91
|
+
workerRef.current = null;
|
|
92
|
+
setIndexRequested(true);
|
|
93
|
+
setWorkerResponse({ query: debouncedQuery, mode, status: "error", results: [], durationMs: null, errorMessage: "Avvio del Web Worker non riuscito." });
|
|
94
|
+
};
|
|
95
|
+
activeWorker.addEventListener("message", onMessage);
|
|
96
|
+
activeWorker.addEventListener("error", onError);
|
|
97
|
+
let postFailureCleanup = null;
|
|
98
|
+
try {
|
|
99
|
+
activeWorker.postMessage({
|
|
100
|
+
type: "search",
|
|
101
|
+
requestId,
|
|
102
|
+
indexUrl: new URL(resolveDataPath(manifest.searchIndexPath, dataBaseUrl), window.location.href).href,
|
|
103
|
+
query: debouncedQuery,
|
|
104
|
+
mode,
|
|
105
|
+
limit: maximum,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch (_b) {
|
|
109
|
+
activeWorker.terminate();
|
|
110
|
+
if (workerRef.current === activeWorker)
|
|
111
|
+
workerRef.current = null;
|
|
112
|
+
postFailureCleanup = scheduleFailure("Invio della ricerca al Web Worker non riuscito.");
|
|
113
|
+
}
|
|
114
|
+
return () => {
|
|
115
|
+
postFailureCleanup === null || postFailureCleanup === void 0 ? void 0 : postFailureCleanup();
|
|
116
|
+
activeWorker.removeEventListener("message", onMessage);
|
|
117
|
+
activeWorker.removeEventListener("error", onError);
|
|
118
|
+
};
|
|
119
|
+
}, [dataBaseUrl, debouncedQuery, exactResults, manifest, maximum, mode]);
|
|
120
|
+
const normalizedInputLength = query.trim().length;
|
|
121
|
+
const querySettled = debouncedQuery === query;
|
|
122
|
+
const fullTextCurrent = querySettled && (workerResponse === null || workerResponse === void 0 ? void 0 : workerResponse.query) === debouncedQuery && workerResponse.mode === mode;
|
|
123
|
+
return {
|
|
124
|
+
queryReady: normalizedInputLength >= 2,
|
|
125
|
+
results: exactResults !== null && exactResults !== void 0 ? exactResults : (fullTextCurrent ? workerResponse.results : []),
|
|
126
|
+
status: exactResults !== null ? "ready" : normalizedInputLength < 2 ? "idle" : fullTextCurrent ? workerResponse.status : "loading",
|
|
127
|
+
source: exactResults !== null ? "exact" : "worker",
|
|
128
|
+
durationMs: exactResults !== null ? 0 : fullTextCurrent ? workerResponse.durationMs : null,
|
|
129
|
+
errorMessage: exactResults === null && fullTextCurrent ? workerResponse.errorMessage : undefined,
|
|
130
|
+
indexRequested,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=searchClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searchClient.js","sourceRoot":"","sources":["../shared/searchClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export function normalizeSearchText(value: any): string;
|
|
2
|
+
export function tokenizeSearchText(value: any): [] | RegExpMatchArray;
|
|
3
|
+
export function parseNormativeReference(value: any): {
|
|
4
|
+
numbering: string;
|
|
5
|
+
documentHint: string | null;
|
|
6
|
+
} | null;
|
|
7
|
+
export function buildSearchIndexPayload(sourceUnits: any): {
|
|
8
|
+
formatVersion: number;
|
|
9
|
+
normalization: string;
|
|
10
|
+
units: any;
|
|
11
|
+
references: any;
|
|
12
|
+
assetReferences: any;
|
|
13
|
+
postings: any;
|
|
14
|
+
};
|
|
15
|
+
export function highlightedSnippet(value: any, normalizedQuery: any, queryTokens: any): {
|
|
16
|
+
snippet: string;
|
|
17
|
+
highlights: any[][];
|
|
18
|
+
};
|
|
19
|
+
export function createSearchEngine(index: any): {
|
|
20
|
+
search({ query, mode, limit }: {
|
|
21
|
+
query: any;
|
|
22
|
+
mode?: string | undefined;
|
|
23
|
+
limit?: number | undefined;
|
|
24
|
+
}): {
|
|
25
|
+
assetKind?: any;
|
|
26
|
+
assetId?: any;
|
|
27
|
+
blockId?: any;
|
|
28
|
+
score: number;
|
|
29
|
+
matchKind: any;
|
|
30
|
+
snippet: string;
|
|
31
|
+
highlights: any[][];
|
|
32
|
+
id: any;
|
|
33
|
+
document: any;
|
|
34
|
+
numbering: any;
|
|
35
|
+
title: any;
|
|
36
|
+
chunkPath: any;
|
|
37
|
+
}[];
|
|
38
|
+
};
|
|
39
|
+
export const searchIndexFormatVersion: 4;
|
|
40
|
+
export const searchRankingWeights: Readonly<{
|
|
41
|
+
priority: Readonly<{
|
|
42
|
+
numberExact: 9000000;
|
|
43
|
+
assetExact: 8000000;
|
|
44
|
+
titleExact: 7000000;
|
|
45
|
+
numberKeyword: 6000000;
|
|
46
|
+
titleTerms: 5000000;
|
|
47
|
+
phrase: 4000000;
|
|
48
|
+
proximity: 3000000;
|
|
49
|
+
allTerms: 2000000;
|
|
50
|
+
partial: 1000000;
|
|
51
|
+
}>;
|
|
52
|
+
field: Readonly<{
|
|
53
|
+
matchedTerm: 20000;
|
|
54
|
+
titleFrequency: 2000;
|
|
55
|
+
bodyRelevance: 420;
|
|
56
|
+
assetRelevance: 260;
|
|
57
|
+
exactNumberPrefix: 90000;
|
|
58
|
+
}>;
|
|
59
|
+
proximity: Readonly<{
|
|
60
|
+
sameBlock: 80000;
|
|
61
|
+
ordered: 35000;
|
|
62
|
+
window: 24;
|
|
63
|
+
perTokenSaved: 1500;
|
|
64
|
+
}>;
|
|
65
|
+
candidatePoolMinimum: 300;
|
|
66
|
+
candidatePoolPerResult: 28;
|
|
67
|
+
partialExpansionLimit: 8;
|
|
68
|
+
}>;
|