eyecite-ts 0.4.0 → 0.6.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 +80 -10
- package/dist/annotate/index.cjs.map +1 -1
- package/dist/annotate/index.d.cts +1 -1
- package/dist/annotate/index.d.mts +1 -1
- package/dist/annotate/index.mjs.map +1 -1
- package/dist/{citation-4bmWbhSK.d.cts → citation-BwXdJTA9.d.mts} +190 -12
- package/dist/citation-BwXdJTA9.d.mts.map +1 -0
- package/dist/{citation-BVN0o8TJ.d.mts → citation-By8QXtGC.d.cts} +190 -12
- package/dist/citation-By8QXtGC.d.cts.map +1 -0
- package/dist/data/index.cjs +1 -1
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +91 -1
- package/dist/data/index.d.cts.map +1 -1
- package/dist/data/index.d.mts +91 -1
- package/dist/data/index.d.mts.map +1 -1
- package/dist/data/index.mjs +1 -1
- package/dist/data/index.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -144
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +94 -144
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/knownCodes-CI-vnoBO.cjs +2 -0
- package/dist/knownCodes-CI-vnoBO.cjs.map +1 -0
- package/dist/knownCodes-MkDSiR1j.mjs +2 -0
- package/dist/knownCodes-MkDSiR1j.mjs.map +1 -0
- package/dist/{reporters-DYNnh4O0.mjs → reporters-CZoC98-L.mjs} +1 -1
- package/dist/reporters-CZoC98-L.mjs.map +1 -0
- package/dist/reporters-Wob0oyD9.cjs +2 -0
- package/dist/reporters-Wob0oyD9.cjs.map +1 -0
- package/dist/types-BfYnmSHC.d.mts +115 -0
- package/dist/types-BfYnmSHC.d.mts.map +1 -0
- package/dist/types-C_5aOCZ1.d.cts +115 -0
- package/dist/types-C_5aOCZ1.d.cts.map +1 -0
- package/dist/utils/index.cjs +7 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +122 -0
- package/dist/utils/index.d.cts.map +1 -0
- package/dist/utils/index.d.mts +122 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +7 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +10 -1
- package/dist/citation-4bmWbhSK.d.cts.map +0 -1
- package/dist/citation-BVN0o8TJ.d.mts.map +0 -1
- package/dist/reporters-BclWimmk.cjs +0 -2
- package/dist/reporters-BclWimmk.cjs.map +0 -1
- package/dist/reporters-DYNnh4O0.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Extract, resolve, and annotate legal citations from court opinions and legal doc
|
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
|
-
- **Full citation extraction**: Case citations, statutes, journal articles, neutral citations, public laws, federal register
|
|
18
|
+
- **Full citation extraction**: Case citations, statutes (20 jurisdictions), constitutional citations (U.S. + 50 states), journal articles, neutral citations, public laws, federal register
|
|
19
19
|
- **Case name & full span**: Backward search extracts case names ("Smith v. Jones", "In re Smith"), `fullSpan` covers case name through closing parenthetical
|
|
20
20
|
- **Parallel citation linking**: Automatic detection and grouping of comma-separated citations sharing a parenthetical (e.g., "410 U.S. 113, 93 S. Ct. 705 (1973)")
|
|
21
21
|
- **Complex parentheticals**: Unified parser handles court+year, full dates (Jan. 15, 2020 / January 15, 2020 / 1/15/2020), disposition (en banc, per curiam), and chained parentheticals
|
|
@@ -24,7 +24,7 @@ Extract, resolve, and annotate legal citations from court opinions and legal doc
|
|
|
24
24
|
- **Citation annotation**: HTML markup with auto-escape XSS protection and position tracking
|
|
25
25
|
- **Bundle optimization**: Tree-shakeable exports, lazy-loaded reporter data, separate entry points
|
|
26
26
|
- **TypeScript native**: Discriminated unions, conditional types, type guards, full IntelliSense
|
|
27
|
-
- **Zero dependencies**: No runtime dependencies,
|
|
27
|
+
- **Zero dependencies**: No runtime dependencies, ~10KB gzipped core bundle
|
|
28
28
|
|
|
29
29
|
## Installation
|
|
30
30
|
|
|
@@ -75,6 +75,75 @@ citations.forEach(citation => {
|
|
|
75
75
|
})
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
### Statute Citations
|
|
79
|
+
|
|
80
|
+
Extract citations from 20 state and federal jurisdictions with subsection, et seq., and jurisdiction identification:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { extractCitations } from 'eyecite-ts'
|
|
84
|
+
|
|
85
|
+
const text = `
|
|
86
|
+
See 42 U.S.C. § 1983(a)(1) et seq.
|
|
87
|
+
Also Cal. Penal Code § 187.
|
|
88
|
+
And N.Y. Penal Law § 125.25(1)(a).
|
|
89
|
+
Compare 735 ILCS 5/2-1001.
|
|
90
|
+
`
|
|
91
|
+
const citations = extractCitations(text)
|
|
92
|
+
|
|
93
|
+
// Federal with subsections + et seq.
|
|
94
|
+
// { type: 'statute', title: 42, code: 'U.S.C.', section: '1983',
|
|
95
|
+
// subsection: '(a)(1)', jurisdiction: 'US', hasEtSeq: true, confidence: 1.0 }
|
|
96
|
+
|
|
97
|
+
// California named-code
|
|
98
|
+
// { type: 'statute', code: 'Penal', section: '187', jurisdiction: 'CA', confidence: 0.95 }
|
|
99
|
+
|
|
100
|
+
// New York named-code with subsections
|
|
101
|
+
// { type: 'statute', code: 'Penal Law', section: '125.25',
|
|
102
|
+
// subsection: '(1)(a)', jurisdiction: 'NY', confidence: 1.0 }
|
|
103
|
+
|
|
104
|
+
// Illinois chapter-act format
|
|
105
|
+
// { type: 'statute', title: 735, code: '5', section: '2-1001',
|
|
106
|
+
// jurisdiction: 'IL', confidence: 0.95 }
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Supported jurisdictions:**
|
|
110
|
+
|
|
111
|
+
| Family | Jurisdictions |
|
|
112
|
+
|--------|--------------|
|
|
113
|
+
| Federal | USC, CFR, prose ("section X of title Y") |
|
|
114
|
+
| Named-code | NY (21 laws), CA (29 codes), TX (29 codes), MD (36 articles), VA, AL, MA |
|
|
115
|
+
| Abbreviated-code | FL, OH, MI, UT, CO, WA, NC, GA, PA, IN, NJ, DE |
|
|
116
|
+
| Chapter-act | IL (ILCS) |
|
|
117
|
+
|
|
118
|
+
### Constitutional Citations
|
|
119
|
+
|
|
120
|
+
Extract U.S. and state constitutional citations with article, amendment, section, and clause parsing:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { extractCitations } from 'eyecite-ts'
|
|
124
|
+
|
|
125
|
+
const text = `
|
|
126
|
+
Under U.S. Const. amend. XIV, § 1, equal protection is guaranteed.
|
|
127
|
+
See also Cal. Const. art. I, § 7.
|
|
128
|
+
And U.S. Const. art. I, § 8, cl. 3.
|
|
129
|
+
`
|
|
130
|
+
const citations = extractCitations(text)
|
|
131
|
+
|
|
132
|
+
// U.S. amendment with section
|
|
133
|
+
// { type: 'constitutional', jurisdiction: 'US', amendment: 14,
|
|
134
|
+
// section: '1', confidence: 0.95 }
|
|
135
|
+
|
|
136
|
+
// California article with section
|
|
137
|
+
// { type: 'constitutional', jurisdiction: 'CA', article: 1,
|
|
138
|
+
// section: '7', confidence: 0.9 }
|
|
139
|
+
|
|
140
|
+
// Commerce Clause (article + section + clause)
|
|
141
|
+
// { type: 'constitutional', jurisdiction: 'US', article: 1,
|
|
142
|
+
// section: '8', clause: 3, confidence: 0.95 }
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Roman numerals (I–XXVII) are automatically parsed to integers. All 50 state abbreviations are supported.
|
|
146
|
+
|
|
78
147
|
### Async API
|
|
79
148
|
|
|
80
149
|
```typescript
|
|
@@ -370,9 +439,10 @@ All citation types use a discriminated union on the `type` field:
|
|
|
370
439
|
|
|
371
440
|
```typescript
|
|
372
441
|
import type {
|
|
373
|
-
Citation,
|
|
442
|
+
Citation, // Union of all 11 types
|
|
374
443
|
FullCaseCitation,
|
|
375
444
|
StatuteCitation,
|
|
445
|
+
ConstitutionalCitation,
|
|
376
446
|
JournalCitation,
|
|
377
447
|
NeutralCitation,
|
|
378
448
|
PublicLawCitation,
|
|
@@ -380,10 +450,10 @@ import type {
|
|
|
380
450
|
IdCitation,
|
|
381
451
|
SupraCitation,
|
|
382
452
|
ShortFormCaseCitation,
|
|
383
|
-
CitationOfType,
|
|
384
|
-
ExtractorMap,
|
|
385
|
-
FullCitation,
|
|
386
|
-
ShortFormCitation,
|
|
453
|
+
CitationOfType, // Extract subtype: CitationOfType<'case'> = FullCaseCitation
|
|
454
|
+
ExtractorMap, // Maps FullCitationType keys to citation subtypes
|
|
455
|
+
FullCitation, // Union of full citation types
|
|
456
|
+
ShortFormCitation, // Union of short-form types
|
|
387
457
|
} from 'eyecite-ts'
|
|
388
458
|
```
|
|
389
459
|
|
|
@@ -412,7 +482,7 @@ if (isCitationType(citation, 'statute')) {
|
|
|
412
482
|
switch (citation.type) {
|
|
413
483
|
case 'case': /* ... */ break
|
|
414
484
|
case 'statute': /* ... */ break
|
|
415
|
-
// ... all
|
|
485
|
+
// ... all 11 types ...
|
|
416
486
|
default: assertUnreachable(citation.type)
|
|
417
487
|
}
|
|
418
488
|
```
|
|
@@ -434,7 +504,7 @@ Three entry points for optimal tree-shaking:
|
|
|
434
504
|
|
|
435
505
|
| Entry Point | Import | Gzipped |
|
|
436
506
|
|------------|--------|---------|
|
|
437
|
-
| Core extraction | `eyecite-ts` |
|
|
507
|
+
| Core extraction | `eyecite-ts` | ~10 KB |
|
|
438
508
|
| Annotation | `eyecite-ts/annotate` | 0.7 KB |
|
|
439
509
|
| Reporter data | `eyecite-ts/data` | 86.5 KB (lazy-loaded) |
|
|
440
510
|
|
|
@@ -469,7 +539,7 @@ pnpm lint # Lint with Biome
|
|
|
469
539
|
pnpm format # Format with Biome
|
|
470
540
|
```
|
|
471
541
|
|
|
472
|
-
|
|
542
|
+
1030+ tests across 34 test files.
|
|
473
543
|
|
|
474
544
|
## License
|
|
475
545
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/annotate/annotate.ts"],"sourcesContent":["import type { Citation } from
|
|
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 useFullSpan = false, // Backward compatible 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 const skipped: Citation[] = []\n\n for (const citation of sorted) {\n // Determine which span to use\n let start: number\n let end: number\n\n if (useFullSpan && \"fullSpan\" in citation && citation.fullSpan) {\n // Full span mode: case name through parenthetical\n start = useCleanText ? citation.fullSpan.cleanStart : citation.fullSpan.originalStart\n end = useCleanText ? citation.fullSpan.cleanEnd : citation.fullSpan.originalEnd\n } else {\n // Default mode: core citation only\n start = useCleanText ? citation.span.cleanStart : citation.span.originalStart\n end = useCleanText ? citation.span.cleanEnd : citation.span.originalEnd\n }\n\n // Snap positions out of HTML tags when annotating original text\n if (!useCleanText) {\n const snapped = snapOutOfHtmlTags(result, start, end)\n if (snapped === null) {\n // Could not safely snap — skip this citation\n skipped.push(citation)\n continue\n }\n start = snapped.start\n end = snapped.end\n }\n\n let markup = \"\"\n\n if (callback) {\n // Callback mode: developer provides full logic\n const surrounding = text.substring(Math.max(0, start - 30), Math.min(text.length, end + 30))\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 * Check if a position falls inside an HTML tag (between `<` and `>`).\n * Returns the index of the opening `<` if inside a tag, otherwise -1.\n */\nfunction findContainingTag(text: string, pos: number): { tagStart: number; tagEnd: number } | null {\n // Search backwards from pos for '<' without encountering '>' first\n let i = pos - 1\n while (i >= 0) {\n if (text[i] === \">\") return null // Hit a tag close — we're outside\n if (text[i] === \"<\") {\n // Found opening '<' — now find the closing '>'\n let j = pos\n while (j < text.length) {\n if (text[j] === \">\") return { tagStart: i, tagEnd: j + 1 }\n j++\n }\n // Unclosed tag — treat as inside\n return { tagStart: i, tagEnd: text.length }\n }\n i--\n }\n return null\n}\n\n/**\n * Snap annotation start/end positions to avoid landing inside HTML tags.\n *\n * If a position falls inside an HTML tag, it is moved:\n * - Start position: snapped to before the tag's `<`\n * - End position: snapped to after the tag's `>`\n *\n * Returns null if the positions can't be safely adjusted (e.g., entirely\n * within a single tag).\n */\nfunction snapOutOfHtmlTags(\n text: string,\n start: number,\n end: number,\n): { start: number; end: number } | null {\n let snappedStart = start\n let snappedEnd = end\n\n const startTag = findContainingTag(text, start)\n if (startTag) {\n snappedStart = startTag.tagStart\n }\n\n const endTag = findContainingTag(text, end)\n if (endTag) {\n snappedEnd = endTag.tagEnd\n }\n\n // Sanity check: start must come before end\n if (snappedStart >= snappedEnd) return null\n\n return { start: snappedStart, end: snappedEnd }\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,cAAc,GACd,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,IAClB,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAY,EAAQ,CAE7B,IAAI,EACA,EAaJ,GAXI,GAAe,aAAc,GAAY,EAAS,UAEpD,EAAQ,EAAe,EAAS,SAAS,WAAa,EAAS,SAAS,cACxE,EAAM,EAAe,EAAS,SAAS,SAAW,EAAS,SAAS,cAGpE,EAAQ,EAAe,EAAS,KAAK,WAAa,EAAS,KAAK,cAChE,EAAM,EAAe,EAAS,KAAK,SAAW,EAAS,KAAK,aAI1D,CAAC,EAAc,CACjB,IAAM,EAAU,EAAkB,EAAQ,EAAO,EAAI,CACrD,GAAI,IAAY,KAAM,CAEpB,EAAQ,KAAK,EAAS,CACtB,SAEF,EAAQ,EAAQ,MAChB,EAAM,EAAQ,IAGhB,IAAI,EAAS,GAEb,GAAI,EAGF,EAAS,EAAS,EADE,EAAK,UAAU,KAAK,IAAI,EAAG,EAAQ,GAAG,CAAE,KAAK,IAAI,EAAK,OAAQ,EAAM,GAAG,CAAC,CACpD,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,UAAS,CAO/C,SAAS,EAAkB,EAAc,EAA0D,CAEjG,IAAI,EAAI,EAAM,EACd,KAAO,GAAK,GAAG,CACb,GAAI,EAAK,KAAO,IAAK,OAAO,KAC5B,GAAI,EAAK,KAAO,IAAK,CAEnB,IAAI,EAAI,EACR,KAAO,EAAI,EAAK,QAAQ,CACtB,GAAI,EAAK,KAAO,IAAK,MAAO,CAAE,SAAU,EAAG,OAAQ,EAAI,EAAG,CAC1D,IAGF,MAAO,CAAE,SAAU,EAAG,OAAQ,EAAK,OAAQ,CAE7C,IAEF,OAAO,KAaT,SAAS,EACP,EACA,EACA,EACuC,CACvC,IAAI,EAAe,EACf,EAAa,EAEX,EAAW,EAAkB,EAAM,EAAM,CAC3C,IACF,EAAe,EAAS,UAG1B,IAAM,EAAS,EAAkB,EAAM,EAAI,CAQ3C,OAPI,IACF,EAAa,EAAO,QAIlB,GAAgB,EAAmB,KAEhC,CAAE,MAAO,EAAc,IAAK,EAAY,CAiBjD,SAAS,EAAmB,EAAsB,CAChD,IAAM,EAA8B,CAClC,IAAK,QACL,IAAK,OACL,IAAK,OACL,IAAK,SACL,IAAK,QACL,IAAK,SACN,CACD,OAAO,EAAK,QAAQ,YAAc,GAAS,EAAI,GAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/annotate/annotate.ts"],"sourcesContent":["import type { Citation } from
|
|
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 useFullSpan = false, // Backward compatible 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 const skipped: Citation[] = []\n\n for (const citation of sorted) {\n // Determine which span to use\n let start: number\n let end: number\n\n if (useFullSpan && \"fullSpan\" in citation && citation.fullSpan) {\n // Full span mode: case name through parenthetical\n start = useCleanText ? citation.fullSpan.cleanStart : citation.fullSpan.originalStart\n end = useCleanText ? citation.fullSpan.cleanEnd : citation.fullSpan.originalEnd\n } else {\n // Default mode: core citation only\n start = useCleanText ? citation.span.cleanStart : citation.span.originalStart\n end = useCleanText ? citation.span.cleanEnd : citation.span.originalEnd\n }\n\n // Snap positions out of HTML tags when annotating original text\n if (!useCleanText) {\n const snapped = snapOutOfHtmlTags(result, start, end)\n if (snapped === null) {\n // Could not safely snap — skip this citation\n skipped.push(citation)\n continue\n }\n start = snapped.start\n end = snapped.end\n }\n\n let markup = \"\"\n\n if (callback) {\n // Callback mode: developer provides full logic\n const surrounding = text.substring(Math.max(0, start - 30), Math.min(text.length, end + 30))\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 * Check if a position falls inside an HTML tag (between `<` and `>`).\n * Returns the index of the opening `<` if inside a tag, otherwise -1.\n */\nfunction findContainingTag(text: string, pos: number): { tagStart: number; tagEnd: number } | null {\n // Search backwards from pos for '<' without encountering '>' first\n let i = pos - 1\n while (i >= 0) {\n if (text[i] === \">\") return null // Hit a tag close — we're outside\n if (text[i] === \"<\") {\n // Found opening '<' — now find the closing '>'\n let j = pos\n while (j < text.length) {\n if (text[j] === \">\") return { tagStart: i, tagEnd: j + 1 }\n j++\n }\n // Unclosed tag — treat as inside\n return { tagStart: i, tagEnd: text.length }\n }\n i--\n }\n return null\n}\n\n/**\n * Snap annotation start/end positions to avoid landing inside HTML tags.\n *\n * If a position falls inside an HTML tag, it is moved:\n * - Start position: snapped to before the tag's `<`\n * - End position: snapped to after the tag's `>`\n *\n * Returns null if the positions can't be safely adjusted (e.g., entirely\n * within a single tag).\n */\nfunction snapOutOfHtmlTags(\n text: string,\n start: number,\n end: number,\n): { start: number; end: number } | null {\n let snappedStart = start\n let snappedEnd = end\n\n const startTag = findContainingTag(text, start)\n if (startTag) {\n snappedStart = startTag.tagStart\n }\n\n const endTag = findContainingTag(text, end)\n if (endTag) {\n snappedEnd = endTag.tagEnd\n }\n\n // Sanity check: start must come before end\n if (snappedStart >= snappedEnd) return null\n\n return { start: snappedStart, end: snappedEnd }\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,cAAc,GACd,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,IAClB,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAY,EAAQ,CAE7B,IAAI,EACA,EAaJ,GAXI,GAAe,aAAc,GAAY,EAAS,UAEpD,EAAQ,EAAe,EAAS,SAAS,WAAa,EAAS,SAAS,cACxE,EAAM,EAAe,EAAS,SAAS,SAAW,EAAS,SAAS,cAGpE,EAAQ,EAAe,EAAS,KAAK,WAAa,EAAS,KAAK,cAChE,EAAM,EAAe,EAAS,KAAK,SAAW,EAAS,KAAK,aAI1D,CAAC,EAAc,CACjB,IAAM,EAAU,EAAkB,EAAQ,EAAO,EAAI,CACrD,GAAI,IAAY,KAAM,CAEpB,EAAQ,KAAK,EAAS,CACtB,SAEF,EAAQ,EAAQ,MAChB,EAAM,EAAQ,IAGhB,IAAI,EAAS,GAEb,GAAI,EAGF,EAAS,EAAS,EADE,EAAK,UAAU,KAAK,IAAI,EAAG,EAAQ,GAAG,CAAE,KAAK,IAAI,EAAK,OAAQ,EAAM,GAAG,CAAC,CACpD,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,UAAS,CAO/C,SAAS,EAAkB,EAAc,EAA0D,CAEjG,IAAI,EAAI,EAAM,EACd,KAAO,GAAK,GAAG,CACb,GAAI,EAAK,KAAO,IAAK,OAAO,KAC5B,GAAI,EAAK,KAAO,IAAK,CAEnB,IAAI,EAAI,EACR,KAAO,EAAI,EAAK,QAAQ,CACtB,GAAI,EAAK,KAAO,IAAK,MAAO,CAAE,SAAU,EAAG,OAAQ,EAAI,EAAG,CAC1D,IAGF,MAAO,CAAE,SAAU,EAAG,OAAQ,EAAK,OAAQ,CAE7C,IAEF,OAAO,KAaT,SAAS,EACP,EACA,EACA,EACuC,CACvC,IAAI,EAAe,EACf,EAAa,EAEX,EAAW,EAAkB,EAAM,EAAM,CAC3C,IACF,EAAe,EAAS,UAG1B,IAAM,EAAS,EAAkB,EAAM,EAAI,CAQ3C,OAPI,IACF,EAAa,EAAO,QAIlB,GAAgB,EAAmB,KAEhC,CAAE,MAAO,EAAc,IAAK,EAAY,CAiBjD,SAAS,EAAmB,EAAsB,CAChD,IAAM,EAA8B,CAClC,IAAK,QACL,IAAK,OACL,IAAK,OACL,IAAK,SACL,IAAK,QACL,IAAK,SACN,CACD,OAAO,EAAK,QAAQ,YAAc,GAAS,EAAI,GAAM"}
|
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
//#region src/extract/pincite.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Structured pincite information parsed from citation text.
|
|
4
|
+
*/
|
|
5
|
+
interface PinciteInfo {
|
|
6
|
+
/** Primary page number */
|
|
7
|
+
page: number;
|
|
8
|
+
/** End page for ranges: "570-75" → 575 */
|
|
9
|
+
endPage?: number;
|
|
10
|
+
/** Footnote number: "570 n.3" → 3 */
|
|
11
|
+
footnote?: number;
|
|
12
|
+
/** True if this is a page range */
|
|
13
|
+
isRange: boolean;
|
|
14
|
+
/** Original text before parsing */
|
|
15
|
+
raw: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a pincite string into structured components.
|
|
19
|
+
*
|
|
20
|
+
* Handles simple pages, ranges (with abbreviated end pages),
|
|
21
|
+
* footnote references, and "at" prefixes.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* parsePincite("570") // { page: 570, isRange: false, raw: "570" }
|
|
25
|
+
* parsePincite("570-75") // { page: 570, endPage: 575, isRange: true, raw: "570-75" }
|
|
26
|
+
* parsePincite("570 n.3") // { page: 570, footnote: 3, isRange: false, raw: "570 n.3" }
|
|
27
|
+
*
|
|
28
|
+
* @returns Parsed pincite info, or null if unparseable
|
|
29
|
+
*/
|
|
30
|
+
declare function parsePincite(raw: string): PinciteInfo | null;
|
|
31
|
+
//#endregion
|
|
1
32
|
//#region src/types/span.d.ts
|
|
2
33
|
/**
|
|
3
34
|
* Represents a text span with positions tracked through transformations.
|
|
@@ -43,7 +74,7 @@ interface TransformationMap {
|
|
|
43
74
|
/**
|
|
44
75
|
* Citation type discriminator for type-safe pattern matching.
|
|
45
76
|
*/
|
|
46
|
-
type CitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge" | "id" | "supra" | "shortFormCase";
|
|
77
|
+
type CitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge" | "constitutional" | "id" | "supra" | "shortFormCase";
|
|
47
78
|
/**
|
|
48
79
|
* Warning generated during citation parsing.
|
|
49
80
|
*/
|
|
@@ -61,6 +92,11 @@ interface Warning {
|
|
|
61
92
|
context?: string;
|
|
62
93
|
}
|
|
63
94
|
/**
|
|
95
|
+
* Introductory signal word classification for citation support level.
|
|
96
|
+
* Based on Bluebook signal categories (Rule 1.2).
|
|
97
|
+
*/
|
|
98
|
+
type CitationSignal = "see" | "see also" | "see generally" | "cf" | "but see" | "but cf" | "compare" | "accord" | "contra";
|
|
99
|
+
/**
|
|
64
100
|
* Base fields shared by all citation types.
|
|
65
101
|
*/
|
|
66
102
|
interface CitationBase {
|
|
@@ -84,6 +120,75 @@ interface CitationBase {
|
|
|
84
120
|
patternsChecked: number;
|
|
85
121
|
/** Warnings for malformed or ambiguous regions */
|
|
86
122
|
warnings?: Warning[];
|
|
123
|
+
/** Introductory signal word (e.g., "see", "see also", "but see") */
|
|
124
|
+
signal?: CitationSignal;
|
|
125
|
+
/** Group ID for string citations sharing the same proposition */
|
|
126
|
+
stringCitationGroupId?: string;
|
|
127
|
+
/** Position within the string citation group (0-indexed) */
|
|
128
|
+
stringCitationIndex?: number;
|
|
129
|
+
/** Total number of citations in this string citation group */
|
|
130
|
+
stringCitationGroupSize?: number;
|
|
131
|
+
/** Whether this citation appears in a footnote (only populated when detectFootnotes enabled) */
|
|
132
|
+
inFootnote?: boolean;
|
|
133
|
+
/** Footnote number, if applicable (only populated when detectFootnotes enabled) */
|
|
134
|
+
footnoteNumber?: number;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Court level and jurisdiction inferred from reporter series.
|
|
138
|
+
* Populated independently of the parenthetical-extracted `court` field.
|
|
139
|
+
*/
|
|
140
|
+
interface CourtInference {
|
|
141
|
+
/** Court level classification */
|
|
142
|
+
level: "supreme" | "appellate" | "trial" | "unknown";
|
|
143
|
+
/** Jurisdiction classification */
|
|
144
|
+
jurisdiction: "federal" | "state" | "unknown";
|
|
145
|
+
/** 2-letter state code, only for state-specific reporters */
|
|
146
|
+
state?: string;
|
|
147
|
+
/** Confidence score 0.0-1.0 (1.0 for unambiguous, 0.7 for regional multi-state) */
|
|
148
|
+
confidence: number;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Signal-word classification for explanatory parentheticals.
|
|
152
|
+
* Based on the leading gerund/verb form in the parenthetical text.
|
|
153
|
+
*/
|
|
154
|
+
type ParentheticalType = "holding" | "finding" | "stating" | "noting" | "explaining" | "quoting" | "citing" | "discussing" | "describing" | "recognizing" | "applying" | "rejecting" | "adopting" | "requiring" | "other";
|
|
155
|
+
/**
|
|
156
|
+
* An extracted explanatory parenthetical from a case citation.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* { text: "holding that X requires Y", type: "holding" }
|
|
161
|
+
* { text: "citing Doe v. City for the same proposition", type: "citing" }
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
interface Parenthetical {
|
|
165
|
+
/** Full text content between the parentheses (excluding parens themselves) */
|
|
166
|
+
text: string;
|
|
167
|
+
/** Signal-word classification based on leading gerund */
|
|
168
|
+
type: ParentheticalType;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Normalized subsequent history signal classification.
|
|
172
|
+
* Maps variant spellings (aff'd, affirmed) to canonical forms.
|
|
173
|
+
*/
|
|
174
|
+
type HistorySignal = "affirmed" | "reversed" | "cert_denied" | "cert_granted" | "overruled" | "vacated" | "remanded" | "modified" | "abrogated" | "superseded" | "disapproved" | "questioned" | "distinguished" | "withdrawn" | "reinstated";
|
|
175
|
+
/**
|
|
176
|
+
* A single subsequent history entry from a case citation.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* { signal: "affirmed", rawSignal: "aff'd", signalSpan: { ... }, order: 0 }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
interface SubsequentHistoryEntry {
|
|
184
|
+
/** Normalized signal classification */
|
|
185
|
+
signal: HistorySignal;
|
|
186
|
+
/** Raw signal text as it appeared in the document */
|
|
187
|
+
rawSignal: string;
|
|
188
|
+
/** Position of the signal text in the document */
|
|
189
|
+
signalSpan: Span;
|
|
190
|
+
/** Order in the history chain (0-based) */
|
|
191
|
+
order: number;
|
|
87
192
|
}
|
|
88
193
|
/**
|
|
89
194
|
* Full case citation (volume-reporter-page format).
|
|
@@ -98,7 +203,11 @@ interface FullCaseCitation extends CitationBase {
|
|
|
98
203
|
/** Page number — optional for blank page placeholder citations (e.g., "___" or "---") */
|
|
99
204
|
page?: number;
|
|
100
205
|
pincite?: number;
|
|
206
|
+
/** Structured pincite information (page, range, footnote) */
|
|
207
|
+
pinciteInfo?: PinciteInfo;
|
|
101
208
|
court?: string;
|
|
209
|
+
/** Normalized court string: spaces collapsed, trailing period ensured */
|
|
210
|
+
normalizedCourt?: string;
|
|
102
211
|
year?: number;
|
|
103
212
|
/** Normalized reporter abbreviation from reporters-db (e.g., "F.2d" vs "F. 2d") */
|
|
104
213
|
normalizedReporter?: string;
|
|
@@ -116,12 +225,29 @@ interface FullCaseCitation extends CitationBase {
|
|
|
116
225
|
reporter: string;
|
|
117
226
|
page: number;
|
|
118
227
|
}>;
|
|
119
|
-
/**
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Explanatory parentheticals following the citation.
|
|
230
|
+
* Only populated when explanatory content is found (not court/year/disposition).
|
|
231
|
+
* @example [{ text: "holding that X requires Y", type: "holding" }]
|
|
232
|
+
*/
|
|
233
|
+
parentheticals?: Parenthetical[];
|
|
234
|
+
/**
|
|
235
|
+
* Subsequent history entries for this citation.
|
|
236
|
+
* Each entry describes a procedural event (affirmed, reversed, etc.).
|
|
237
|
+
* Only populated on the parent (original) citation.
|
|
238
|
+
* @example [{ signal: "affirmed", rawSignal: "aff'd", signalSpan: {...}, order: 0 }]
|
|
239
|
+
*/
|
|
240
|
+
subsequentHistoryEntries?: SubsequentHistoryEntry[];
|
|
241
|
+
/**
|
|
242
|
+
* Back-pointer indicating this citation is a subsequent history citation.
|
|
243
|
+
* `index` is the parent's position in the results array returned by
|
|
244
|
+
* `extractCitations()` — it becomes invalid if the array is filtered or reordered.
|
|
245
|
+
* @example { index: 0, signal: "affirmed" }
|
|
246
|
+
*/
|
|
247
|
+
subsequentHistoryOf?: {
|
|
248
|
+
index: number;
|
|
249
|
+
signal: HistorySignal;
|
|
250
|
+
};
|
|
125
251
|
/**
|
|
126
252
|
* Date information in multiple formats.
|
|
127
253
|
* - iso: ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ssZ)
|
|
@@ -189,6 +315,18 @@ interface FullCaseCitation extends CitationBase {
|
|
|
189
315
|
*/
|
|
190
316
|
proceduralPrefix?: string;
|
|
191
317
|
/**
|
|
318
|
+
* Nominative (historical) reporter volume for early SCOTUS citations.
|
|
319
|
+
* Present only when citation includes a nominative parenthetical, e.g.,
|
|
320
|
+
* `67 U.S. (2 Black) 635` → nominativeVolume: 2
|
|
321
|
+
*/
|
|
322
|
+
nominativeVolume?: number;
|
|
323
|
+
/**
|
|
324
|
+
* Nominative (historical) reporter abbreviation for early SCOTUS citations.
|
|
325
|
+
* Present only when citation includes a nominative parenthetical, e.g.,
|
|
326
|
+
* `67 U.S. (2 Black) 635` → nominativeReporter: "Black"
|
|
327
|
+
*/
|
|
328
|
+
nominativeReporter?: string;
|
|
329
|
+
/**
|
|
192
330
|
* True when page position contains a blank placeholder ("___" or "---").
|
|
193
331
|
* Populated by Phase 5 (Blank Page support).
|
|
194
332
|
* When true, page field will be undefined and confidence reduced to 0.8.
|
|
@@ -200,17 +338,37 @@ interface FullCaseCitation extends CitationBase {
|
|
|
200
338
|
* @example "en banc", "per curiam"
|
|
201
339
|
*/
|
|
202
340
|
disposition?: string;
|
|
341
|
+
/**
|
|
342
|
+
* Court level/jurisdiction inferred from reporter series.
|
|
343
|
+
* Always populated independently of the parenthetical `court` field.
|
|
344
|
+
* Uses a curated static lookup table — does not depend on the reporter DB
|
|
345
|
+
* to preserve tree-shaking of the `eyecite-ts/data` entry point.
|
|
346
|
+
*/
|
|
347
|
+
inferredCourt?: CourtInference;
|
|
203
348
|
}
|
|
204
349
|
/**
|
|
205
350
|
* Statute citation (U.S. Code, state codes, etc.).
|
|
206
351
|
*
|
|
207
352
|
* @example "42 U.S.C. § 1983"
|
|
353
|
+
* @example "42 U.S.C. § 1983(a)(1) et seq."
|
|
208
354
|
*/
|
|
209
355
|
interface StatuteCitation extends CitationBase {
|
|
210
356
|
type: "statute";
|
|
211
357
|
title?: number;
|
|
212
358
|
code: string;
|
|
213
359
|
section: string;
|
|
360
|
+
/** Subsection/pincite chain, e.g. "(a)(1)(A)" */
|
|
361
|
+
subsection?: string;
|
|
362
|
+
/** 2-letter state code or "US" when unambiguously identified */
|
|
363
|
+
jurisdiction?: string;
|
|
364
|
+
/**
|
|
365
|
+
* Alias for subsection (eyecite-ts convention).
|
|
366
|
+
* Note: this is string (subsection chain), unlike FullCaseCitation.pincite which is number (page offset).
|
|
367
|
+
* The discriminated union on `type` ensures type safety at call sites.
|
|
368
|
+
*/
|
|
369
|
+
pincite?: string;
|
|
370
|
+
/** True when "et seq." follows the citation */
|
|
371
|
+
hasEtSeq?: boolean;
|
|
214
372
|
}
|
|
215
373
|
/**
|
|
216
374
|
* Journal citation (law review, legal periodical).
|
|
@@ -301,6 +459,26 @@ interface StatutesAtLargeCitation extends CitationBase {
|
|
|
301
459
|
year?: number;
|
|
302
460
|
}
|
|
303
461
|
/**
|
|
462
|
+
* Constitutional citation (U.S. or state constitution).
|
|
463
|
+
*
|
|
464
|
+
* @example "U.S. Const. art. III, § 2"
|
|
465
|
+
* @example "U.S. Const. amend. XIV, § 1"
|
|
466
|
+
* @example "Cal. Const. art. I, § 7"
|
|
467
|
+
*/
|
|
468
|
+
interface ConstitutionalCitation extends CitationBase {
|
|
469
|
+
type: "constitutional";
|
|
470
|
+
/** Jurisdiction code: "US", 2-letter state code, or undefined for bare "Const." */
|
|
471
|
+
jurisdiction?: string;
|
|
472
|
+
/** Article number (parsed from Roman numerals) — mutually exclusive with amendment */
|
|
473
|
+
article?: number;
|
|
474
|
+
/** Amendment number (parsed from Roman numerals) — mutually exclusive with article */
|
|
475
|
+
amendment?: number;
|
|
476
|
+
/** Section identifier (string to handle non-numeric like "3-a") */
|
|
477
|
+
section?: string;
|
|
478
|
+
/** Clause number (always numeric) */
|
|
479
|
+
clause?: number;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
304
482
|
* Id. citation (refers to immediately preceding citation).
|
|
305
483
|
*
|
|
306
484
|
* @example "Id."
|
|
@@ -353,16 +531,16 @@ interface ShortFormCaseCitation extends CitationBase {
|
|
|
353
531
|
* // ...
|
|
354
532
|
* }
|
|
355
533
|
*/
|
|
356
|
-
type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
|
|
534
|
+
type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation | ConstitutionalCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
|
|
357
535
|
/**
|
|
358
536
|
* Citation type discriminators grouped by category.
|
|
359
537
|
*/
|
|
360
|
-
type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge";
|
|
538
|
+
type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge" | "constitutional";
|
|
361
539
|
type ShortFormCitationType = "id" | "supra" | "shortFormCase";
|
|
362
540
|
/**
|
|
363
541
|
* Union of all full citation types (not short-form references).
|
|
364
542
|
*/
|
|
365
|
-
type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation;
|
|
543
|
+
type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation | ConstitutionalCitation;
|
|
366
544
|
/**
|
|
367
545
|
* Union of all short-form citation types (Id., supra, short-form case).
|
|
368
546
|
*/
|
|
@@ -385,5 +563,5 @@ type CitationOfType<T extends CitationType> = Extract<Citation, {
|
|
|
385
563
|
*/
|
|
386
564
|
type ExtractorMap = { [K in FullCitationType]: CitationOfType<K> };
|
|
387
565
|
//#endregion
|
|
388
|
-
export {
|
|
389
|
-
//# sourceMappingURL=citation-
|
|
566
|
+
export { PinciteInfo as A, StatuteCitation as C, Warning as D, SupraCitation as E, Span as O, ShortFormCitationType as S, SubsequentHistoryEntry as T, Parenthetical as _, CitationType as a, ShortFormCaseCitation as b, ExtractorMap as c, FullCitation as d, FullCitationType as f, NeutralCitation as g, JournalCitation as h, CitationSignal as i, parsePincite as j, TransformationMap as k, FederalRegisterCitation as l, IdCitation as m, CitationBase as n, ConstitutionalCitation as o, HistorySignal as p, CitationOfType as r, CourtInference as s, Citation as t, FullCaseCitation as u, ParentheticalType as v, StatutesAtLargeCitation as w, ShortFormCitation as x, PublicLawCitation as y };
|
|
567
|
+
//# sourceMappingURL=citation-BwXdJTA9.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citation-BwXdJTA9.d.mts","names":[],"sources":["../src/extract/pincite.ts","../src/types/span.ts","../src/types/citation.ts"],"mappings":"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"}
|