eyecite-ts 0.1.0 → 0.2.0
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/README.md +129 -125
- package/dist/annotate/index.cjs.map +1 -1
- package/dist/annotate/index.d.cts +4 -4
- package/dist/annotate/index.d.cts.map +1 -1
- package/dist/annotate/index.d.mts +4 -4
- package/dist/annotate/index.d.mts.map +1 -1
- package/dist/annotate/index.mjs.map +1 -1
- package/dist/{citation-8_GvfEuj.d.mts → citation-BhJJj_AZ.d.cts} +32 -2
- package/dist/{citation-8_GvfEuj.d.mts.map → citation-BhJJj_AZ.d.cts.map} +1 -1
- package/dist/{citation-BcY5zzWb.d.cts → citation-FJ10UFM7.d.mts} +32 -2
- package/dist/{citation-BcY5zzWb.d.cts.map → citation-FJ10UFM7.d.mts.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -38
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +53 -38
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
# eyecite-ts
|
|
2
2
|
|
|
3
|
-
TypeScript legal citation extraction library
|
|
3
|
+
TypeScript legal citation extraction library — port of Python [eyecite](https://github.com/freelawproject/eyecite).
|
|
4
4
|
|
|
5
|
-
Extract,
|
|
5
|
+
Extract, resolve, and annotate legal citations from court opinions and legal documents with zero runtime dependencies.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **Full citation extraction**: Case citations, statutes, journal articles, neutral citations, public laws, federal register
|
|
10
10
|
- **Short-form resolution**: Id./Ibid., supra, and short-form case citations resolved to their full antecedents
|
|
11
|
-
- **Reporter database**:
|
|
12
|
-
- **Citation annotation**: HTML
|
|
13
|
-
- **Bundle optimization**: Tree-shakeable exports, lazy-loaded data, separate entry points
|
|
14
|
-
- **TypeScript native**: Discriminated unions,
|
|
11
|
+
- **Reporter database**: 1,200+ reporters with variant matching and confidence scoring
|
|
12
|
+
- **Citation annotation**: HTML markup with auto-escape XSS protection and position tracking
|
|
13
|
+
- **Bundle optimization**: Tree-shakeable exports, lazy-loaded reporter data, separate entry points
|
|
14
|
+
- **TypeScript native**: Discriminated unions, conditional types, type guards, full IntelliSense
|
|
15
|
+
- **Zero dependencies**: No runtime dependencies, 4.4KB gzipped core bundle
|
|
15
16
|
|
|
16
17
|
## Installation
|
|
17
18
|
|
|
@@ -36,13 +37,13 @@ console.log(citations[0])
|
|
|
36
37
|
// court: '9th Cir.',
|
|
37
38
|
// year: 2020,
|
|
38
39
|
// confidence: 0.85,
|
|
39
|
-
// span: { originalStart: 4, originalEnd: 48 }
|
|
40
|
+
// span: { originalStart: 4, originalEnd: 48, cleanStart: 4, cleanEnd: 48 }
|
|
40
41
|
// }
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
## Citation Extraction
|
|
44
45
|
|
|
45
|
-
###
|
|
46
|
+
### Multiple Citation Types
|
|
46
47
|
|
|
47
48
|
```typescript
|
|
48
49
|
import { extractCitations } from 'eyecite-ts'
|
|
@@ -70,7 +71,8 @@ const citations = await extractCitationsAsync(text)
|
|
|
70
71
|
### Custom Patterns
|
|
71
72
|
|
|
72
73
|
```typescript
|
|
73
|
-
import { extractCitations
|
|
74
|
+
import { extractCitations } from 'eyecite-ts'
|
|
75
|
+
import { casePatterns } from 'eyecite-ts'
|
|
74
76
|
|
|
75
77
|
// Extract only case citations
|
|
76
78
|
const citations = extractCitations(text, {
|
|
@@ -81,17 +83,17 @@ const citations = extractCitations(text, {
|
|
|
81
83
|
### Custom Cleaners
|
|
82
84
|
|
|
83
85
|
```typescript
|
|
84
|
-
import { extractCitations,
|
|
86
|
+
import { extractCitations, cleanText } from 'eyecite-ts'
|
|
85
87
|
|
|
86
|
-
// Use only HTML stripping
|
|
88
|
+
// Use only HTML stripping
|
|
87
89
|
const citations = extractCitations(html, {
|
|
88
|
-
cleaners: [
|
|
90
|
+
cleaners: [(text) => text.replace(/<[^>]+>/g, '')]
|
|
89
91
|
})
|
|
90
92
|
```
|
|
91
93
|
|
|
92
94
|
## Resolving Short-Form Citations
|
|
93
95
|
|
|
94
|
-
Short-form citations (Id., supra, short-form case) refer to earlier citations in the document. The resolution engine
|
|
96
|
+
Short-form citations (Id., supra, short-form case) refer to earlier citations in the document. The resolution engine links them to their full antecedents.
|
|
95
97
|
|
|
96
98
|
### Convenience API
|
|
97
99
|
|
|
@@ -105,16 +107,11 @@ const text = `
|
|
|
105
107
|
500 F.2d at 140.
|
|
106
108
|
`
|
|
107
109
|
|
|
108
|
-
// Convenience: extract + resolve in one call
|
|
109
110
|
const citations = extractCitations(text, { resolve: true })
|
|
110
111
|
|
|
111
112
|
// citations[1] is Id. citation
|
|
112
113
|
console.log(citations[1].resolution)
|
|
113
|
-
// {
|
|
114
|
-
// resolvedTo: 0, // Points to Smith v. Jones (index 0)
|
|
115
|
-
// confidence: 1.0,
|
|
116
|
-
// warnings: []
|
|
117
|
-
// }
|
|
114
|
+
// { resolvedTo: 0, confidence: 1.0 }
|
|
118
115
|
```
|
|
119
116
|
|
|
120
117
|
### Power-User API
|
|
@@ -122,15 +119,13 @@ console.log(citations[1].resolution)
|
|
|
122
119
|
```typescript
|
|
123
120
|
import { extractCitations, resolveCitations } from 'eyecite-ts'
|
|
124
121
|
|
|
125
|
-
// Step 1: Extract citations
|
|
126
122
|
const citations = extractCitations(text)
|
|
127
123
|
|
|
128
|
-
// Step 2: Resolve short-form citations
|
|
129
124
|
const resolved = resolveCitations(citations, text, {
|
|
130
|
-
scopeStrategy: 'paragraph',
|
|
131
|
-
fuzzyPartyMatching: true,
|
|
132
|
-
partyMatchThreshold: 0.8,
|
|
133
|
-
reportUnresolved: true
|
|
125
|
+
scopeStrategy: 'paragraph',
|
|
126
|
+
fuzzyPartyMatching: true,
|
|
127
|
+
partyMatchThreshold: 0.8,
|
|
128
|
+
reportUnresolved: true
|
|
134
129
|
})
|
|
135
130
|
```
|
|
136
131
|
|
|
@@ -153,125 +148,91 @@ const resolved = resolveCitations(citations, text, {
|
|
|
153
148
|
```typescript
|
|
154
149
|
const text = 'Smith v. Jones, 500 F.2d 123. Id. at 125.'
|
|
155
150
|
const citations = extractCitations(text, { resolve: true })
|
|
156
|
-
|
|
157
|
-
// citations[1].resolution.resolvedTo === 0 (points to Smith v. Jones)
|
|
151
|
+
// citations[1].resolution.resolvedTo === 0
|
|
158
152
|
```
|
|
159
153
|
|
|
160
154
|
**Supra citations:**
|
|
161
155
|
|
|
162
156
|
```typescript
|
|
163
|
-
const text = 'Smith v. Jones, 500 F.2d 123.
|
|
157
|
+
const text = 'Smith v. Jones, 500 F.2d 123. Smith, supra, at 130.'
|
|
164
158
|
const citations = extractCitations(text, { resolve: true })
|
|
165
|
-
|
|
166
159
|
// citations[1].resolution.resolvedTo === 0 (party name matches "Smith")
|
|
167
160
|
```
|
|
168
161
|
|
|
169
162
|
**Short-form case citations:**
|
|
170
163
|
|
|
171
164
|
```typescript
|
|
172
|
-
const text = 'Brown v. Board, 347 U.S. 483
|
|
165
|
+
const text = 'Brown v. Board, 347 U.S. 483. See 347 U.S. at 495.'
|
|
173
166
|
const citations = extractCitations(text, { resolve: true })
|
|
174
|
-
|
|
175
167
|
// citations[1].resolution.resolvedTo === 0 (volume/reporter matches)
|
|
176
168
|
```
|
|
177
169
|
|
|
178
|
-
|
|
170
|
+
**Unresolved citations:**
|
|
179
171
|
|
|
180
172
|
```typescript
|
|
181
173
|
const text = 'Id. at 100.' // Orphan Id. with no preceding citation
|
|
182
|
-
|
|
183
174
|
const citations = extractCitations(text, { resolve: true })
|
|
184
|
-
|
|
185
|
-
console.log(citations[0].resolution)
|
|
186
|
-
// {
|
|
187
|
-
// resolvedTo: undefined,
|
|
188
|
-
// failureReason: 'No preceding full citation found',
|
|
189
|
-
// confidence: 0,
|
|
190
|
-
// warnings: []
|
|
191
|
-
// }
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
To suppress unresolved warnings:
|
|
195
|
-
|
|
196
|
-
```typescript
|
|
197
|
-
const citations = extractCitations(text, {
|
|
198
|
-
resolve: true,
|
|
199
|
-
resolutionOptions: {
|
|
200
|
-
reportUnresolved: false // Omits resolution field for unresolved citations
|
|
201
|
-
}
|
|
202
|
-
})
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## Citation Validation
|
|
206
|
-
|
|
207
|
-
Validate case citations against the reporters database:
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
import { validateCitation } from 'eyecite-ts/data'
|
|
211
|
-
|
|
212
|
-
// Returns citations with adjusted confidence scores
|
|
213
|
-
const validated = await validateCitation(citations)
|
|
214
|
-
|
|
215
|
-
// Confidence adjustments:
|
|
216
|
-
// - +0.2 boost for reporter match
|
|
217
|
-
// - -0.3 penalty for reporter mismatch
|
|
218
|
-
// - -0.1 penalty for ambiguous reporter
|
|
175
|
+
// citations[0].resolution.failureReason === 'No preceding full case citation found'
|
|
219
176
|
```
|
|
220
177
|
|
|
221
178
|
## Citation Annotation
|
|
222
179
|
|
|
223
|
-
Add HTML
|
|
180
|
+
Add HTML markup to citations in text:
|
|
224
181
|
|
|
225
182
|
```typescript
|
|
226
183
|
import { annotate } from 'eyecite-ts/annotate'
|
|
184
|
+
import { extractCitations } from 'eyecite-ts'
|
|
185
|
+
|
|
186
|
+
const text = 'See Smith v. Jones, 500 F.2d 123 (2020).'
|
|
187
|
+
const citations = extractCitations(text)
|
|
227
188
|
|
|
228
|
-
// Template mode
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
)
|
|
189
|
+
// Template mode
|
|
190
|
+
const result = annotate(text, citations, {
|
|
191
|
+
template: { before: '<cite>', after: '</cite>' }
|
|
192
|
+
})
|
|
193
|
+
// result.text === 'See Smith v. Jones, <cite>500 F.2d 123</cite> (2020).'
|
|
234
194
|
|
|
235
195
|
// Callback mode (full control)
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
196
|
+
const result2 = annotate(text, citations, {
|
|
197
|
+
callback: (citation, surrounding) => {
|
|
198
|
+
if (citation.type === 'case') {
|
|
199
|
+
return `<a href="/cases/${citation.volume}">${citation.matchedText}</a>`
|
|
200
|
+
}
|
|
201
|
+
return citation.matchedText
|
|
202
|
+
}
|
|
239
203
|
})
|
|
240
204
|
```
|
|
241
205
|
|
|
242
206
|
Auto-escape is enabled by default for XSS protection:
|
|
243
207
|
|
|
244
208
|
```typescript
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
autoEscape: true // default
|
|
209
|
+
const result = annotate(text, citations, {
|
|
210
|
+
template: { before: '<cite>', after: '</cite>' },
|
|
211
|
+
autoEscape: true // default — escapes &, <, >, ", ', /
|
|
248
212
|
})
|
|
249
213
|
```
|
|
250
214
|
|
|
251
|
-
##
|
|
252
|
-
|
|
253
|
-
Core library is optimized for tree-shaking:
|
|
254
|
-
|
|
255
|
-
- **Core extraction**: 2.5 KB gzipped
|
|
256
|
-
- **Reporter database**: 88.5 KB gzipped (lazy-loaded)
|
|
257
|
-
- **Annotation**: 0.5 KB gzipped
|
|
215
|
+
## Reporter Validation
|
|
258
216
|
|
|
259
|
-
|
|
217
|
+
Validate case citations against the reporters database:
|
|
260
218
|
|
|
261
219
|
```typescript
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
220
|
+
import { extractWithValidation } from 'eyecite-ts'
|
|
221
|
+
|
|
222
|
+
const validated = await extractWithValidation(text, { validate: true })
|
|
223
|
+
// Confidence adjustments:
|
|
224
|
+
// +0.2 boost for reporter match
|
|
225
|
+
// -0.3 penalty for unknown reporter
|
|
226
|
+
// -0.1 per extra match for ambiguous reporter
|
|
266
227
|
```
|
|
267
228
|
|
|
268
|
-
##
|
|
229
|
+
## Type System
|
|
269
230
|
|
|
270
|
-
All citation types
|
|
231
|
+
All citation types use a discriminated union on the `type` field:
|
|
271
232
|
|
|
272
233
|
```typescript
|
|
273
234
|
import type {
|
|
274
|
-
Citation,
|
|
235
|
+
Citation, // Union of all 9 types
|
|
275
236
|
FullCaseCitation,
|
|
276
237
|
StatuteCitation,
|
|
277
238
|
JournalCitation,
|
|
@@ -280,24 +241,69 @@ import type {
|
|
|
280
241
|
FederalRegisterCitation,
|
|
281
242
|
IdCitation,
|
|
282
243
|
SupraCitation,
|
|
283
|
-
ShortFormCaseCitation
|
|
244
|
+
ShortFormCaseCitation,
|
|
245
|
+
CitationOfType, // Extract subtype: CitationOfType<'case'> = FullCaseCitation
|
|
246
|
+
ExtractorMap, // Maps FullCitationType keys to citation subtypes
|
|
247
|
+
FullCitation, // Union of full citation types
|
|
248
|
+
ShortFormCitation, // Union of short-form types
|
|
284
249
|
} from 'eyecite-ts'
|
|
250
|
+
```
|
|
285
251
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
252
|
+
### Type Guards
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import {
|
|
256
|
+
isFullCitation,
|
|
257
|
+
isShortFormCitation,
|
|
258
|
+
isCaseCitation,
|
|
259
|
+
isCitationType,
|
|
260
|
+
assertUnreachable
|
|
261
|
+
} from 'eyecite-ts'
|
|
262
|
+
|
|
263
|
+
// Specific guards
|
|
264
|
+
if (isFullCitation(citation)) {
|
|
265
|
+
// citation: FullCitation
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Generic guard — narrows to any specific type
|
|
269
|
+
if (isCitationType(citation, 'statute')) {
|
|
270
|
+
// citation: StatuteCitation
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Exhaustiveness check in switch statements
|
|
274
|
+
switch (citation.type) {
|
|
275
|
+
case 'case': /* ... */ break
|
|
276
|
+
case 'statute': /* ... */ break
|
|
277
|
+
// ... all 9 types ...
|
|
278
|
+
default: assertUnreachable(citation.type)
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Resolved Citation Types
|
|
283
|
+
|
|
284
|
+
`ResolvedCitation` uses a conditional type — `resolution` is only meaningfully present on short-form citations:
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
import type { ResolvedCitation } from 'eyecite-ts'
|
|
288
|
+
|
|
289
|
+
// On short-form citations: resolution: ResolutionResult | undefined
|
|
290
|
+
// On full citations: resolution?: undefined
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Bundle Size
|
|
294
|
+
|
|
295
|
+
Three entry points for optimal tree-shaking:
|
|
296
|
+
|
|
297
|
+
| Entry Point | Import | Gzipped |
|
|
298
|
+
|------------|--------|---------|
|
|
299
|
+
| Core extraction | `eyecite-ts` | 4.4 KB |
|
|
300
|
+
| Annotation | `eyecite-ts/annotate` | 0.5 KB |
|
|
301
|
+
| Reporter data | `eyecite-ts/data` | 88.5 KB (lazy-loaded) |
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { extractCitations } from 'eyecite-ts' // Core only
|
|
305
|
+
import { annotate } from 'eyecite-ts/annotate' // Annotation
|
|
306
|
+
import { loadReporters } from 'eyecite-ts/data' // Reporter database
|
|
301
307
|
```
|
|
302
308
|
|
|
303
309
|
## Architecture
|
|
@@ -307,28 +313,26 @@ Citation extraction follows a 4-stage pipeline:
|
|
|
307
313
|
1. **Clean**: Remove HTML, normalize Unicode, fix smart quotes
|
|
308
314
|
2. **Tokenize**: Apply regex patterns to find citation candidates
|
|
309
315
|
3. **Extract**: Parse metadata (volume, reporter, page, etc.)
|
|
310
|
-
4. **
|
|
316
|
+
4. **Resolve** (optional): Link short-form citations to antecedents
|
|
311
317
|
|
|
312
|
-
All positions (spans) track both cleaned and original text offsets
|
|
318
|
+
All positions (spans) track both cleaned and original text offsets via `TransformationMap`.
|
|
313
319
|
|
|
314
320
|
See [ARCHITECTURE.md](ARCHITECTURE.md) for details.
|
|
315
321
|
|
|
316
322
|
## Development
|
|
317
323
|
|
|
318
324
|
```bash
|
|
319
|
-
# Install dependencies
|
|
320
|
-
npm
|
|
321
|
-
|
|
322
|
-
#
|
|
323
|
-
npm
|
|
324
|
-
|
|
325
|
-
#
|
|
326
|
-
npm run typecheck
|
|
327
|
-
|
|
328
|
-
# Build
|
|
329
|
-
npm run build
|
|
325
|
+
npm install # Install dependencies
|
|
326
|
+
npm test # Run tests (vitest, watch mode)
|
|
327
|
+
npx vitest run # Run tests once
|
|
328
|
+
npm run typecheck # Type-check with tsc
|
|
329
|
+
npm run build # Build (ESM + CJS + DTS)
|
|
330
|
+
npm run lint # Lint with Biome
|
|
331
|
+
npm run format # Format with Biome
|
|
330
332
|
```
|
|
331
333
|
|
|
334
|
+
304 tests, 97% statement coverage, 91% branch coverage.
|
|
335
|
+
|
|
332
336
|
## License
|
|
333
337
|
|
|
334
338
|
MIT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/annotate/annotate.ts"],"sourcesContent":["import type { Citation } from '../types/citation'\nimport type { AnnotationOptions, AnnotationResult } from './types'\n\n/**\n * Annotate citations in text with custom markup.\n *\n * Supports two modes:\n * - **Template mode**: Simple before/after wrapping (set `options.template`)\n * - **Callback mode**: Custom logic with full citation context (set `options.callback`)\n *\n * Citations are processed in reverse order to avoid position shifts invalidating\n * subsequent annotations. Position tracking maps original positions to new positions\n * after markup insertion.\n *\n * @param text - Original or cleaned text to annotate\n * @param citations - Citations to mark up (from extraction pipeline)\n * @param options - Annotation configuration\n * @returns Annotated text with position mapping\n *\n * @example Template mode\n * ```typescript\n * const result = annotate(text, citations, {\n * template: { before: '<cite>', after: '</cite>' }\n * })\n * // Result: \"See <cite>500 F.2d 123</cite>\"\n * ```\n *\n * @example Callback mode\n * ```typescript\n * const result = annotate(text, citations, {\n * callback: (citation) => {\n * if (citation.type === 'case') {\n * return `<a href=\"/cases/${citation.volume}\">${citation.matchedText}</a>`\n * }\n * return citation.matchedText\n * }\n * })\n * ```\n *\n * @example Position tracking\n * ```typescript\n * const result = annotate(text, citations, { template: { before: '<mark>', after: '</mark>' } })\n * // result.positionMap tracks how positions shifted\n * const originalPos = 10\n * const newPos = result.positionMap.get(originalPos)\n * ```\n */\nexport function annotate(\n text: string,\n citations:
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/annotate/annotate.ts"],"sourcesContent":["import type { Citation } from '../types/citation'\nimport type { AnnotationOptions, AnnotationResult } from './types'\n\n/**\n * Annotate citations in text with custom markup.\n *\n * Supports two modes:\n * - **Template mode**: Simple before/after wrapping (set `options.template`)\n * - **Callback mode**: Custom logic with full citation context (set `options.callback`)\n *\n * Citations are processed in reverse order to avoid position shifts invalidating\n * subsequent annotations. Position tracking maps original positions to new positions\n * after markup insertion.\n *\n * @param text - Original or cleaned text to annotate\n * @param citations - Citations to mark up (from extraction pipeline)\n * @param options - Annotation configuration\n * @returns Annotated text with position mapping\n *\n * @example Template mode\n * ```typescript\n * const result = annotate(text, citations, {\n * template: { before: '<cite>', after: '</cite>' }\n * })\n * // Result: \"See <cite>500 F.2d 123</cite>\"\n * ```\n *\n * @example Callback mode\n * ```typescript\n * const result = annotate(text, citations, {\n * callback: (citation) => {\n * if (citation.type === 'case') {\n * return `<a href=\"/cases/${citation.volume}\">${citation.matchedText}</a>`\n * }\n * return citation.matchedText\n * }\n * })\n * ```\n *\n * @example Position tracking\n * ```typescript\n * const result = annotate(text, citations, { template: { before: '<mark>', after: '</mark>' } })\n * // result.positionMap tracks how positions shifted\n * const originalPos = 10\n * const newPos = result.positionMap.get(originalPos)\n * ```\n */\nexport function annotate<C extends Citation = Citation>(\n text: string,\n citations: C[],\n options: AnnotationOptions<C> = {}\n): AnnotationResult {\n const {\n useCleanText = false,\n autoEscape = true, // Secure by default\n template,\n callback,\n } = options\n\n // Sort reverse to avoid position shifts invalidating subsequent annotations\n const sorted = [...citations].sort((a, b) => {\n const aPos = useCleanText ? a.span.cleanStart : a.span.originalStart\n const bPos = useCleanText ? b.span.cleanStart : b.span.originalStart\n return bPos - aPos // Reverse for backward iteration\n })\n\n let result = text\n const positionMap = new Map<number, number>()\n\n for (const citation of sorted) {\n const start = useCleanText ? citation.span.cleanStart : citation.span.originalStart\n const end = useCleanText ? citation.span.cleanEnd : citation.span.originalEnd\n\n let markup = ''\n\n if (callback) {\n // Callback mode: developer provides full logic\n const surrounding = text.substring(\n Math.max(0, start - 30),\n Math.min(text.length, end + 30)\n )\n markup = callback(citation, surrounding)\n } else if (template) {\n // Template mode: simple before/after wrapping\n const citationText = result.substring(start, end)\n const escaped = autoEscape ? escapeHtmlEntities(citationText) : citationText\n markup = template.before + escaped + template.after\n } else {\n // No annotation specified\n continue\n }\n\n // Insert annotation (working backwards preserves positions for later citations)\n result = result.slice(0, start) + markup + result.slice(end)\n\n // Track original position to new position (before this annotation was added)\n positionMap.set(start, start)\n }\n\n return { text: result, positionMap, skipped: [] }\n}\n\n/**\n * Escape HTML entities to prevent XSS injection.\n *\n * Converts special HTML characters to their entity equivalents:\n * - `&` → `&`\n * - `<` → `<`\n * - `>` → `>`\n * - `\"` → `"`\n * - `'` → `'`\n * - `/` → `/`\n *\n * @param text - Text to escape\n * @returns Escaped text safe for HTML insertion\n */\nfunction escapeHtmlEntities(text: string): string {\n const map: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n }\n return text.replace(/[&<>\"'\\/]/g, (char) => map[char])\n}\n"],"mappings":"mEA+CA,SAAgB,EACd,EACA,EACA,EAAgC,EAAE,CAChB,CAClB,GAAM,CACJ,eAAe,GACf,aAAa,GACb,WACA,YACE,EAGE,EAAS,CAAC,GAAG,EAAU,CAAC,MAAM,EAAG,IAAM,CAC3C,IAAM,EAAO,EAAe,EAAE,KAAK,WAAa,EAAE,KAAK,cAEvD,OADa,EAAe,EAAE,KAAK,WAAa,EAAE,KAAK,eACzC,GACd,CAEE,EAAS,EACP,EAAc,IAAI,IAExB,IAAK,IAAM,KAAY,EAAQ,CAC7B,IAAM,EAAQ,EAAe,EAAS,KAAK,WAAa,EAAS,KAAK,cAChE,EAAM,EAAe,EAAS,KAAK,SAAW,EAAS,KAAK,YAE9D,EAAS,GAEb,GAAI,EAMF,EAAS,EAAS,EAJE,EAAK,UACvB,KAAK,IAAI,EAAG,EAAQ,GAAG,CACvB,KAAK,IAAI,EAAK,OAAQ,EAAM,GAAG,CAChC,CACuC,SAC/B,EAAU,CAEnB,IAAM,EAAe,EAAO,UAAU,EAAO,EAAI,CAC3C,EAAU,EAAa,EAAmB,EAAa,CAAG,EAChE,EAAS,EAAS,OAAS,EAAU,EAAS,WAG9C,SAIF,EAAS,EAAO,MAAM,EAAG,EAAM,CAAG,EAAS,EAAO,MAAM,EAAI,CAG5D,EAAY,IAAI,EAAO,EAAM,CAG/B,MAAO,CAAE,KAAM,EAAQ,cAAa,QAAS,EAAE,CAAE,CAiBnD,SAAS,EAAmB,EAAsB,CAChD,IAAM,EAA8B,CAClC,IAAK,QACL,IAAK,OACL,IAAK,OACL,IAAK,SACL,IAAK,QACL,IAAK,SACN,CACD,OAAO,EAAK,QAAQ,aAAe,GAAS,EAAI,GAAM"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Citation } from "../citation-
|
|
1
|
+
import { t as Citation } from "../citation-BhJJj_AZ.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/annotate/types.d.ts
|
|
4
4
|
/**
|
|
@@ -27,7 +27,7 @@ import { t as Citation } from "../citation-BcY5zzWb.cjs";
|
|
|
27
27
|
* })
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
interface AnnotationOptions {
|
|
30
|
+
interface AnnotationOptions<C extends Citation = Citation> {
|
|
31
31
|
/**
|
|
32
32
|
* Apply annotations to cleaned text (true) or original text (false).
|
|
33
33
|
*
|
|
@@ -65,7 +65,7 @@ interface AnnotationOptions {
|
|
|
65
65
|
* @param surrounding - Text around the citation (for context-aware markup)
|
|
66
66
|
* @returns Complete markup string (replaces citation.matchedText)
|
|
67
67
|
*/
|
|
68
|
-
callback?: (citation:
|
|
68
|
+
callback?: (citation: C, surrounding: string) => string;
|
|
69
69
|
/**
|
|
70
70
|
* Template mode: simple before/after markup strings.
|
|
71
71
|
*
|
|
@@ -157,7 +157,7 @@ interface AnnotationResult {
|
|
|
157
157
|
* const newPos = result.positionMap.get(originalPos)
|
|
158
158
|
* ```
|
|
159
159
|
*/
|
|
160
|
-
declare function annotate(text: string, citations:
|
|
160
|
+
declare function annotate<C extends Citation = Citation>(text: string, citations: C[], options?: AnnotationOptions<C>): AnnotationResult;
|
|
161
161
|
//#endregion
|
|
162
162
|
export { AnnotationOptions, AnnotationResult, annotate };
|
|
163
163
|
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/annotate/types.ts","../../src/annotate/annotate.ts"],"mappings":";;;;;AA4BA
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/annotate/types.ts","../../src/annotate/annotate.ts"],"mappings":";;;;;AA4BA;;;;;;;;;;;;;;;;;;;;;;AAoEA;;UApEiB,iBAAA,WAA4B,QAAA,GAAW,QAAA;EA0F7C;;;;;;;;EAjFT,YAAA;;;ACUF;;;;;;;;;;;;;;;EDSE,UAAA;;;;;;;;;;;EAYA,QAAA,IAAY,QAAA,EAAU,CAAA,EAAG,WAAA;;;;;;;;;;;;;;;;EAiBzB,QAAA;+CAEE,MAAA;IAEA,KAAA;EAAA;AAAA;;;;UAOa,gBAAA;;;;EAIf,IAAA;;;;;;;;;EAUA,WAAA,EAAa,GAAA;;;;;;;EAQb,OAAA,EAAS,QAAA;AAAA;;;;AA1FX;;;;;;;;;;;;;;;;;;;;;;AAoEA;;;;;;;;;;;;;;ACjDA;;;;;;;iBAAgB,QAAA,WAAmB,QAAA,GAAW,QAAA,CAAA,CAC5C,IAAA,UACA,SAAA,EAAW,CAAA,IACX,OAAA,GAAS,iBAAA,CAAkB,CAAA,IAC1B,gBAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Citation } from "../citation-
|
|
1
|
+
import { t as Citation } from "../citation-FJ10UFM7.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/annotate/types.d.ts
|
|
4
4
|
/**
|
|
@@ -27,7 +27,7 @@ import { t as Citation } from "../citation-8_GvfEuj.mjs";
|
|
|
27
27
|
* })
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
interface AnnotationOptions {
|
|
30
|
+
interface AnnotationOptions<C extends Citation = Citation> {
|
|
31
31
|
/**
|
|
32
32
|
* Apply annotations to cleaned text (true) or original text (false).
|
|
33
33
|
*
|
|
@@ -65,7 +65,7 @@ interface AnnotationOptions {
|
|
|
65
65
|
* @param surrounding - Text around the citation (for context-aware markup)
|
|
66
66
|
* @returns Complete markup string (replaces citation.matchedText)
|
|
67
67
|
*/
|
|
68
|
-
callback?: (citation:
|
|
68
|
+
callback?: (citation: C, surrounding: string) => string;
|
|
69
69
|
/**
|
|
70
70
|
* Template mode: simple before/after markup strings.
|
|
71
71
|
*
|
|
@@ -157,7 +157,7 @@ interface AnnotationResult {
|
|
|
157
157
|
* const newPos = result.positionMap.get(originalPos)
|
|
158
158
|
* ```
|
|
159
159
|
*/
|
|
160
|
-
declare function annotate(text: string, citations:
|
|
160
|
+
declare function annotate<C extends Citation = Citation>(text: string, citations: C[], options?: AnnotationOptions<C>): AnnotationResult;
|
|
161
161
|
//#endregion
|
|
162
162
|
export { AnnotationOptions, AnnotationResult, annotate };
|
|
163
163
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/annotate/types.ts","../../src/annotate/annotate.ts"],"mappings":";;;;;AA4BA
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/annotate/types.ts","../../src/annotate/annotate.ts"],"mappings":";;;;;AA4BA;;;;;;;;;;;;;;;;;;;;;;AAoEA;;UApEiB,iBAAA,WAA4B,QAAA,GAAW,QAAA;EA0F7C;;;;;;;;EAjFT,YAAA;;;ACUF;;;;;;;;;;;;;;;EDSE,UAAA;;;;;;;;;;;EAYA,QAAA,IAAY,QAAA,EAAU,CAAA,EAAG,WAAA;;;;;;;;;;;;;;;;EAiBzB,QAAA;+CAEE,MAAA;IAEA,KAAA;EAAA;AAAA;;;;UAOa,gBAAA;;;;EAIf,IAAA;;;;;;;;;EAUA,WAAA,EAAa,GAAA;;;;;;;EAQb,OAAA,EAAS,QAAA;AAAA;;;;AA1FX;;;;;;;;;;;;;;;;;;;;;;AAoEA;;;;;;;;;;;;;;ACjDA;;;;;;;iBAAgB,QAAA,WAAmB,QAAA,GAAW,QAAA,CAAA,CAC5C,IAAA,UACA,SAAA,EAAW,CAAA,IACX,OAAA,GAAS,iBAAA,CAAkB,CAAA,IAC1B,gBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/annotate/annotate.ts"],"sourcesContent":["import type { Citation } from '../types/citation'\nimport type { AnnotationOptions, AnnotationResult } from './types'\n\n/**\n * Annotate citations in text with custom markup.\n *\n * Supports two modes:\n * - **Template mode**: Simple before/after wrapping (set `options.template`)\n * - **Callback mode**: Custom logic with full citation context (set `options.callback`)\n *\n * Citations are processed in reverse order to avoid position shifts invalidating\n * subsequent annotations. Position tracking maps original positions to new positions\n * after markup insertion.\n *\n * @param text - Original or cleaned text to annotate\n * @param citations - Citations to mark up (from extraction pipeline)\n * @param options - Annotation configuration\n * @returns Annotated text with position mapping\n *\n * @example Template mode\n * ```typescript\n * const result = annotate(text, citations, {\n * template: { before: '<cite>', after: '</cite>' }\n * })\n * // Result: \"See <cite>500 F.2d 123</cite>\"\n * ```\n *\n * @example Callback mode\n * ```typescript\n * const result = annotate(text, citations, {\n * callback: (citation) => {\n * if (citation.type === 'case') {\n * return `<a href=\"/cases/${citation.volume}\">${citation.matchedText}</a>`\n * }\n * return citation.matchedText\n * }\n * })\n * ```\n *\n * @example Position tracking\n * ```typescript\n * const result = annotate(text, citations, { template: { before: '<mark>', after: '</mark>' } })\n * // result.positionMap tracks how positions shifted\n * const originalPos = 10\n * const newPos = result.positionMap.get(originalPos)\n * ```\n */\nexport function annotate(\n text: string,\n citations:
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/annotate/annotate.ts"],"sourcesContent":["import type { Citation } from '../types/citation'\nimport type { AnnotationOptions, AnnotationResult } from './types'\n\n/**\n * Annotate citations in text with custom markup.\n *\n * Supports two modes:\n * - **Template mode**: Simple before/after wrapping (set `options.template`)\n * - **Callback mode**: Custom logic with full citation context (set `options.callback`)\n *\n * Citations are processed in reverse order to avoid position shifts invalidating\n * subsequent annotations. Position tracking maps original positions to new positions\n * after markup insertion.\n *\n * @param text - Original or cleaned text to annotate\n * @param citations - Citations to mark up (from extraction pipeline)\n * @param options - Annotation configuration\n * @returns Annotated text with position mapping\n *\n * @example Template mode\n * ```typescript\n * const result = annotate(text, citations, {\n * template: { before: '<cite>', after: '</cite>' }\n * })\n * // Result: \"See <cite>500 F.2d 123</cite>\"\n * ```\n *\n * @example Callback mode\n * ```typescript\n * const result = annotate(text, citations, {\n * callback: (citation) => {\n * if (citation.type === 'case') {\n * return `<a href=\"/cases/${citation.volume}\">${citation.matchedText}</a>`\n * }\n * return citation.matchedText\n * }\n * })\n * ```\n *\n * @example Position tracking\n * ```typescript\n * const result = annotate(text, citations, { template: { before: '<mark>', after: '</mark>' } })\n * // result.positionMap tracks how positions shifted\n * const originalPos = 10\n * const newPos = result.positionMap.get(originalPos)\n * ```\n */\nexport function annotate<C extends Citation = Citation>(\n text: string,\n citations: C[],\n options: AnnotationOptions<C> = {}\n): AnnotationResult {\n const {\n useCleanText = false,\n autoEscape = true, // Secure by default\n template,\n callback,\n } = options\n\n // Sort reverse to avoid position shifts invalidating subsequent annotations\n const sorted = [...citations].sort((a, b) => {\n const aPos = useCleanText ? a.span.cleanStart : a.span.originalStart\n const bPos = useCleanText ? b.span.cleanStart : b.span.originalStart\n return bPos - aPos // Reverse for backward iteration\n })\n\n let result = text\n const positionMap = new Map<number, number>()\n\n for (const citation of sorted) {\n const start = useCleanText ? citation.span.cleanStart : citation.span.originalStart\n const end = useCleanText ? citation.span.cleanEnd : citation.span.originalEnd\n\n let markup = ''\n\n if (callback) {\n // Callback mode: developer provides full logic\n const surrounding = text.substring(\n Math.max(0, start - 30),\n Math.min(text.length, end + 30)\n )\n markup = callback(citation, surrounding)\n } else if (template) {\n // Template mode: simple before/after wrapping\n const citationText = result.substring(start, end)\n const escaped = autoEscape ? escapeHtmlEntities(citationText) : citationText\n markup = template.before + escaped + template.after\n } else {\n // No annotation specified\n continue\n }\n\n // Insert annotation (working backwards preserves positions for later citations)\n result = result.slice(0, start) + markup + result.slice(end)\n\n // Track original position to new position (before this annotation was added)\n positionMap.set(start, start)\n }\n\n return { text: result, positionMap, skipped: [] }\n}\n\n/**\n * Escape HTML entities to prevent XSS injection.\n *\n * Converts special HTML characters to their entity equivalents:\n * - `&` → `&`\n * - `<` → `<`\n * - `>` → `>`\n * - `\"` → `"`\n * - `'` → `'`\n * - `/` → `/`\n *\n * @param text - Text to escape\n * @returns Escaped text safe for HTML insertion\n */\nfunction escapeHtmlEntities(text: string): string {\n const map: Record<string, string> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n }\n return text.replace(/[&<>\"'\\/]/g, (char) => map[char])\n}\n"],"mappings":"AA+CA,SAAgB,EACd,EACA,EACA,EAAgC,EAAE,CAChB,CAClB,GAAM,CACJ,eAAe,GACf,aAAa,GACb,WACA,YACE,EAGE,EAAS,CAAC,GAAG,EAAU,CAAC,MAAM,EAAG,IAAM,CAC3C,IAAM,EAAO,EAAe,EAAE,KAAK,WAAa,EAAE,KAAK,cAEvD,OADa,EAAe,EAAE,KAAK,WAAa,EAAE,KAAK,eACzC,GACd,CAEE,EAAS,EACP,EAAc,IAAI,IAExB,IAAK,IAAM,KAAY,EAAQ,CAC7B,IAAM,EAAQ,EAAe,EAAS,KAAK,WAAa,EAAS,KAAK,cAChE,EAAM,EAAe,EAAS,KAAK,SAAW,EAAS,KAAK,YAE9D,EAAS,GAEb,GAAI,EAMF,EAAS,EAAS,EAJE,EAAK,UACvB,KAAK,IAAI,EAAG,EAAQ,GAAG,CACvB,KAAK,IAAI,EAAK,OAAQ,EAAM,GAAG,CAChC,CACuC,SAC/B,EAAU,CAEnB,IAAM,EAAe,EAAO,UAAU,EAAO,EAAI,CAC3C,EAAU,EAAa,EAAmB,EAAa,CAAG,EAChE,EAAS,EAAS,OAAS,EAAU,EAAS,WAG9C,SAIF,EAAS,EAAO,MAAM,EAAG,EAAM,CAAG,EAAS,EAAO,MAAM,EAAI,CAG5D,EAAY,IAAI,EAAO,EAAM,CAG/B,MAAO,CAAE,KAAM,EAAQ,cAAa,QAAS,EAAE,CAAE,CAiBnD,SAAS,EAAmB,EAAsB,CAChD,IAAM,EAA8B,CAClC,IAAK,QACL,IAAK,OACL,IAAK,OACL,IAAK,SACL,IAAK,QACL,IAAK,SACN,CACD,OAAO,EAAK,QAAQ,aAAe,GAAS,EAAI,GAAM"}
|
|
@@ -281,6 +281,36 @@ interface ShortFormCaseCitation extends CitationBase {
|
|
|
281
281
|
* }
|
|
282
282
|
*/
|
|
283
283
|
type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
|
|
284
|
+
/**
|
|
285
|
+
* Citation type discriminators grouped by category.
|
|
286
|
+
*/
|
|
287
|
+
type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister";
|
|
288
|
+
type ShortFormCitationType = "id" | "supra" | "shortFormCase";
|
|
289
|
+
/**
|
|
290
|
+
* Union of all full citation types (not short-form references).
|
|
291
|
+
*/
|
|
292
|
+
type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation;
|
|
293
|
+
/**
|
|
294
|
+
* Union of all short-form citation types (Id., supra, short-form case).
|
|
295
|
+
*/
|
|
296
|
+
type ShortFormCitation = IdCitation | SupraCitation | ShortFormCaseCitation;
|
|
297
|
+
/**
|
|
298
|
+
* Extract the Citation subtype for a given type discriminator.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```typescript
|
|
302
|
+
* type CaseCit = CitationOfType<'case'> // FullCaseCitation
|
|
303
|
+
* type IdCit = CitationOfType<'id'> // IdCitation
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
type CitationOfType<T extends CitationType> = Extract<Citation, {
|
|
307
|
+
type: T;
|
|
308
|
+
}>;
|
|
309
|
+
/**
|
|
310
|
+
* Maps each full citation type to its concrete Citation subtype.
|
|
311
|
+
* Useful for generic code building custom extraction pipelines.
|
|
312
|
+
*/
|
|
313
|
+
type ExtractorMap = { [K in FullCitationType]: CitationOfType<K> };
|
|
284
314
|
//#endregion
|
|
285
|
-
export {
|
|
286
|
-
//# sourceMappingURL=citation-
|
|
315
|
+
export { StatuteCitation as _, ExtractorMap as a, Span as b, FullCitation as c, JournalCitation as d, NeutralCitation as f, ShortFormCitationType as g, ShortFormCitation as h, CitationType as i, FullCitationType as l, ShortFormCaseCitation as m, CitationBase as n, FederalRegisterCitation as o, PublicLawCitation as p, CitationOfType as r, FullCaseCitation as s, Citation as t, IdCitation as u, SupraCitation as v, TransformationMap as x, Warning as y };
|
|
316
|
+
//# sourceMappingURL=citation-BhJJj_AZ.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"citation-
|
|
1
|
+
{"version":3,"file":"citation-BhJJj_AZ.d.cts","names":[],"sources":["../src/types/span.ts","../src/types/citation.ts"],"mappings":";;AAiBA;;;;;;;;;;AAoBA;;;;;;UApBiB,IAAA;;EAEf,UAAA;EAuBiB;EApBjB,QAAA;;EAGA,aAAA;ECpBF;EDuBE,WAAA;AAAA;;;AClBF;;;;UD2BiB,iBAAA;;EAEf,eAAA,EAAiB,GAAA;;EAGjB,eAAA,EAAiB,GAAA;AAAA;;;AAzBnB;;;AAAA,KCZY,YAAA;;;;UAKK,OAAA;;EAEf,KAAA;EDyBF;ECvBE,OAAA;;EAEA,QAAA;IAAY,KAAA;IAAe,GAAA;EAAA;;EAE3B,OAAA;AAAA;;;;UAMe,YAAA;EAnBL;EAqBV,IAAA;EArBU;EAwBV,IAAA,EAAM,IAAA;EAnBR;;;;;;;EA4BE,UAAA;;EAGA,WAAA;;EAGA,aAAA;EApBF;EAuBE,eAAA;;EAGA,QAAA,GAAW,OAAA;AAAA;;;;;;;UASI,gBAAA,SAAyB,YAAA;EACxC,IAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA;;EAGA,kBAAA;;EAGA,iBAAA,GAAoB,KAAA;IAClB,MAAA;IACA,QAAA;IACA,IAAA;EAAA;;EAIF,MAAA;;EAGA,aAAA;;EAGA,iBAAA;;;;;;EAOA,IAAA;IACE,GAAA;IACA,MAAA;MAAW,IAAA;MAAc,KAAA;MAAgB,GAAA;IAAA;EAAA;;;;;EAO3C,uBAAA,GAA0B,KAAA;IACxB,MAAA;IACA,QAAA;IACA,IAAA;IACA,UAAA;IACA,MAAA;EAAA;AAAA;;;;;;UASa,eAAA,SAAwB,YAAA;EACvC,IAAA;EACA,KAAA;EACA,IAAA;EACA,OAAA;AAAA;;;;;;;;;UAWe,eAAA,SAAwB,YAAA;EACvC,IAAA;;EAEA,MAAA;EAcA;EAZA,KAAA;EAuBe;EArBf,MAAA;EAqBuC;EAnBvC,OAAA;;EAEA,YAAA;;EAEA,IAAA;;EAEA,OAAA;EA+BF;EA7BE,IAAA;AAAA;;;;;;;;;UAWe,eAAA,SAAwB,YAAA;EACvC,IAAA;;EAEA,IAAA;;EAEA,KAAA;;EAEA,cAAA;AAAA;;;AA6CF;;;;;;UAlCiB,iBAAA,SAA0B,YAAA;EACzC,IAAA;EAmCA;EAjCA,QAAA;EA0Ce;EAxCf,SAAA;EAwCqC;EAtCrC,KAAA;AAAA;;;;;AAoDF;;;;UAzCiB,uBAAA,SAAgC,YAAA;EAC/C,IAAA;;EAEA,MAAA;;EAEA,IAAA;;EAEA,IAAA;AAAA;;;;;;;UASe,UAAA,SAAmB,YAAA;EAClC,IAAA;EACA,OAAA;AAAA;;;;;;;UASe,aAAA,SAAsB,YAAA;EACrC,IAAA;;EAEA,SAAA;;EAEA,OAAA;AAAA;;AAgDF;;;;;UAvCiB,qBAAA,SAA8B,YAAA;EAC7C,IAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,OAAA;AAAA;;;;;;;;;;;;;;;;;;KAoBU,QAAA,GACR,gBAAA,GACA,eAAA,GACA,eAAA,GACA,eAAA,GACA,iBAAA,GACA,uBAAA,GACA,UAAA,GACA,aAAA,GACA,qBAAA;;;;KAKQ,gBAAA;AAAA,KACA,qBAAA;;;;KAKA,YAAA,GAAe,gBAAA,GAAmB,eAAA,GAAkB,eAAA,GAAkB,eAAA,GAAkB,iBAAA,GAAoB,uBAAA;;;;KAK5G,iBAAA,GAAoB,UAAA,GAAa,aAAA,GAAgB,qBAAA;;;;;;;;;;KAWjD,cAAA,WAAyB,YAAA,IAAgB,OAAA,CAAQ,QAAA;EAAY,IAAA,EAAM,CAAA;AAAA;;;;;KAMnE,YAAA,WACJ,gBAAA,GAAmB,cAAA,CAAe,CAAA"}
|
|
@@ -281,6 +281,36 @@ interface ShortFormCaseCitation extends CitationBase {
|
|
|
281
281
|
* }
|
|
282
282
|
*/
|
|
283
283
|
type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
|
|
284
|
+
/**
|
|
285
|
+
* Citation type discriminators grouped by category.
|
|
286
|
+
*/
|
|
287
|
+
type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister";
|
|
288
|
+
type ShortFormCitationType = "id" | "supra" | "shortFormCase";
|
|
289
|
+
/**
|
|
290
|
+
* Union of all full citation types (not short-form references).
|
|
291
|
+
*/
|
|
292
|
+
type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation;
|
|
293
|
+
/**
|
|
294
|
+
* Union of all short-form citation types (Id., supra, short-form case).
|
|
295
|
+
*/
|
|
296
|
+
type ShortFormCitation = IdCitation | SupraCitation | ShortFormCaseCitation;
|
|
297
|
+
/**
|
|
298
|
+
* Extract the Citation subtype for a given type discriminator.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```typescript
|
|
302
|
+
* type CaseCit = CitationOfType<'case'> // FullCaseCitation
|
|
303
|
+
* type IdCit = CitationOfType<'id'> // IdCitation
|
|
304
|
+
* ```
|
|
305
|
+
*/
|
|
306
|
+
type CitationOfType<T extends CitationType> = Extract<Citation, {
|
|
307
|
+
type: T;
|
|
308
|
+
}>;
|
|
309
|
+
/**
|
|
310
|
+
* Maps each full citation type to its concrete Citation subtype.
|
|
311
|
+
* Useful for generic code building custom extraction pipelines.
|
|
312
|
+
*/
|
|
313
|
+
type ExtractorMap = { [K in FullCitationType]: CitationOfType<K> };
|
|
284
314
|
//#endregion
|
|
285
|
-
export {
|
|
286
|
-
//# sourceMappingURL=citation-
|
|
315
|
+
export { StatuteCitation as _, ExtractorMap as a, Span as b, FullCitation as c, JournalCitation as d, NeutralCitation as f, ShortFormCitationType as g, ShortFormCitation as h, CitationType as i, FullCitationType as l, ShortFormCaseCitation as m, CitationBase as n, FederalRegisterCitation as o, PublicLawCitation as p, CitationOfType as r, FullCaseCitation as s, Citation as t, IdCitation as u, SupraCitation as v, TransformationMap as x, Warning as y };
|
|
316
|
+
//# sourceMappingURL=citation-FJ10UFM7.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"citation-
|
|
1
|
+
{"version":3,"file":"citation-FJ10UFM7.d.mts","names":[],"sources":["../src/types/span.ts","../src/types/citation.ts"],"mappings":";;AAiBA;;;;;;;;;;AAoBA;;;;;;UApBiB,IAAA;;EAEf,UAAA;EAuBiB;EApBjB,QAAA;;EAGA,aAAA;ECpBF;EDuBE,WAAA;AAAA;;;AClBF;;;;UD2BiB,iBAAA;;EAEf,eAAA,EAAiB,GAAA;;EAGjB,eAAA,EAAiB,GAAA;AAAA;;;AAzBnB;;;AAAA,KCZY,YAAA;;;;UAKK,OAAA;;EAEf,KAAA;EDyBF;ECvBE,OAAA;;EAEA,QAAA;IAAY,KAAA;IAAe,GAAA;EAAA;;EAE3B,OAAA;AAAA;;;;UAMe,YAAA;EAnBL;EAqBV,IAAA;EArBU;EAwBV,IAAA,EAAM,IAAA;EAnBR;;;;;;;EA4BE,UAAA;;EAGA,WAAA;;EAGA,aAAA;EApBF;EAuBE,eAAA;;EAGA,QAAA,GAAW,OAAA;AAAA;;;;;;;UASI,gBAAA,SAAyB,YAAA;EACxC,IAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,OAAA;EACA,KAAA;EACA,IAAA;;EAGA,kBAAA;;EAGA,iBAAA,GAAoB,KAAA;IAClB,MAAA;IACA,QAAA;IACA,IAAA;EAAA;;EAIF,MAAA;;EAGA,aAAA;;EAGA,iBAAA;;;;;;EAOA,IAAA;IACE,GAAA;IACA,MAAA;MAAW,IAAA;MAAc,KAAA;MAAgB,GAAA;IAAA;EAAA;;;;;EAO3C,uBAAA,GAA0B,KAAA;IACxB,MAAA;IACA,QAAA;IACA,IAAA;IACA,UAAA;IACA,MAAA;EAAA;AAAA;;;;;;UASa,eAAA,SAAwB,YAAA;EACvC,IAAA;EACA,KAAA;EACA,IAAA;EACA,OAAA;AAAA;;;;;;;;;UAWe,eAAA,SAAwB,YAAA;EACvC,IAAA;;EAEA,MAAA;EAcA;EAZA,KAAA;EAuBe;EArBf,MAAA;EAqBuC;EAnBvC,OAAA;;EAEA,YAAA;;EAEA,IAAA;;EAEA,OAAA;EA+BF;EA7BE,IAAA;AAAA;;;;;;;;;UAWe,eAAA,SAAwB,YAAA;EACvC,IAAA;;EAEA,IAAA;;EAEA,KAAA;;EAEA,cAAA;AAAA;;;AA6CF;;;;;;UAlCiB,iBAAA,SAA0B,YAAA;EACzC,IAAA;EAmCA;EAjCA,QAAA;EA0Ce;EAxCf,SAAA;EAwCqC;EAtCrC,KAAA;AAAA;;;;;AAoDF;;;;UAzCiB,uBAAA,SAAgC,YAAA;EAC/C,IAAA;;EAEA,MAAA;;EAEA,IAAA;;EAEA,IAAA;AAAA;;;;;;;UASe,UAAA,SAAmB,YAAA;EAClC,IAAA;EACA,OAAA;AAAA;;;;;;;UASe,aAAA,SAAsB,YAAA;EACrC,IAAA;;EAEA,SAAA;;EAEA,OAAA;AAAA;;AAgDF;;;;;UAvCiB,qBAAA,SAA8B,YAAA;EAC7C,IAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,OAAA;AAAA;;;;;;;;;;;;;;;;;;KAoBU,QAAA,GACR,gBAAA,GACA,eAAA,GACA,eAAA,GACA,eAAA,GACA,iBAAA,GACA,uBAAA,GACA,UAAA,GACA,aAAA,GACA,qBAAA;;;;KAKQ,gBAAA;AAAA,KACA,qBAAA;;;;KAKA,YAAA,GAAe,gBAAA,GAAmB,eAAA,GAAkB,eAAA,GAAkB,eAAA,GAAkB,iBAAA,GAAoB,uBAAA;;;;KAK5G,iBAAA,GAAoB,UAAA,GAAa,aAAA,GAAgB,qBAAA;;;;;;;;;;KAWjD,cAAA,WAAyB,YAAA,IAAgB,OAAA,CAAQ,QAAA;EAAY,IAAA,EAAM,CAAA;AAAA;;;;;KAMnE,YAAA,WACJ,gBAAA,GAAmB,cAAA,CAAe,CAAA"}
|