eyecite-ts 0.5.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 +38 -8
- 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-25ZydLsu.d.mts → citation-BwXdJTA9.d.mts} +177 -12
- package/dist/citation-BwXdJTA9.d.mts.map +1 -0
- package/dist/{citation-Cymq3pJ-.d.cts → citation-By8QXtGC.d.cts} +177 -12
- package/dist/citation-By8QXtGC.d.cts.map +1 -0
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +90 -90
- package/dist/data/index.d.cts.map +1 -1
- package/dist/data/index.d.mts +90 -90
- package/dist/data/index.d.mts.map +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 +110 -128
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +110 -128
- 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.map +1 -1
- package/dist/knownCodes-MkDSiR1j.mjs.map +1 -1
- 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-25ZydLsu.d.mts.map +0 -1
- package/dist/citation-Cymq3pJ-.d.cts.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 (20 jurisdictions), 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
|
|
@@ -115,6 +115,35 @@ const citations = extractCitations(text)
|
|
|
115
115
|
| Abbreviated-code | FL, OH, MI, UT, CO, WA, NC, GA, PA, IN, NJ, DE |
|
|
116
116
|
| Chapter-act | IL (ILCS) |
|
|
117
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
|
+
|
|
118
147
|
### Async API
|
|
119
148
|
|
|
120
149
|
```typescript
|
|
@@ -410,9 +439,10 @@ All citation types use a discriminated union on the `type` field:
|
|
|
410
439
|
|
|
411
440
|
```typescript
|
|
412
441
|
import type {
|
|
413
|
-
Citation,
|
|
442
|
+
Citation, // Union of all 11 types
|
|
414
443
|
FullCaseCitation,
|
|
415
444
|
StatuteCitation,
|
|
445
|
+
ConstitutionalCitation,
|
|
416
446
|
JournalCitation,
|
|
417
447
|
NeutralCitation,
|
|
418
448
|
PublicLawCitation,
|
|
@@ -420,10 +450,10 @@ import type {
|
|
|
420
450
|
IdCitation,
|
|
421
451
|
SupraCitation,
|
|
422
452
|
ShortFormCaseCitation,
|
|
423
|
-
CitationOfType,
|
|
424
|
-
ExtractorMap,
|
|
425
|
-
FullCitation,
|
|
426
|
-
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
|
|
427
457
|
} from 'eyecite-ts'
|
|
428
458
|
```
|
|
429
459
|
|
|
@@ -452,7 +482,7 @@ if (isCitationType(citation, 'statute')) {
|
|
|
452
482
|
switch (citation.type) {
|
|
453
483
|
case 'case': /* ... */ break
|
|
454
484
|
case 'statute': /* ... */ break
|
|
455
|
-
// ... all
|
|
485
|
+
// ... all 11 types ...
|
|
456
486
|
default: assertUnreachable(citation.type)
|
|
457
487
|
}
|
|
458
488
|
```
|
|
@@ -509,7 +539,7 @@ pnpm lint # Lint with Biome
|
|
|
509
539
|
pnpm format # Format with Biome
|
|
510
540
|
```
|
|
511
541
|
|
|
512
|
-
|
|
542
|
+
1030+ tests across 34 test files.
|
|
513
543
|
|
|
514
544
|
## License
|
|
515
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,6 +338,13 @@ 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.).
|
|
@@ -314,6 +459,26 @@ interface StatutesAtLargeCitation extends CitationBase {
|
|
|
314
459
|
year?: number;
|
|
315
460
|
}
|
|
316
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
|
+
/**
|
|
317
482
|
* Id. citation (refers to immediately preceding citation).
|
|
318
483
|
*
|
|
319
484
|
* @example "Id."
|
|
@@ -366,16 +531,16 @@ interface ShortFormCaseCitation extends CitationBase {
|
|
|
366
531
|
* // ...
|
|
367
532
|
* }
|
|
368
533
|
*/
|
|
369
|
-
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;
|
|
370
535
|
/**
|
|
371
536
|
* Citation type discriminators grouped by category.
|
|
372
537
|
*/
|
|
373
|
-
type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge";
|
|
538
|
+
type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge" | "constitutional";
|
|
374
539
|
type ShortFormCitationType = "id" | "supra" | "shortFormCase";
|
|
375
540
|
/**
|
|
376
541
|
* Union of all full citation types (not short-form references).
|
|
377
542
|
*/
|
|
378
|
-
type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation;
|
|
543
|
+
type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation | ConstitutionalCitation;
|
|
379
544
|
/**
|
|
380
545
|
* Union of all short-form citation types (Id., supra, short-form case).
|
|
381
546
|
*/
|
|
@@ -398,5 +563,5 @@ type CitationOfType<T extends CitationType> = Extract<Citation, {
|
|
|
398
563
|
*/
|
|
399
564
|
type ExtractorMap = { [K in FullCitationType]: CitationOfType<K> };
|
|
400
565
|
//#endregion
|
|
401
|
-
export {
|
|
402
|
-
//# 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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"}
|