structural-codes-viewer 0.1.0-alpha.1 → 0.1.0-alpha.3

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.
Files changed (63) hide show
  1. package/LICENSE +501 -0
  2. package/NOTICE +16 -0
  3. package/README.md +57 -68
  4. package/package-dist/CorpusContent.d.ts +44 -9
  5. package/package-dist/CorpusContent.js +452 -26
  6. package/package-dist/CorpusContent.js.map +1 -1
  7. package/package-dist/NormativeViewer.d.ts +23 -2
  8. package/package-dist/NormativeViewer.js +1699 -234
  9. package/package-dist/NormativeViewer.js.map +1 -1
  10. package/package-dist/ReferenceTools.d.ts +49 -0
  11. package/package-dist/ReferenceTools.js +14 -0
  12. package/package-dist/ReferenceTools.js.map +1 -0
  13. package/package-dist/annotations/AnnotationUi.d.ts +57 -0
  14. package/package-dist/annotations/AnnotationUi.js +114 -0
  15. package/package-dist/annotations/AnnotationUi.js.map +1 -0
  16. package/package-dist/annotations/annotationTargets.d.ts +39 -0
  17. package/package-dist/annotations/annotationTargets.js +94 -0
  18. package/package-dist/annotations/annotationTargets.js.map +1 -0
  19. package/package-dist/annotations/exportImport.d.ts +6 -0
  20. package/package-dist/annotations/exportImport.js +30 -0
  21. package/package-dist/annotations/exportImport.js.map +1 -0
  22. package/package-dist/annotations/index.d.ts +4 -0
  23. package/package-dist/annotations/index.js +5 -0
  24. package/package-dist/annotations/index.js.map +1 -0
  25. package/package-dist/annotations/indexedDb.d.ts +21 -0
  26. package/package-dist/annotations/indexedDb.js +210 -0
  27. package/package-dist/annotations/indexedDb.js.map +1 -0
  28. package/package-dist/annotations/schema.d.ts +8 -0
  29. package/package-dist/annotations/schema.js +102 -0
  30. package/package-dist/annotations/schema.js.map +1 -0
  31. package/package-dist/annotations/types.d.ts +52 -0
  32. package/package-dist/annotations/types.js +18 -0
  33. package/package-dist/annotations/types.js.map +1 -0
  34. package/package-dist/chunkNavigation.d.ts +12 -0
  35. package/package-dist/chunkNavigation.js +44 -0
  36. package/package-dist/chunkNavigation.js.map +1 -0
  37. package/package-dist/corpusData.d.ts +176 -33
  38. package/package-dist/corpusData.js +52 -0
  39. package/package-dist/corpusData.js.map +1 -1
  40. package/package-dist/crossReferences.d.ts +46 -0
  41. package/package-dist/crossReferences.js +198 -0
  42. package/package-dist/crossReferences.js.map +1 -0
  43. package/package-dist/generate-artifacts.mjs +47 -12
  44. package/package-dist/globalScrubber.d.ts +10 -0
  45. package/package-dist/globalScrubber.js +85 -0
  46. package/package-dist/globalScrubber.js.map +1 -0
  47. package/package-dist/permalinks.d.ts +22 -0
  48. package/package-dist/permalinks.js +36 -0
  49. package/package-dist/permalinks.js.map +1 -0
  50. package/package-dist/searchClient.d.ts +22 -0
  51. package/package-dist/searchClient.js +133 -0
  52. package/package-dist/searchClient.js.map +1 -0
  53. package/package-dist/searchEngine.d.ts +68 -0
  54. package/package-dist/searchEngine.js +558 -0
  55. package/package-dist/searchEngine.js.map +1 -0
  56. package/package-dist/searchWorker.d.ts +1 -0
  57. package/package-dist/searchWorker.js +32 -0
  58. package/package-dist/searchWorker.js.map +1 -0
  59. package/package-dist/styles.css +762 -182
  60. package/package-dist/tableCaptions.d.mts +3 -0
  61. package/package-dist/tableCaptions.mjs +35 -0
  62. package/package-dist/tableCaptions.mjs.map +1 -0
  63. package/package.json +18 -14
@@ -0,0 +1,52 @@
1
+ import type { DocumentId } from "../corpusData.js";
2
+ import type { ViewerTarget } from "../permalinks.js";
3
+ export declare const ANNOTATION_SCHEMA_VERSION: 1;
4
+ export type AnnotationType = "bookmark" | "note";
5
+ export interface UserAnnotation {
6
+ id: string;
7
+ schemaVersion: typeof ANNOTATION_SCHEMA_VERSION;
8
+ type: AnnotationType;
9
+ target: ViewerTarget;
10
+ documentId: DocumentId;
11
+ numbering: string;
12
+ title: string;
13
+ label?: string;
14
+ text?: string;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ }
18
+ export interface CreateAnnotationInput {
19
+ type: AnnotationType;
20
+ target: ViewerTarget;
21
+ documentId: DocumentId;
22
+ numbering: string;
23
+ title: string;
24
+ label?: string;
25
+ text?: string;
26
+ }
27
+ export interface UpdateAnnotationPatch {
28
+ label?: string;
29
+ text?: string;
30
+ }
31
+ export interface AnnotationExport {
32
+ schemaVersion: typeof ANNOTATION_SCHEMA_VERSION;
33
+ exportedAt: string;
34
+ annotations: UserAnnotation[];
35
+ }
36
+ export interface AnnotationImportResult {
37
+ imported: number;
38
+ ignored: number;
39
+ }
40
+ export interface AnnotationStore {
41
+ listAnnotations(): Promise<UserAnnotation[]>;
42
+ createAnnotation(input: CreateAnnotationInput): Promise<UserAnnotation>;
43
+ updateAnnotation(id: string, patch: UpdateAnnotationPatch): Promise<UserAnnotation>;
44
+ deleteAnnotation(id: string): Promise<void>;
45
+ importAnnotations(value: unknown): Promise<AnnotationImportResult>;
46
+ exportAnnotations(): Promise<AnnotationExport>;
47
+ }
48
+ export type AnnotationErrorCode = "UNAVAILABLE" | "BLOCKED" | "UPGRADE_FAILED" | "CORRUPT" | "WRITE_FAILED" | "CONFLICT" | "INVALID_DATA";
49
+ export declare class AnnotationStoreError extends Error {
50
+ readonly code: AnnotationErrorCode;
51
+ constructor(code: AnnotationErrorCode);
52
+ }
@@ -0,0 +1,18 @@
1
+ export const ANNOTATION_SCHEMA_VERSION = 1;
2
+ export class AnnotationStoreError extends Error {
3
+ constructor(code) {
4
+ const messages = {
5
+ UNAVAILABLE: "Le annotazioni locali non sono disponibili in questo browser.",
6
+ BLOCKED: "Chiudi le altre schede del viewer e riprova per aggiornare le annotazioni.",
7
+ UPGRADE_FAILED: "Aggiornamento dell’archivio annotazioni non riuscito. I dati esistenti non sono stati cancellati.",
8
+ CORRUPT: "L’archivio annotazioni contiene dati non leggibili. I dati sono stati conservati.",
9
+ WRITE_FAILED: "Salvataggio locale non riuscito. Mantieni aperta questa pagina e riprova.",
10
+ CONFLICT: "L’annotazione non esiste più o collide con un segnalibro esistente.",
11
+ INVALID_DATA: "I dati dell’annotazione non rispettano il formato supportato.",
12
+ };
13
+ super(messages[code]);
14
+ this.code = code;
15
+ this.name = "AnnotationStoreError";
16
+ }
17
+ }
18
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../shared/annotations/types.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAU,CAAC;AAsDpD,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAqB,IAAyB;QAC5C,MAAM,QAAQ,GAAwC;YACpD,WAAW,EAAE,+DAA+D;YAC5E,OAAO,EAAE,4EAA4E;YACrF,cAAc,EAAE,mGAAmG;YACnH,OAAO,EAAE,mFAAmF;YAC5F,YAAY,EAAE,2EAA2E;YACzF,QAAQ,EAAE,qEAAqE;YAC/E,YAAY,EAAE,+DAA+D;SAC9E,CAAC;QACF,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAVH,SAAI,GAAJ,IAAI,CAAqB;QAW5C,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ export function navigationChunkWindow(lookup: any, targetPath: any): {
2
+ previous: any;
3
+ target: any;
4
+ next: any;
5
+ };
6
+ export function navigationChunkPaths(lookup: any, targetPath: any): any[];
7
+ export function isChunkNearRenderedWindow(lookup: any, targetPath: any, renderedPaths: any): boolean;
8
+ export function primarySummaryForVisibleUnit(lookup: any, unitId: any, primaryAnchorByFallbackId: any): any;
9
+ export function progressiveChunkTargetsForVisibleUnit(lookup: any, unitId: any, primaryAnchorByFallbackId: any): {
10
+ previous: any;
11
+ next: any;
12
+ };
@@ -0,0 +1,44 @@
1
+ export function navigationChunkWindow(lookup, targetPath) {
2
+ var _a, _b;
3
+ const position = lookup === null || lookup === void 0 ? void 0 : lookup.chunkIndexByPath.get(targetPath);
4
+ if (position === undefined)
5
+ return { previous: null, target: targetPath, next: null };
6
+ return {
7
+ previous: (_a = lookup.chunkPaths[position - 1]) !== null && _a !== void 0 ? _a : null,
8
+ target: targetPath,
9
+ next: (_b = lookup.chunkPaths[position + 1]) !== null && _b !== void 0 ? _b : null,
10
+ };
11
+ }
12
+ export function navigationChunkPaths(lookup, targetPath) {
13
+ const window = navigationChunkWindow(lookup, targetPath);
14
+ return [window.previous, window.target, window.next].filter(Boolean);
15
+ }
16
+ export function isChunkNearRenderedWindow(lookup, targetPath, renderedPaths) {
17
+ const position = lookup === null || lookup === void 0 ? void 0 : lookup.chunkIndexByPath.get(targetPath);
18
+ if (position === undefined)
19
+ return false;
20
+ return [position - 1, position, position + 1].some((candidate) => {
21
+ const path = lookup.chunkPaths[candidate];
22
+ return Boolean(path && renderedPaths.has(path));
23
+ });
24
+ }
25
+ export function primarySummaryForVisibleUnit(lookup, unitId, primaryAnchorByFallbackId) {
26
+ var _a, _b;
27
+ return (_b = (_a = lookup === null || lookup === void 0 ? void 0 : lookup.unitById.get(unitId)) !== null && _a !== void 0 ? _a : primaryAnchorByFallbackId === null || primaryAnchorByFallbackId === void 0 ? void 0 : primaryAnchorByFallbackId.get(unitId)) !== null && _b !== void 0 ? _b : null;
28
+ }
29
+ export function progressiveChunkTargetsForVisibleUnit(lookup, unitId, primaryAnchorByFallbackId) {
30
+ var _a;
31
+ const summary = primarySummaryForVisibleUnit(lookup, unitId, primaryAnchorByFallbackId);
32
+ if (!lookup || !summary)
33
+ return { previous: null, next: null };
34
+ const chunkUnits = (_a = lookup.unitsByChunkPath.get(summary.chunkPath)) !== null && _a !== void 0 ? _a : [];
35
+ const position = chunkUnits.findIndex((unit) => unit.id === summary.id);
36
+ if (position < 0)
37
+ return { previous: null, next: null };
38
+ const adjacent = navigationChunkWindow(lookup, summary.chunkPath);
39
+ return {
40
+ previous: position <= 1 ? adjacent.previous : null,
41
+ next: position >= chunkUnits.length - 2 ? adjacent.next : null,
42
+ };
43
+ }
44
+ //# sourceMappingURL=chunkNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunkNavigation.js","sourceRoot":"","sources":["../shared/chunkNavigation.js"],"names":[],"mappings":"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"}
@@ -1,15 +1,47 @@
1
1
  export type DocumentId = "ntc2018" | "circ2019";
2
2
  export type ViewerMode = "ntc" | "circ" | "combined";
3
+ export type InlineSegment = {
4
+ kind: "text";
5
+ value: string;
6
+ } | {
7
+ kind: "em";
8
+ value: string;
9
+ } | {
10
+ kind: "underline";
11
+ value: string;
12
+ } | {
13
+ kind: "em-underline";
14
+ value: string;
15
+ } | {
16
+ kind: "strong";
17
+ value: string;
18
+ } | {
19
+ kind: "strong-em";
20
+ value: string;
21
+ } | {
22
+ kind: "strong-underline";
23
+ value: string;
24
+ } | {
25
+ kind: "math";
26
+ value: string;
27
+ latex: string;
28
+ };
29
+ export interface TextParagraph {
30
+ normalized: string;
31
+ inline?: InlineSegment[];
32
+ listMarker?: "numbered" | "bullet" | "dash";
33
+ listLevel?: number;
34
+ }
3
35
  export interface Evidence {
4
36
  sourceId: string;
5
37
  pdfPage: number;
6
38
  printedPage: string | null;
7
- region: {
39
+ region?: {
8
40
  x: number;
9
41
  y: number;
10
42
  width: number;
11
43
  height: number;
12
- };
44
+ } | null;
13
45
  transformations?: Array<{
14
46
  operation: string;
15
47
  note: string;
@@ -21,72 +53,100 @@ export interface CorpusBlock {
21
53
  blockId: string;
22
54
  kind: string;
23
55
  origin: string;
56
+ listMarker?: "bullet" | "dash" | "none";
57
+ listLevel?: number;
58
+ indentLevel?: number;
24
59
  text?: {
25
60
  raw: string;
26
61
  normalized: string;
27
62
  normalizationVersion: string;
28
- inline?: Array<{
29
- kind: "text";
30
- value: string;
31
- } | {
32
- kind: "math";
33
- value: string;
34
- latex: string;
35
- }>;
63
+ inline?: InlineSegment[];
64
+ paragraphs?: TextParagraph[];
36
65
  };
37
66
  assetId?: string;
38
67
  evidence?: Evidence;
39
68
  }
40
69
  export interface FormulaAsset {
41
70
  id: string;
71
+ unitId?: string;
42
72
  officialNumber: string | null;
43
73
  pdfPage: number;
44
74
  latex: string;
45
75
  }
76
+ export interface TableCellImage {
77
+ imagePath: string;
78
+ alt: string;
79
+ sha256: string;
80
+ region: {
81
+ x: number;
82
+ y: number;
83
+ width: number;
84
+ height: number;
85
+ };
86
+ }
46
87
  export interface TableCell {
47
88
  text: string;
48
89
  latex?: string;
90
+ inline?: InlineSegment[];
91
+ image?: TableCellImage;
49
92
  colSpan?: number;
50
93
  rowSpan?: number;
94
+ strong?: boolean;
95
+ align?: "left" | "center" | "right";
96
+ noWrap?: boolean;
97
+ header?: boolean;
98
+ verticalText?: boolean;
99
+ shade?: "gray";
100
+ spacer?: boolean;
101
+ subrowIndent?: boolean;
102
+ subrowLabel?: boolean;
51
103
  }
52
104
  export interface TableAsset {
53
105
  id: string;
106
+ unitId?: string;
107
+ columnCount?: number;
108
+ columnWidths?: number[];
109
+ footerColumnCount?: number;
110
+ footerColumnWidths?: number[];
54
111
  officialNumber: string | null;
55
112
  pdfPage: number;
56
113
  caption: string | null;
114
+ hideLabel?: boolean;
115
+ captionInline?: InlineSegment[];
57
116
  headers: TableCell[][];
58
117
  rows: TableCell[][];
118
+ footerRows?: TableCell[][];
59
119
  notes: string[];
120
+ notesInline?: InlineSegment[][];
60
121
  }
61
122
  export interface FigureAsset {
62
123
  id: string;
124
+ unitId?: string;
125
+ sha256?: string;
63
126
  officialNumber: string;
64
127
  pdfPage: number;
65
- caption: string;
128
+ caption: string | null;
129
+ captionInline?: InlineSegment[];
66
130
  alt: string;
67
131
  imagePath: string;
68
132
  region?: {
69
133
  width: number;
70
134
  height: number;
71
135
  };
136
+ displayScale?: number;
72
137
  }
73
138
  export interface AssetBundle {
74
139
  formulas: Record<string, FormulaAsset>;
75
140
  tables: Record<string, TableAsset>;
76
141
  figures: Record<string, FigureAsset>;
77
142
  }
78
- export interface OpenIssue {
79
- issueId: string;
80
- type: string;
81
- severity: "blocking" | "warning" | "info";
82
- note: string;
83
- }
84
143
  export interface Relation {
85
144
  relationId: string;
86
145
  type: string;
87
146
  targetUnitId: string;
88
147
  basis: string;
89
148
  rationale: string;
149
+ evidenceBlockIds?: string[];
90
150
  review: {
91
151
  status: string;
92
152
  };
@@ -100,6 +160,7 @@ export interface CorpusUnit {
100
160
  sortKey: string;
101
161
  };
102
162
  title: string;
163
+ titleBlockId?: string;
103
164
  hierarchy: {
104
165
  parentId: string | null;
105
166
  ancestorIds: string[];
@@ -113,9 +174,8 @@ export interface CorpusUnit {
113
174
  };
114
175
  blocks: CorpusBlock[];
115
176
  relations: Relation[];
116
- workflow: {
117
- status: string;
118
- openIssues: OpenIssue[];
177
+ review: {
178
+ status: "draft" | "verified";
119
179
  };
120
180
  }
121
181
  export interface UnitSummary {
@@ -129,9 +189,7 @@ export interface UnitSummary {
129
189
  title: string;
130
190
  hierarchy: CorpusUnit["hierarchy"];
131
191
  validity: CorpusUnit["validity"];
132
- workflowStatus: string;
133
- openIssueCount: number;
134
- blockingIssueCount: number;
192
+ reviewStatus: "draft" | "verified";
135
193
  chunkPath: string;
136
194
  }
137
195
  export interface DocumentMetadata {
@@ -166,7 +224,6 @@ export interface CorpusManifest {
166
224
  explicitRelations: number;
167
225
  proposedRelations: number;
168
226
  suggestedRelationDiagnostics: number;
169
- reviewedUnits: number;
170
227
  assetUnits: number;
171
228
  formulas: number;
172
229
  tables: number;
@@ -177,6 +234,7 @@ export interface CorpusManifest {
177
234
  relationsPath: string;
178
235
  relationDiagnosticsPath: string;
179
236
  searchIndexPath: string;
237
+ crossReferenceIndexPath: string;
180
238
  chunks: Array<{
181
239
  path: string;
182
240
  document: DocumentId;
@@ -215,21 +273,106 @@ export interface RelationsIndex {
215
273
  inferredRelationsIncluded: false;
216
274
  relations: RelationEdge[];
217
275
  }
276
+ export type SearchMatchKind = "number-exact" | "asset-exact" | "title" | "number-keyword" | "phrase" | "proximity" | "text" | "partial";
277
+ export type SearchAssetKind = "formula" | "table" | "figure";
278
+ export interface SearchSegment {
279
+ blockId: string;
280
+ assetId?: string;
281
+ assetKind?: SearchAssetKind;
282
+ officialNumber?: string;
283
+ text: string;
284
+ }
285
+ export interface SearchUnit {
286
+ id: string;
287
+ document: DocumentId;
288
+ numbering: string;
289
+ title: string;
290
+ titleNormalized: string;
291
+ titleBlockId?: string;
292
+ chunkPath: string;
293
+ segments: SearchSegment[];
294
+ textLength: number;
295
+ assetTextLength: number;
296
+ }
218
297
  export interface SearchIndex {
219
- formatVersion: 2;
220
- units: Array<{
221
- id: string;
222
- document: DocumentId;
223
- numbering: string;
224
- title: string;
225
- chunkPath: string;
226
- text: string;
227
- }>;
298
+ formatVersion: 4;
299
+ normalization: string;
300
+ units: SearchUnit[];
301
+ references: Record<string, [number, number]>;
302
+ assetReferences: Record<string, Array<[number, number]>>;
303
+ postings: Record<string, string>;
304
+ }
305
+ export interface SearchResult {
306
+ id: string;
307
+ document: DocumentId;
308
+ numbering: string;
309
+ title: string;
310
+ chunkPath: string;
311
+ snippet: string;
312
+ highlights: Array<[number, number]>;
313
+ score: number;
314
+ matchKind: SearchMatchKind;
315
+ blockId?: string;
316
+ assetId?: string;
317
+ assetKind?: SearchAssetKind;
318
+ }
319
+ export interface NormativeReference {
320
+ numbering: string;
321
+ documentHint: "circ2019" | null;
322
+ }
323
+ export type CrossReferenceKind = "unit" | "formula" | "table" | "figure";
324
+ export interface CrossReferenceUnit {
325
+ id: string;
326
+ document: DocumentId;
327
+ numbering: string;
328
+ title: string;
329
+ snippet: string;
330
+ }
331
+ export interface CrossReferenceAsset {
332
+ id: string;
333
+ kind: Exclude<CrossReferenceKind, "unit">;
334
+ unitId: string;
335
+ blockId: string;
336
+ officialNumber: string;
337
+ title?: string | null;
338
+ snippet?: string | null;
339
+ }
340
+ export interface TextualBacklink {
341
+ targetType: CrossReferenceKind;
342
+ targetId: string;
343
+ sourceUnitId: string;
344
+ sourceBlockId: string;
345
+ }
346
+ export interface CrossReferenceIndex {
347
+ formatVersion: 1;
348
+ units: CrossReferenceUnit[];
349
+ assets: CrossReferenceAsset[];
350
+ backlinks: TextualBacklink[];
351
+ }
352
+ export interface DocumentLookup {
353
+ unitById: Map<string, UnitSummary>;
354
+ unitByNumbering: Map<string, UnitSummary>;
355
+ unitsByChunkPath: Map<string, UnitSummary[]>;
356
+ chunkPaths: string[];
357
+ chunkIndexByPath: Map<string, number>;
228
358
  }
229
359
  export declare function resolveDataPath(path: string, dataBaseUrl?: string): string;
360
+ export declare function createDocumentLookup(index: DocumentIndex): DocumentLookup;
361
+ export declare function parseNormativeReference(value: string): NormativeReference | null;
362
+ export declare function initialUnitForIndex(index: DocumentIndex, requestedUnitId: string | null): UnitSummary;
363
+ export declare function adjacentChunkPaths(lookup: DocumentLookup, chunkPath: string): {
364
+ previous: null;
365
+ next: null;
366
+ } | {
367
+ previous: string;
368
+ next: string;
369
+ };
370
+ /** Read-only instrumentation used by diagnostics and tests. */
371
+ export declare function cachedJsonPaths(): string[];
230
372
  export declare function documentForMode(mode: ViewerMode): DocumentId;
231
373
  export declare function loadManifest(dataBaseUrl?: string): Promise<CorpusManifest>;
232
374
  export declare function loadDocumentIndex(manifest: CorpusManifest, document: DocumentId, dataBaseUrl?: string): Promise<DocumentIndex>;
233
375
  export declare function loadChunk(path: string, dataBaseUrl?: string): Promise<CorpusChunk>;
234
376
  export declare function loadRelations(manifest: CorpusManifest, dataBaseUrl?: string): Promise<RelationsIndex>;
235
377
  export declare function loadSearchIndex(manifest: CorpusManifest, dataBaseUrl?: string): Promise<SearchIndex>;
378
+ export declare function loadCrossReferenceIndex(manifest: CorpusManifest, dataBaseUrl?: string): Promise<CrossReferenceIndex>;
@@ -16,9 +16,58 @@ async function fetchJson(path) {
16
16
  return response.json();
17
17
  });
18
18
  jsonCache.set(path, pending);
19
+ pending.catch(() => {
20
+ if (jsonCache.get(path) === pending)
21
+ jsonCache.delete(path);
22
+ });
19
23
  }
20
24
  return pending;
21
25
  }
26
+ export function createDocumentLookup(index) {
27
+ var _a;
28
+ const unitById = new Map();
29
+ const unitByNumbering = new Map();
30
+ const unitsByChunkPath = new Map();
31
+ for (const unit of index.units) {
32
+ unitById.set(unit.id, unit);
33
+ unitByNumbering.set(unit.numbering.official.replace(/^C/iu, ""), unit);
34
+ const chunkUnits = (_a = unitsByChunkPath.get(unit.chunkPath)) !== null && _a !== void 0 ? _a : [];
35
+ chunkUnits.push(unit);
36
+ unitsByChunkPath.set(unit.chunkPath, chunkUnits);
37
+ }
38
+ const chunkPaths = [...unitsByChunkPath.keys()];
39
+ return {
40
+ unitById,
41
+ unitByNumbering,
42
+ unitsByChunkPath,
43
+ chunkPaths,
44
+ chunkIndexByPath: new Map(chunkPaths.map((path, position) => [path, position])),
45
+ };
46
+ }
47
+ export function parseNormativeReference(value) {
48
+ const match = value.normalize("NFKC").trim().match(/^§?\s*(c)?\s*(\d+(?:\.\d+)*)\.?$/iu);
49
+ if (!match)
50
+ return null;
51
+ return { numbering: match[2], documentHint: match[1] ? "circ2019" : null };
52
+ }
53
+ export function initialUnitForIndex(index, requestedUnitId) {
54
+ var _a, _b, _c;
55
+ return (_c = (_b = (_a = index.units.find((unit) => unit.id === requestedUnitId)) !== null && _a !== void 0 ? _a : index.units.find((unit) => unit.hierarchy.ancestorIds.length === 0)) !== null && _b !== void 0 ? _b : index.units[0]) !== null && _c !== void 0 ? _c : null;
56
+ }
57
+ export function adjacentChunkPaths(lookup, chunkPath) {
58
+ var _a, _b;
59
+ const position = lookup.chunkIndexByPath.get(chunkPath);
60
+ if (position === undefined)
61
+ return { previous: null, next: null };
62
+ return {
63
+ previous: (_a = lookup.chunkPaths[position - 1]) !== null && _a !== void 0 ? _a : null,
64
+ next: (_b = lookup.chunkPaths[position + 1]) !== null && _b !== void 0 ? _b : null,
65
+ };
66
+ }
67
+ /** Read-only instrumentation used by diagnostics and tests. */
68
+ export function cachedJsonPaths() {
69
+ return [...jsonCache.keys()];
70
+ }
22
71
  export function documentForMode(mode) {
23
72
  return mode === "circ" ? "circ2019" : "ntc2018";
24
73
  }
@@ -37,4 +86,7 @@ export function loadRelations(manifest, dataBaseUrl = "/data/codes") {
37
86
  export function loadSearchIndex(manifest, dataBaseUrl = "/data/codes") {
38
87
  return fetchJson(resolveDataPath(manifest.searchIndexPath, dataBaseUrl));
39
88
  }
89
+ export function loadCrossReferenceIndex(manifest, dataBaseUrl = "/data/codes") {
90
+ return fetchJson(resolveDataPath(manifest.crossReferenceIndexPath, dataBaseUrl));
91
+ }
40
92
  //# sourceMappingURL=corpusData.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"corpusData.js","sourceRoot":"","sources":["../shared/corpusData.ts"],"names":[],"mappings":"AA2JA,MAAM,SAAS,GAAG,IAAI,GAAG,EAA4B,CAAC;AAEtD,SAAS,QAAQ,CAAC,WAAmB;IACnC,OAAO,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,WAAW,GAAG,aAAa;IACvE,IAAI,WAAW,KAAK,aAAa,IAAI,WAAW,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACrE,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED,KAAK,UAAU,SAAS,CAAI,IAAY;IACtC,IAAI,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;YAC5C,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;QACH,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAqB,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAgB;IAC9C,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;AAClD,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,WAAW,GAAG,aAAa;IACtD,OAAO,SAAS,CAAiB,eAAe,CAAC,2BAA2B,EAAE,WAAW,CAAC,CAAC,CAAC;AAC9F,CAAC;AACD,MAAM,UAAU,iBAAiB,CAAC,QAAwB,EAAE,QAAoB,EAAE,WAAW,GAAG,aAAa;IAC3G,OAAO,SAAS,CAAgB,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;AACxG,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,WAAW,GAAG,aAAa;IACjE,OAAO,SAAS,CAAc,eAAe,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;AACpE,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,QAAwB,EAAE,WAAW,GAAG,aAAa;IACjF,OAAO,SAAS,CAAiB,eAAe,CAAC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;AACzF,CAAC;AACD,MAAM,UAAU,eAAe,CAAC,QAAwB,EAAE,WAAW,GAAG,aAAa;IACnF,OAAO,SAAS,CAAc,eAAe,CAAC,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;AACxF,CAAC"}
1
+ {"version":3,"file":"corpusData.js","sourceRoot":"","sources":["../shared/corpusData.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ export function findCrossReferences(value: any): {
2
+ start: number;
3
+ end: number;
4
+ text: string;
5
+ kind: string;
6
+ number: any;
7
+ documentHint: string | null;
8
+ }[];
9
+ export function buildCrossReferenceIndexPayload({ units, assetCollections }: {
10
+ units: any;
11
+ assetCollections: any;
12
+ }): {
13
+ formatVersion: number;
14
+ units: any;
15
+ assets: {
16
+ title?: any;
17
+ snippet?: any;
18
+ id: any;
19
+ kind: string;
20
+ unitId: any;
21
+ blockId: any;
22
+ officialNumber: any;
23
+ }[];
24
+ backlinks: {
25
+ targetType: string;
26
+ targetId: any;
27
+ sourceUnitId: any;
28
+ sourceBlockId: any;
29
+ }[];
30
+ };
31
+ export function createCrossReferenceLookup(index: any): {
32
+ unitById: Map<any, any>;
33
+ unitByDocumentAndNumber: Map<any, any>;
34
+ assetById: Map<any, any>;
35
+ assetByDocumentKindAndNumber: Map<any, any>;
36
+ backlinksByTarget: Map<any, any>;
37
+ };
38
+ export function resolveCrossReference(lookup: any, reference: any, sourceDocument: any): {
39
+ targetType: string;
40
+ unit: any;
41
+ asset?: undefined;
42
+ } | {
43
+ targetType: any;
44
+ unit: any;
45
+ asset: any;
46
+ } | null;