eyecite-ts 0.2.0 → 0.3.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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # eyecite-ts
2
2
 
3
+ [![CI](https://github.com/medelman17/eyecite-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/medelman17/eyecite-ts/actions/workflows/ci.yml)
4
+ [![codecov](https://codecov.io/gh/medelman17/eyecite-ts/branch/main/graph/badge.svg)](https://codecov.io/gh/medelman17/eyecite-ts)
5
+ [![npm version](https://img.shields.io/npm/v/eyecite-ts.svg)](https://www.npmjs.com/package/eyecite-ts)
6
+ [![npm bundle size](https://img.shields.io/bundlephobia/minzip/eyecite-ts)](https://bundlephobia.com/package/eyecite-ts)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
8
+ [![Node.js](https://img.shields.io/node/v/eyecite-ts.svg)](https://nodejs.org)
9
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)
10
+ [![Zero Dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)](https://www.npmjs.com/package/eyecite-ts)
11
+
3
12
  TypeScript legal citation extraction library — port of Python [eyecite](https://github.com/freelawproject/eyecite).
4
13
 
5
14
  Extract, resolve, and annotate legal citations from court opinions and legal documents with zero runtime dependencies.
@@ -322,13 +331,13 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details.
322
331
  ## Development
323
332
 
324
333
  ```bash
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
334
+ pnpm install # Install dependencies
335
+ pnpm test # Run tests (vitest, watch mode)
336
+ pnpm exec vitest run # Run tests once
337
+ pnpm typecheck # Type-check with tsc
338
+ pnpm build # Build (ESM + CJS + DTS)
339
+ pnpm lint # Lint with Biome
340
+ pnpm format # Format with Biome
332
341
  ```
333
342
 
334
343
  304 tests, 97% statement coverage, 91% branch coverage.
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,n,r={}){let{useCleanText:i=!1,autoEscape:a=!0,template:o,callback:s}=r,c=[...n].sort((e,t)=>{let n=i?e.span.cleanStart:e.span.originalStart;return(i?t.span.cleanStart:t.span.originalStart)-n}),l=e,u=new Map;for(let n of c){let r=i?n.span.cleanStart:n.span.originalStart,c=i?n.span.cleanEnd:n.span.originalEnd,d=``;if(s)d=s(n,e.substring(Math.max(0,r-30),Math.min(e.length,c+30)));else if(o){let e=l.substring(r,c),n=a?t(e):e;d=o.before+n+o.after}else continue;l=l.slice(0,r)+d+l.slice(c),u.set(r,r)}return{text:l,positionMap:u,skipped:[]}}function t(e){let t={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`,"/":`&#x2F;`};return e.replace(/[&<>"'\/]/g,e=>t[e])}exports.annotate=e;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,t,i={}){let{useCleanText:a=!1,autoEscape:o=!0,template:s,callback:c}=i,l=[...t].sort((e,t)=>{let n=a?e.span.cleanStart:e.span.originalStart;return(a?t.span.cleanStart:t.span.originalStart)-n}),u=e,d=new Map,f=[];for(let t of l){let i=a?t.span.cleanStart:t.span.originalStart,l=a?t.span.cleanEnd:t.span.originalEnd;if(!a){let e=n(u,i,l);if(e===null){f.push(t);continue}i=e.start,l=e.end}let p=``;if(c)p=c(t,e.substring(Math.max(0,i-30),Math.min(e.length,l+30)));else if(s){let e=u.substring(i,l),t=o?r(e):e;p=s.before+t+s.after}else continue;u=u.slice(0,i)+p+u.slice(l),d.set(i,i)}return{text:u,positionMap:d,skipped:f}}function t(e,t){let n=t-1;for(;n>=0;){if(e[n]===`>`)return null;if(e[n]===`<`){let r=t;for(;r<e.length;){if(e[r]===`>`)return{tagStart:n,tagEnd:r+1};r++}return{tagStart:n,tagEnd:e.length}}n--}return null}function n(e,n,r){let i=n,a=r,o=t(e,n);o&&(i=o.tagStart);let s=t(e,r);return s&&(a=s.tagEnd),i>=a?null:{start:i,end:a}}function r(e){let t={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`,"/":`&#x2F;`};return e.replace(/[&<>"'/]/g,e=>t[e])}exports.annotate=e;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -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<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 * - `&` → `&amp;`\n * - `<` → `&lt;`\n * - `>` → `&gt;`\n * - `\"` → `&quot;`\n * - `'` → `&#39;`\n * - `/` → `&#x2F;`\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 '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\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
+ {"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 const skipped: Citation[] = []\n\n for (const citation of sorted) {\n let start = useCleanText ? citation.span.cleanStart : citation.span.originalStart\n let end = useCleanText ? citation.span.cleanEnd : citation.span.originalEnd\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(\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 * 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 * - `&` → `&amp;`\n * - `<` → `&lt;`\n * - `>` → `&gt;`\n * - `\"` → `&quot;`\n * - `'` → `&#39;`\n * - `/` → `&#x2F;`\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 '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\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,IAClB,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAY,EAAQ,CAC7B,IAAI,EAAQ,EAAe,EAAS,KAAK,WAAa,EAAS,KAAK,cAChE,EAAM,EAAe,EAAS,KAAK,SAAW,EAAS,KAAK,YAGhE,GAAI,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,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,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,4 +1,4 @@
1
- import { t as Citation } from "../citation-BhJJj_AZ.cjs";
1
+ import { t as Citation } from "../citation-qKSc_Myj.cjs";
2
2
 
3
3
  //#region src/annotate/types.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Citation } from "../citation-FJ10UFM7.mjs";
1
+ import { t as Citation } from "../citation-DAyM8kNA.mjs";
2
2
 
3
3
  //#region src/annotate/types.d.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- function e(e,n,r={}){let{useCleanText:i=!1,autoEscape:a=!0,template:o,callback:s}=r,c=[...n].sort((e,t)=>{let n=i?e.span.cleanStart:e.span.originalStart;return(i?t.span.cleanStart:t.span.originalStart)-n}),l=e,u=new Map;for(let n of c){let r=i?n.span.cleanStart:n.span.originalStart,c=i?n.span.cleanEnd:n.span.originalEnd,d=``;if(s)d=s(n,e.substring(Math.max(0,r-30),Math.min(e.length,c+30)));else if(o){let e=l.substring(r,c),n=a?t(e):e;d=o.before+n+o.after}else continue;l=l.slice(0,r)+d+l.slice(c),u.set(r,r)}return{text:l,positionMap:u,skipped:[]}}function t(e){let t={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`,"/":`&#x2F;`};return e.replace(/[&<>"'\/]/g,e=>t[e])}export{e as annotate};
1
+ function e(e,t,i={}){let{useCleanText:a=!1,autoEscape:o=!0,template:s,callback:c}=i,l=[...t].sort((e,t)=>{let n=a?e.span.cleanStart:e.span.originalStart;return(a?t.span.cleanStart:t.span.originalStart)-n}),u=e,d=new Map,f=[];for(let t of l){let i=a?t.span.cleanStart:t.span.originalStart,l=a?t.span.cleanEnd:t.span.originalEnd;if(!a){let e=n(u,i,l);if(e===null){f.push(t);continue}i=e.start,l=e.end}let p=``;if(c)p=c(t,e.substring(Math.max(0,i-30),Math.min(e.length,l+30)));else if(s){let e=u.substring(i,l),t=o?r(e):e;p=s.before+t+s.after}else continue;u=u.slice(0,i)+p+u.slice(l),d.set(i,i)}return{text:u,positionMap:d,skipped:f}}function t(e,t){let n=t-1;for(;n>=0;){if(e[n]===`>`)return null;if(e[n]===`<`){let r=t;for(;r<e.length;){if(e[r]===`>`)return{tagStart:n,tagEnd:r+1};r++}return{tagStart:n,tagEnd:e.length}}n--}return null}function n(e,n,r){let i=n,a=r,o=t(e,n);o&&(i=o.tagStart);let s=t(e,r);return s&&(a=s.tagEnd),i>=a?null:{start:i,end:a}}function r(e){let t={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`,"/":`&#x2F;`};return e.replace(/[&<>"'/]/g,e=>t[e])}export{e as annotate};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -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<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 * - `&` → `&amp;`\n * - `<` → `&lt;`\n * - `>` → `&gt;`\n * - `\"` → `&quot;`\n * - `'` → `&#39;`\n * - `/` → `&#x2F;`\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 '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\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"}
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 const skipped: Citation[] = []\n\n for (const citation of sorted) {\n let start = useCleanText ? citation.span.cleanStart : citation.span.originalStart\n let end = useCleanText ? citation.span.cleanEnd : citation.span.originalEnd\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(\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 * 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 * - `&` → `&amp;`\n * - `<` → `&lt;`\n * - `>` → `&gt;`\n * - `\"` → `&quot;`\n * - `'` → `&#39;`\n * - `/` → `&#x2F;`\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 '&': '&amp;',\n '<': '&lt;',\n '>': '&gt;',\n '\"': '&quot;',\n \"'\": '&#39;',\n '/': '&#x2F;',\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,IAClB,EAAsB,EAAE,CAE9B,IAAK,IAAM,KAAY,EAAQ,CAC7B,IAAI,EAAQ,EAAe,EAAS,KAAK,WAAa,EAAS,KAAK,cAChE,EAAM,EAAe,EAAS,KAAK,SAAW,EAAS,KAAK,YAGhE,GAAI,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,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,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"}
@@ -43,7 +43,7 @@ interface TransformationMap {
43
43
  /**
44
44
  * Citation type discriminator for type-safe pattern matching.
45
45
  */
46
- type CitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "id" | "supra" | "shortFormCase";
46
+ type CitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge" | "id" | "supra" | "shortFormCase";
47
47
  /**
48
48
  * Warning generated during citation parsing.
49
49
  */
@@ -93,7 +93,7 @@ interface CitationBase {
93
93
  */
94
94
  interface FullCaseCitation extends CitationBase {
95
95
  type: "case";
96
- volume: number;
96
+ volume: number | string;
97
97
  reporter: string;
98
98
  page: number;
99
99
  pincite?: number;
@@ -103,7 +103,7 @@ interface FullCaseCitation extends CitationBase {
103
103
  normalizedReporter?: string;
104
104
  /** Parallel citations for same case in different reporters */
105
105
  parallelCitations?: Array<{
106
- volume: number;
106
+ volume: number | string;
107
107
  reporter: string;
108
108
  page: number;
109
109
  }>;
@@ -131,7 +131,7 @@ interface FullCaseCitation extends CitationBase {
131
131
  * Used when reporter abbreviation matches multiple reporters or format is unclear.
132
132
  */
133
133
  possibleInterpretations?: Array<{
134
- volume: number;
134
+ volume: number | string;
135
135
  reporter: string;
136
136
  page: number;
137
137
  confidence: number;
@@ -163,8 +163,8 @@ interface JournalCitation extends CitationBase {
163
163
  author?: string;
164
164
  /** Article title (if extracted) */
165
165
  title?: string;
166
- /** Volume number */
167
- volume?: number;
166
+ /** Volume number (string for hyphenated volumes like "1984-1") */
167
+ volume?: number | string;
168
168
  /** Full journal name */
169
169
  journal: string;
170
170
  /** Standard journal abbreviation (e.g., "Harv. L. Rev.") */
@@ -221,7 +221,17 @@ interface PublicLawCitation extends CitationBase {
221
221
  interface FederalRegisterCitation extends CitationBase {
222
222
  type: "federalRegister";
223
223
  /** Federal Register volume */
224
- volume: number;
224
+ volume: number | string;
225
+ /** Page number */
226
+ page: number;
227
+ /** Publication year (if extracted) */
228
+ year?: number;
229
+ }
230
+ /** Citation to the Statutes at Large (session law compilation) */
231
+ interface StatutesAtLargeCitation extends CitationBase {
232
+ type: "statutesAtLarge";
233
+ /** Statutes at Large volume */
234
+ volume: number | string;
225
235
  /** Page number */
226
236
  page: number;
227
237
  /** Publication year (if extracted) */
@@ -258,7 +268,7 @@ interface SupraCitation extends CitationBase {
258
268
  */
259
269
  interface ShortFormCaseCitation extends CitationBase {
260
270
  type: "shortFormCase";
261
- volume: number;
271
+ volume: number | string;
262
272
  reporter: string;
263
273
  page?: number;
264
274
  pincite?: number;
@@ -280,16 +290,16 @@ interface ShortFormCaseCitation extends CitationBase {
280
290
  * // ...
281
291
  * }
282
292
  */
283
- type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
293
+ type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
284
294
  /**
285
295
  * Citation type discriminators grouped by category.
286
296
  */
287
- type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister";
297
+ type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge";
288
298
  type ShortFormCitationType = "id" | "supra" | "shortFormCase";
289
299
  /**
290
300
  * Union of all full citation types (not short-form references).
291
301
  */
292
- type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation;
302
+ type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation;
293
303
  /**
294
304
  * Union of all short-form citation types (Id., supra, short-form case).
295
305
  */
@@ -312,5 +322,5 @@ type CitationOfType<T extends CitationType> = Extract<Citation, {
312
322
  */
313
323
  type ExtractorMap = { [K in FullCitationType]: CitationOfType<K> };
314
324
  //#endregion
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
325
+ export { TransformationMap as S, StatuteCitation as _, ExtractorMap as a, Warning 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, StatutesAtLargeCitation as v, Span as x, SupraCitation as y };
326
+ //# sourceMappingURL=citation-DAyM8kNA.d.mts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"citation-DAyM8kNA.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;;;AAwCF;;;;;;UA7BiB,iBAAA,SAA0B,YAAA;EACzC,IAAA;;EAEA,QAAA;EAiCA;EA/BA,SAAA;EAwCe;EAtCf,KAAA;AAAA;;;;;;AAiDF;;;UAtCiB,uBAAA,SAAgC,YAAA;EAC/C,IAAA;;EAEA,MAAA;;EAEA,IAAA;EAsCA;EApCA,IAAA;AAAA;;UAIe,uBAAA,SAAgC,YAAA;EAC/C,IAAA;;EAEA,MAAA;;EAEA,IAAA;;EAEA,IAAA;AAAA;AA2DF;;;;;;AAAA,UAlDiB,UAAA,SAAmB,YAAA;EAClC,IAAA;EACA,OAAA;AAAA;;;;;;;UASe,aAAA,SAAsB,YAAA;EACrC,IAAA;;EAEA,SAAA;;EAEA,OAAA;AAAA;;;;;AAiDF;;UAxCiB,qBAAA,SAA8B,YAAA;EAC7C,IAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,OAAA;AAAA;;AAyCF;;;;;;;;;;;;;;;;KArBY,QAAA,GACR,gBAAA,GACA,eAAA,GACA,eAAA,GACA,eAAA,GACA,iBAAA,GACA,uBAAA,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,GAA0B,uBAAA;;;;KAKtI,iBAAA,GAAoB,UAAA,GAAa,aAAA,GAAgB,qBAAA;;;;;AAW7D;;;;;KAAY,cAAA,WAAyB,YAAA,IAAgB,OAAA,CAAQ,QAAA;EAAY,IAAA,EAAM,CAAA;AAAA;;;;;KAMnE,YAAA,WACJ,gBAAA,GAAmB,cAAA,CAAe,CAAA"}
@@ -43,7 +43,7 @@ interface TransformationMap {
43
43
  /**
44
44
  * Citation type discriminator for type-safe pattern matching.
45
45
  */
46
- type CitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "id" | "supra" | "shortFormCase";
46
+ type CitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge" | "id" | "supra" | "shortFormCase";
47
47
  /**
48
48
  * Warning generated during citation parsing.
49
49
  */
@@ -93,7 +93,7 @@ interface CitationBase {
93
93
  */
94
94
  interface FullCaseCitation extends CitationBase {
95
95
  type: "case";
96
- volume: number;
96
+ volume: number | string;
97
97
  reporter: string;
98
98
  page: number;
99
99
  pincite?: number;
@@ -103,7 +103,7 @@ interface FullCaseCitation extends CitationBase {
103
103
  normalizedReporter?: string;
104
104
  /** Parallel citations for same case in different reporters */
105
105
  parallelCitations?: Array<{
106
- volume: number;
106
+ volume: number | string;
107
107
  reporter: string;
108
108
  page: number;
109
109
  }>;
@@ -131,7 +131,7 @@ interface FullCaseCitation extends CitationBase {
131
131
  * Used when reporter abbreviation matches multiple reporters or format is unclear.
132
132
  */
133
133
  possibleInterpretations?: Array<{
134
- volume: number;
134
+ volume: number | string;
135
135
  reporter: string;
136
136
  page: number;
137
137
  confidence: number;
@@ -163,8 +163,8 @@ interface JournalCitation extends CitationBase {
163
163
  author?: string;
164
164
  /** Article title (if extracted) */
165
165
  title?: string;
166
- /** Volume number */
167
- volume?: number;
166
+ /** Volume number (string for hyphenated volumes like "1984-1") */
167
+ volume?: number | string;
168
168
  /** Full journal name */
169
169
  journal: string;
170
170
  /** Standard journal abbreviation (e.g., "Harv. L. Rev.") */
@@ -221,7 +221,17 @@ interface PublicLawCitation extends CitationBase {
221
221
  interface FederalRegisterCitation extends CitationBase {
222
222
  type: "federalRegister";
223
223
  /** Federal Register volume */
224
- volume: number;
224
+ volume: number | string;
225
+ /** Page number */
226
+ page: number;
227
+ /** Publication year (if extracted) */
228
+ year?: number;
229
+ }
230
+ /** Citation to the Statutes at Large (session law compilation) */
231
+ interface StatutesAtLargeCitation extends CitationBase {
232
+ type: "statutesAtLarge";
233
+ /** Statutes at Large volume */
234
+ volume: number | string;
225
235
  /** Page number */
226
236
  page: number;
227
237
  /** Publication year (if extracted) */
@@ -258,7 +268,7 @@ interface SupraCitation extends CitationBase {
258
268
  */
259
269
  interface ShortFormCaseCitation extends CitationBase {
260
270
  type: "shortFormCase";
261
- volume: number;
271
+ volume: number | string;
262
272
  reporter: string;
263
273
  page?: number;
264
274
  pincite?: number;
@@ -280,16 +290,16 @@ interface ShortFormCaseCitation extends CitationBase {
280
290
  * // ...
281
291
  * }
282
292
  */
283
- type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
293
+ type Citation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation | IdCitation | SupraCitation | ShortFormCaseCitation;
284
294
  /**
285
295
  * Citation type discriminators grouped by category.
286
296
  */
287
- type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister";
297
+ type FullCitationType = "case" | "statute" | "journal" | "neutral" | "publicLaw" | "federalRegister" | "statutesAtLarge";
288
298
  type ShortFormCitationType = "id" | "supra" | "shortFormCase";
289
299
  /**
290
300
  * Union of all full citation types (not short-form references).
291
301
  */
292
- type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation;
302
+ type FullCitation = FullCaseCitation | StatuteCitation | JournalCitation | NeutralCitation | PublicLawCitation | FederalRegisterCitation | StatutesAtLargeCitation;
293
303
  /**
294
304
  * Union of all short-form citation types (Id., supra, short-form case).
295
305
  */
@@ -312,5 +322,5 @@ type CitationOfType<T extends CitationType> = Extract<Citation, {
312
322
  */
313
323
  type ExtractorMap = { [K in FullCitationType]: CitationOfType<K> };
314
324
  //#endregion
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
325
+ export { TransformationMap as S, StatuteCitation as _, ExtractorMap as a, Warning 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, StatutesAtLargeCitation as v, Span as x, SupraCitation as y };
326
+ //# sourceMappingURL=citation-qKSc_Myj.d.cts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"citation-qKSc_Myj.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;;;AAwCF;;;;;;UA7BiB,iBAAA,SAA0B,YAAA;EACzC,IAAA;;EAEA,QAAA;EAiCA;EA/BA,SAAA;EAwCe;EAtCf,KAAA;AAAA;;;;;;AAiDF;;;UAtCiB,uBAAA,SAAgC,YAAA;EAC/C,IAAA;;EAEA,MAAA;;EAEA,IAAA;EAsCA;EApCA,IAAA;AAAA;;UAIe,uBAAA,SAAgC,YAAA;EAC/C,IAAA;;EAEA,MAAA;;EAEA,IAAA;;EAEA,IAAA;AAAA;AA2DF;;;;;;AAAA,UAlDiB,UAAA,SAAmB,YAAA;EAClC,IAAA;EACA,OAAA;AAAA;;;;;;;UASe,aAAA,SAAsB,YAAA;EACrC,IAAA;;EAEA,SAAA;;EAEA,OAAA;AAAA;;;;;AAiDF;;UAxCiB,qBAAA,SAA8B,YAAA;EAC7C,IAAA;EACA,MAAA;EACA,QAAA;EACA,IAAA;EACA,OAAA;AAAA;;AAyCF;;;;;;;;;;;;;;;;KArBY,QAAA,GACR,gBAAA,GACA,eAAA,GACA,eAAA,GACA,eAAA,GACA,iBAAA,GACA,uBAAA,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,GAA0B,uBAAA;;;;KAKtI,iBAAA,GAAoB,UAAA,GAAa,aAAA,GAAgB,qBAAA;;;;;AAW7D;;;;;KAAY,cAAA,WAAyB,YAAA,IAAgB,OAAA,CAAQ,QAAA;EAAY,IAAA,EAAM,CAAA;AAAA;;;;;KAMnE,YAAA,WACJ,gBAAA,GAAmB,cAAA,CAAe,CAAA"}
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=null;async function t(){if(e)return e;let t=await import(`../../data/reporters.json`,{assert:{type:`json`}}),n=new Map,r=[],i=t.default||t;for(let[e,t]of Object.entries(i))for(let e of t){r.push(e);for(let t of Object.keys(e.editions)){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r).push(e)}for(let[t,r]of Object.entries(e.variations||{})){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r).push(e)}}return e={byAbbreviation:n,all:r},e}function n(){return e}async function r(e){return(await t()).byAbbreviation.get(e.toLowerCase())??[]}exports.findReportersByAbbreviation=r,exports.getReportersSync=n,exports.loadReporters=t;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=null;async function t(){if(e)return e;let t=await import(`../../data/reporters.json`,{assert:{type:`json`}}),n=new Map,r=[],i=t.default||t;for(let[e,t]of Object.entries(i))for(let e of t){r.push(e);for(let t of Object.keys(e.editions)){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r)?.push(e)}for(let[t,r]of Object.entries(e.variations||{})){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r)?.push(e)}}return e={byAbbreviation:n,all:r},e}function n(){return e}async function r(e){return(await t()).byAbbreviation.get(e.toLowerCase())??[]}exports.findReportersByAbbreviation=r,exports.getReportersSync=n,exports.loadReporters=t;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/data/reporters.ts"],"sourcesContent":["/**\n * Reporter database integration for citation validation\n *\n * This module provides lazy-loadable access to the reporters-db database,\n * containing 1200+ court reporters with variant forms. The library works\n * in degraded mode (pattern-based extraction only) if reporters are not loaded.\n *\n * @example\n * // Degraded mode: extraction works without reporter data\n * const citations = await extract(text)\n *\n * @example\n * // Full mode: load reporters for validation\n * await loadReporters()\n * const citations = await extract(text) // Now with reporter validation\n */\n\n/**\n * Edition entry from reporters-db\n *\n * Represents a specific edition of a reporter with start/end dates.\n */\nexport interface ReporterEdition {\n /** Start date in ISO 8601 format */\n start: string | null\n /** End date in ISO 8601 format (null if ongoing) */\n end: string | null\n}\n\n/**\n * Reporter entry from reporters-db\n *\n * Represents a single court reporter with all metadata needed for\n * citation validation and enrichment.\n *\n * Note: The reporters-db structure has the actual data; this interface\n * represents it flexibly to handle all variations in the JSON.\n */\nexport interface ReporterEntry {\n /** Full reporter name (e.g., \"Federal Reporter\") */\n name: string\n /** Citation type: state, federal, specialty, neutral, state_regional, etc. */\n cite_type: string\n /** Editions keyed by abbreviation (e.g., {\"F.2d\": {...}, \"F.3d\": {...}}) */\n editions: Record<string, ReporterEdition>\n /** Variant forms mapped to canonical form (e.g., {\"F. 2d\": \"F.2d\"}) */\n variations?: Record<string, string | undefined>\n /** MLZ jurisdiction identifiers (optional) */\n mlz_jurisdiction?: string[]\n /** Publisher (optional) */\n publisher?: string\n /** Notes (optional) */\n notes?: string\n}\n\n/**\n * In-memory reporter database with fast O(1) lookup\n *\n * Uses Map-based indexing for case-insensitive abbreviation lookup.\n * All variant forms are indexed to support fuzzy matching.\n */\nexport interface ReportersDatabase {\n /** Fast O(1) lookup by abbreviation (lowercase normalized keys) */\n byAbbreviation: Map<string, ReporterEntry[]>\n /** All reporters (for iteration/filtering) */\n all: ReporterEntry[]\n}\n\n/**\n * Cached database instance (null until loadReporters() called)\n */\nlet cached: ReportersDatabase | null = null\n\n/**\n * Load reporter database asynchronously with lazy loading\n *\n * Dynamic import prevents loading 1200+ reporters until explicitly requested.\n * Result is cached after first load for subsequent calls.\n *\n * @returns Promise resolving to indexed reporter database\n *\n * @example\n * const db = await loadReporters()\n * const reporters = db.byAbbreviation.get('f.2d') // Fast O(1) lookup\n */\nexport async function loadReporters(): Promise<ReportersDatabase> {\n if (cached) return cached\n\n // Dynamic import prevents loading until requested (keeps core bundle small)\n const data = await import(\"../../data/reporters.json\", {\n assert: { type: \"json\" },\n })\n\n const byAbbreviation = new Map<string, ReporterEntry[]>()\n const all: ReporterEntry[] = []\n\n // reporters.json structure: { \"A.\": [...], \"F.2d\": [...], ... }\n const reportersData = (data.default || data) as Record<\n string,\n ReporterEntry[]\n >\n\n // Build fast lookup index with lowercase normalization\n for (const [canonicalAbbr, reporters] of Object.entries(reportersData)) {\n for (const reporter of reporters) {\n all.push(reporter)\n\n // Index by all edition abbreviations\n for (const editionAbbr of Object.keys(reporter.editions)) {\n const key = editionAbbr.toLowerCase()\n if (!byAbbreviation.has(key)) {\n byAbbreviation.set(key, [])\n }\n byAbbreviation.get(key)!.push(reporter)\n }\n\n // Index all variations for fuzzy matching\n for (const [variant, canonical] of Object.entries(\n reporter.variations || {},\n )) {\n const variantKey = variant.toLowerCase()\n if (!byAbbreviation.has(variantKey)) {\n byAbbreviation.set(variantKey, [])\n }\n byAbbreviation.get(variantKey)!.push(reporter)\n }\n }\n }\n\n cached = {\n byAbbreviation,\n all,\n }\n return cached\n}\n\n/**\n * Get cached reporter database synchronously (degraded mode support)\n *\n * Returns null if reporters not loaded yet. This enables the library to\n * work in degraded mode without reporter validation.\n *\n * @returns Cached database or null if not loaded\n *\n * @example\n * const db = getReportersSync()\n * if (db) {\n * // Full mode: validate citations\n * } else {\n * // Degraded mode: extract without validation\n * }\n */\nexport function getReportersSync(): ReportersDatabase | null {\n return cached\n}\n\n/**\n * Find reporters by abbreviation (case-insensitive)\n *\n * Loads reporter database if not already loaded. Returns all reporters\n * matching the abbreviation (including variant forms).\n *\n * @param abbr - Reporter abbreviation to look up\n * @returns Promise resolving to matching reporters (empty array if none)\n *\n * @example\n * const reporters = await findReportersByAbbreviation('F.2d')\n * // [{ abbreviation: 'F.2d', name: 'Federal Reporter, Second Series', ... }]\n *\n * @example\n * const unknown = await findReportersByAbbreviation('NONEXISTENT')\n * // [] (empty array, not error)\n */\nexport async function findReportersByAbbreviation(\n abbr: string,\n): Promise<ReporterEntry[]> {\n const db = await loadReporters()\n return db.byAbbreviation.get(abbr.toLowerCase()) ?? []\n}\n"],"mappings":"mEAuEA,IAAI,EAAmC,KAcvC,eAAsB,GAA4C,CAChE,GAAI,EAAQ,OAAO,EAGnB,IAAM,EAAO,MAAM,OAAO,4BAA6B,CACrD,OAAQ,CAAE,KAAM,OAAQ,CACzB,EAEK,EAAiB,IAAI,IACrB,EAAuB,EAAE,CAGzB,EAAiB,EAAK,SAAW,EAMvC,IAAK,GAAM,CAAC,EAAe,KAAc,OAAO,QAAQ,EAAc,CACpE,IAAK,IAAM,KAAY,EAAW,CAChC,EAAI,KAAK,EAAS,CAGlB,IAAK,IAAM,KAAe,OAAO,KAAK,EAAS,SAAS,CAAE,CACxD,IAAM,EAAM,EAAY,aAAa,CAChC,EAAe,IAAI,EAAI,EAC1B,EAAe,IAAI,EAAK,EAAE,CAAC,CAE7B,EAAe,IAAI,EAAI,CAAE,KAAK,EAAS,CAIzC,IAAK,GAAM,CAAC,EAAS,KAAc,OAAO,QACxC,EAAS,YAAc,EAAE,CAC1B,CAAE,CACD,IAAM,EAAa,EAAQ,aAAa,CACnC,EAAe,IAAI,EAAW,EACjC,EAAe,IAAI,EAAY,EAAE,CAAC,CAEpC,EAAe,IAAI,EAAW,CAAE,KAAK,EAAS,EASpD,MAJA,GAAS,CACP,iBACA,MACD,CACM,EAmBT,SAAgB,GAA6C,CAC3D,OAAO,EAoBT,eAAsB,EACpB,EAC0B,CAE1B,OADW,MAAM,GAAe,EACtB,eAAe,IAAI,EAAK,aAAa,CAAC,EAAI,EAAE"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/data/reporters.ts"],"sourcesContent":["/**\n * Reporter database integration for citation validation\n *\n * This module provides lazy-loadable access to the reporters-db database,\n * containing 1200+ court reporters with variant forms. The library works\n * in degraded mode (pattern-based extraction only) if reporters are not loaded.\n *\n * @example\n * // Degraded mode: extraction works without reporter data\n * const citations = await extract(text)\n *\n * @example\n * // Full mode: load reporters for validation\n * await loadReporters()\n * const citations = await extract(text) // Now with reporter validation\n */\n\n/**\n * Edition entry from reporters-db\n *\n * Represents a specific edition of a reporter with start/end dates.\n */\nexport interface ReporterEdition {\n /** Start date in ISO 8601 format */\n start: string | null\n /** End date in ISO 8601 format (null if ongoing) */\n end: string | null\n}\n\n/**\n * Reporter entry from reporters-db\n *\n * Represents a single court reporter with all metadata needed for\n * citation validation and enrichment.\n *\n * Note: The reporters-db structure has the actual data; this interface\n * represents it flexibly to handle all variations in the JSON.\n */\nexport interface ReporterEntry {\n /** Full reporter name (e.g., \"Federal Reporter\") */\n name: string\n /** Citation type: state, federal, specialty, neutral, state_regional, etc. */\n cite_type: string\n /** Editions keyed by abbreviation (e.g., {\"F.2d\": {...}, \"F.3d\": {...}}) */\n editions: Record<string, ReporterEdition>\n /** Variant forms mapped to canonical form (e.g., {\"F. 2d\": \"F.2d\"}) */\n variations?: Record<string, string | undefined>\n /** MLZ jurisdiction identifiers (optional) */\n mlz_jurisdiction?: string[]\n /** Publisher (optional) */\n publisher?: string\n /** Notes (optional) */\n notes?: string\n}\n\n/**\n * In-memory reporter database with fast O(1) lookup\n *\n * Uses Map-based indexing for case-insensitive abbreviation lookup.\n * All variant forms are indexed to support fuzzy matching.\n */\nexport interface ReportersDatabase {\n /** Fast O(1) lookup by abbreviation (lowercase normalized keys) */\n byAbbreviation: Map<string, ReporterEntry[]>\n /** All reporters (for iteration/filtering) */\n all: ReporterEntry[]\n}\n\n/**\n * Cached database instance (null until loadReporters() called)\n */\nlet cached: ReportersDatabase | null = null\n\n/**\n * Load reporter database asynchronously with lazy loading\n *\n * Dynamic import prevents loading 1200+ reporters until explicitly requested.\n * Result is cached after first load for subsequent calls.\n *\n * @returns Promise resolving to indexed reporter database\n *\n * @example\n * const db = await loadReporters()\n * const reporters = db.byAbbreviation.get('f.2d') // Fast O(1) lookup\n */\nexport async function loadReporters(): Promise<ReportersDatabase> {\n if (cached) return cached\n\n // Dynamic import prevents loading until requested (keeps core bundle small)\n const data = await import(\"../../data/reporters.json\", {\n assert: { type: \"json\" },\n })\n\n const byAbbreviation = new Map<string, ReporterEntry[]>()\n const all: ReporterEntry[] = []\n\n // reporters.json structure: { \"A.\": [...], \"F.2d\": [...], ... }\n const reportersData = (data.default || data) as Record<\n string,\n ReporterEntry[]\n >\n\n // Build fast lookup index with lowercase normalization\n for (const [_canonicalAbbr, reporters] of Object.entries(reportersData)) {\n for (const reporter of reporters) {\n all.push(reporter)\n\n // Index by all edition abbreviations\n for (const editionAbbr of Object.keys(reporter.editions)) {\n const key = editionAbbr.toLowerCase()\n if (!byAbbreviation.has(key)) {\n byAbbreviation.set(key, [])\n }\n byAbbreviation.get(key)?.push(reporter)\n }\n\n // Index all variations for fuzzy matching\n for (const [variant, _canonical] of Object.entries(\n reporter.variations || {},\n )) {\n const variantKey = variant.toLowerCase()\n if (!byAbbreviation.has(variantKey)) {\n byAbbreviation.set(variantKey, [])\n }\n byAbbreviation.get(variantKey)?.push(reporter)\n }\n }\n }\n\n cached = {\n byAbbreviation,\n all,\n }\n return cached\n}\n\n/**\n * Get cached reporter database synchronously (degraded mode support)\n *\n * Returns null if reporters not loaded yet. This enables the library to\n * work in degraded mode without reporter validation.\n *\n * @returns Cached database or null if not loaded\n *\n * @example\n * const db = getReportersSync()\n * if (db) {\n * // Full mode: validate citations\n * } else {\n * // Degraded mode: extract without validation\n * }\n */\nexport function getReportersSync(): ReportersDatabase | null {\n return cached\n}\n\n/**\n * Find reporters by abbreviation (case-insensitive)\n *\n * Loads reporter database if not already loaded. Returns all reporters\n * matching the abbreviation (including variant forms).\n *\n * @param abbr - Reporter abbreviation to look up\n * @returns Promise resolving to matching reporters (empty array if none)\n *\n * @example\n * const reporters = await findReportersByAbbreviation('F.2d')\n * // [{ abbreviation: 'F.2d', name: 'Federal Reporter, Second Series', ... }]\n *\n * @example\n * const unknown = await findReportersByAbbreviation('NONEXISTENT')\n * // [] (empty array, not error)\n */\nexport async function findReportersByAbbreviation(\n abbr: string,\n): Promise<ReporterEntry[]> {\n const db = await loadReporters()\n return db.byAbbreviation.get(abbr.toLowerCase()) ?? []\n}\n"],"mappings":"mEAuEA,IAAI,EAAmC,KAcvC,eAAsB,GAA4C,CAChE,GAAI,EAAQ,OAAO,EAGnB,IAAM,EAAO,MAAM,OAAO,4BAA6B,CACrD,OAAQ,CAAE,KAAM,OAAQ,CACzB,EAEK,EAAiB,IAAI,IACrB,EAAuB,EAAE,CAGzB,EAAiB,EAAK,SAAW,EAMvC,IAAK,GAAM,CAAC,EAAgB,KAAc,OAAO,QAAQ,EAAc,CACrE,IAAK,IAAM,KAAY,EAAW,CAChC,EAAI,KAAK,EAAS,CAGlB,IAAK,IAAM,KAAe,OAAO,KAAK,EAAS,SAAS,CAAE,CACxD,IAAM,EAAM,EAAY,aAAa,CAChC,EAAe,IAAI,EAAI,EAC1B,EAAe,IAAI,EAAK,EAAE,CAAC,CAE7B,EAAe,IAAI,EAAI,EAAE,KAAK,EAAS,CAIzC,IAAK,GAAM,CAAC,EAAS,KAAe,OAAO,QACzC,EAAS,YAAc,EAAE,CAC1B,CAAE,CACD,IAAM,EAAa,EAAQ,aAAa,CACnC,EAAe,IAAI,EAAW,EACjC,EAAe,IAAI,EAAY,EAAE,CAAC,CAEpC,EAAe,IAAI,EAAW,EAAE,KAAK,EAAS,EASpD,MAJA,GAAS,CACP,iBACA,MACD,CACM,EAmBT,SAAgB,GAA6C,CAC3D,OAAO,EAoBT,eAAsB,EACpB,EAC0B,CAE1B,OADW,MAAM,GAAe,EACtB,eAAe,IAAI,EAAK,aAAa,CAAC,EAAI,EAAE"}
@@ -1,2 +1,2 @@
1
- let e=null;async function t(){if(e)return e;let t=await import(`../../data/reporters.json`,{assert:{type:`json`}}),n=new Map,r=[],i=t.default||t;for(let[e,t]of Object.entries(i))for(let e of t){r.push(e);for(let t of Object.keys(e.editions)){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r).push(e)}for(let[t,r]of Object.entries(e.variations||{})){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r).push(e)}}return e={byAbbreviation:n,all:r},e}function n(){return e}async function r(e){return(await t()).byAbbreviation.get(e.toLowerCase())??[]}export{r as findReportersByAbbreviation,n as getReportersSync,t as loadReporters};
1
+ let e=null;async function t(){if(e)return e;let t=await import(`../../data/reporters.json`,{assert:{type:`json`}}),n=new Map,r=[],i=t.default||t;for(let[e,t]of Object.entries(i))for(let e of t){r.push(e);for(let t of Object.keys(e.editions)){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r)?.push(e)}for(let[t,r]of Object.entries(e.variations||{})){let r=t.toLowerCase();n.has(r)||n.set(r,[]),n.get(r)?.push(e)}}return e={byAbbreviation:n,all:r},e}function n(){return e}async function r(e){return(await t()).byAbbreviation.get(e.toLowerCase())??[]}export{r as findReportersByAbbreviation,n as getReportersSync,t as loadReporters};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/data/reporters.ts"],"sourcesContent":["/**\n * Reporter database integration for citation validation\n *\n * This module provides lazy-loadable access to the reporters-db database,\n * containing 1200+ court reporters with variant forms. The library works\n * in degraded mode (pattern-based extraction only) if reporters are not loaded.\n *\n * @example\n * // Degraded mode: extraction works without reporter data\n * const citations = await extract(text)\n *\n * @example\n * // Full mode: load reporters for validation\n * await loadReporters()\n * const citations = await extract(text) // Now with reporter validation\n */\n\n/**\n * Edition entry from reporters-db\n *\n * Represents a specific edition of a reporter with start/end dates.\n */\nexport interface ReporterEdition {\n /** Start date in ISO 8601 format */\n start: string | null\n /** End date in ISO 8601 format (null if ongoing) */\n end: string | null\n}\n\n/**\n * Reporter entry from reporters-db\n *\n * Represents a single court reporter with all metadata needed for\n * citation validation and enrichment.\n *\n * Note: The reporters-db structure has the actual data; this interface\n * represents it flexibly to handle all variations in the JSON.\n */\nexport interface ReporterEntry {\n /** Full reporter name (e.g., \"Federal Reporter\") */\n name: string\n /** Citation type: state, federal, specialty, neutral, state_regional, etc. */\n cite_type: string\n /** Editions keyed by abbreviation (e.g., {\"F.2d\": {...}, \"F.3d\": {...}}) */\n editions: Record<string, ReporterEdition>\n /** Variant forms mapped to canonical form (e.g., {\"F. 2d\": \"F.2d\"}) */\n variations?: Record<string, string | undefined>\n /** MLZ jurisdiction identifiers (optional) */\n mlz_jurisdiction?: string[]\n /** Publisher (optional) */\n publisher?: string\n /** Notes (optional) */\n notes?: string\n}\n\n/**\n * In-memory reporter database with fast O(1) lookup\n *\n * Uses Map-based indexing for case-insensitive abbreviation lookup.\n * All variant forms are indexed to support fuzzy matching.\n */\nexport interface ReportersDatabase {\n /** Fast O(1) lookup by abbreviation (lowercase normalized keys) */\n byAbbreviation: Map<string, ReporterEntry[]>\n /** All reporters (for iteration/filtering) */\n all: ReporterEntry[]\n}\n\n/**\n * Cached database instance (null until loadReporters() called)\n */\nlet cached: ReportersDatabase | null = null\n\n/**\n * Load reporter database asynchronously with lazy loading\n *\n * Dynamic import prevents loading 1200+ reporters until explicitly requested.\n * Result is cached after first load for subsequent calls.\n *\n * @returns Promise resolving to indexed reporter database\n *\n * @example\n * const db = await loadReporters()\n * const reporters = db.byAbbreviation.get('f.2d') // Fast O(1) lookup\n */\nexport async function loadReporters(): Promise<ReportersDatabase> {\n if (cached) return cached\n\n // Dynamic import prevents loading until requested (keeps core bundle small)\n const data = await import(\"../../data/reporters.json\", {\n assert: { type: \"json\" },\n })\n\n const byAbbreviation = new Map<string, ReporterEntry[]>()\n const all: ReporterEntry[] = []\n\n // reporters.json structure: { \"A.\": [...], \"F.2d\": [...], ... }\n const reportersData = (data.default || data) as Record<\n string,\n ReporterEntry[]\n >\n\n // Build fast lookup index with lowercase normalization\n for (const [canonicalAbbr, reporters] of Object.entries(reportersData)) {\n for (const reporter of reporters) {\n all.push(reporter)\n\n // Index by all edition abbreviations\n for (const editionAbbr of Object.keys(reporter.editions)) {\n const key = editionAbbr.toLowerCase()\n if (!byAbbreviation.has(key)) {\n byAbbreviation.set(key, [])\n }\n byAbbreviation.get(key)!.push(reporter)\n }\n\n // Index all variations for fuzzy matching\n for (const [variant, canonical] of Object.entries(\n reporter.variations || {},\n )) {\n const variantKey = variant.toLowerCase()\n if (!byAbbreviation.has(variantKey)) {\n byAbbreviation.set(variantKey, [])\n }\n byAbbreviation.get(variantKey)!.push(reporter)\n }\n }\n }\n\n cached = {\n byAbbreviation,\n all,\n }\n return cached\n}\n\n/**\n * Get cached reporter database synchronously (degraded mode support)\n *\n * Returns null if reporters not loaded yet. This enables the library to\n * work in degraded mode without reporter validation.\n *\n * @returns Cached database or null if not loaded\n *\n * @example\n * const db = getReportersSync()\n * if (db) {\n * // Full mode: validate citations\n * } else {\n * // Degraded mode: extract without validation\n * }\n */\nexport function getReportersSync(): ReportersDatabase | null {\n return cached\n}\n\n/**\n * Find reporters by abbreviation (case-insensitive)\n *\n * Loads reporter database if not already loaded. Returns all reporters\n * matching the abbreviation (including variant forms).\n *\n * @param abbr - Reporter abbreviation to look up\n * @returns Promise resolving to matching reporters (empty array if none)\n *\n * @example\n * const reporters = await findReportersByAbbreviation('F.2d')\n * // [{ abbreviation: 'F.2d', name: 'Federal Reporter, Second Series', ... }]\n *\n * @example\n * const unknown = await findReportersByAbbreviation('NONEXISTENT')\n * // [] (empty array, not error)\n */\nexport async function findReportersByAbbreviation(\n abbr: string,\n): Promise<ReporterEntry[]> {\n const db = await loadReporters()\n return db.byAbbreviation.get(abbr.toLowerCase()) ?? []\n}\n"],"mappings":"AAuEA,IAAI,EAAmC,KAcvC,eAAsB,GAA4C,CAChE,GAAI,EAAQ,OAAO,EAGnB,IAAM,EAAO,MAAM,OAAO,4BAA6B,CACrD,OAAQ,CAAE,KAAM,OAAQ,CACzB,EAEK,EAAiB,IAAI,IACrB,EAAuB,EAAE,CAGzB,EAAiB,EAAK,SAAW,EAMvC,IAAK,GAAM,CAAC,EAAe,KAAc,OAAO,QAAQ,EAAc,CACpE,IAAK,IAAM,KAAY,EAAW,CAChC,EAAI,KAAK,EAAS,CAGlB,IAAK,IAAM,KAAe,OAAO,KAAK,EAAS,SAAS,CAAE,CACxD,IAAM,EAAM,EAAY,aAAa,CAChC,EAAe,IAAI,EAAI,EAC1B,EAAe,IAAI,EAAK,EAAE,CAAC,CAE7B,EAAe,IAAI,EAAI,CAAE,KAAK,EAAS,CAIzC,IAAK,GAAM,CAAC,EAAS,KAAc,OAAO,QACxC,EAAS,YAAc,EAAE,CAC1B,CAAE,CACD,IAAM,EAAa,EAAQ,aAAa,CACnC,EAAe,IAAI,EAAW,EACjC,EAAe,IAAI,EAAY,EAAE,CAAC,CAEpC,EAAe,IAAI,EAAW,CAAE,KAAK,EAAS,EASpD,MAJA,GAAS,CACP,iBACA,MACD,CACM,EAmBT,SAAgB,GAA6C,CAC3D,OAAO,EAoBT,eAAsB,EACpB,EAC0B,CAE1B,OADW,MAAM,GAAe,EACtB,eAAe,IAAI,EAAK,aAAa,CAAC,EAAI,EAAE"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/data/reporters.ts"],"sourcesContent":["/**\n * Reporter database integration for citation validation\n *\n * This module provides lazy-loadable access to the reporters-db database,\n * containing 1200+ court reporters with variant forms. The library works\n * in degraded mode (pattern-based extraction only) if reporters are not loaded.\n *\n * @example\n * // Degraded mode: extraction works without reporter data\n * const citations = await extract(text)\n *\n * @example\n * // Full mode: load reporters for validation\n * await loadReporters()\n * const citations = await extract(text) // Now with reporter validation\n */\n\n/**\n * Edition entry from reporters-db\n *\n * Represents a specific edition of a reporter with start/end dates.\n */\nexport interface ReporterEdition {\n /** Start date in ISO 8601 format */\n start: string | null\n /** End date in ISO 8601 format (null if ongoing) */\n end: string | null\n}\n\n/**\n * Reporter entry from reporters-db\n *\n * Represents a single court reporter with all metadata needed for\n * citation validation and enrichment.\n *\n * Note: The reporters-db structure has the actual data; this interface\n * represents it flexibly to handle all variations in the JSON.\n */\nexport interface ReporterEntry {\n /** Full reporter name (e.g., \"Federal Reporter\") */\n name: string\n /** Citation type: state, federal, specialty, neutral, state_regional, etc. */\n cite_type: string\n /** Editions keyed by abbreviation (e.g., {\"F.2d\": {...}, \"F.3d\": {...}}) */\n editions: Record<string, ReporterEdition>\n /** Variant forms mapped to canonical form (e.g., {\"F. 2d\": \"F.2d\"}) */\n variations?: Record<string, string | undefined>\n /** MLZ jurisdiction identifiers (optional) */\n mlz_jurisdiction?: string[]\n /** Publisher (optional) */\n publisher?: string\n /** Notes (optional) */\n notes?: string\n}\n\n/**\n * In-memory reporter database with fast O(1) lookup\n *\n * Uses Map-based indexing for case-insensitive abbreviation lookup.\n * All variant forms are indexed to support fuzzy matching.\n */\nexport interface ReportersDatabase {\n /** Fast O(1) lookup by abbreviation (lowercase normalized keys) */\n byAbbreviation: Map<string, ReporterEntry[]>\n /** All reporters (for iteration/filtering) */\n all: ReporterEntry[]\n}\n\n/**\n * Cached database instance (null until loadReporters() called)\n */\nlet cached: ReportersDatabase | null = null\n\n/**\n * Load reporter database asynchronously with lazy loading\n *\n * Dynamic import prevents loading 1200+ reporters until explicitly requested.\n * Result is cached after first load for subsequent calls.\n *\n * @returns Promise resolving to indexed reporter database\n *\n * @example\n * const db = await loadReporters()\n * const reporters = db.byAbbreviation.get('f.2d') // Fast O(1) lookup\n */\nexport async function loadReporters(): Promise<ReportersDatabase> {\n if (cached) return cached\n\n // Dynamic import prevents loading until requested (keeps core bundle small)\n const data = await import(\"../../data/reporters.json\", {\n assert: { type: \"json\" },\n })\n\n const byAbbreviation = new Map<string, ReporterEntry[]>()\n const all: ReporterEntry[] = []\n\n // reporters.json structure: { \"A.\": [...], \"F.2d\": [...], ... }\n const reportersData = (data.default || data) as Record<\n string,\n ReporterEntry[]\n >\n\n // Build fast lookup index with lowercase normalization\n for (const [_canonicalAbbr, reporters] of Object.entries(reportersData)) {\n for (const reporter of reporters) {\n all.push(reporter)\n\n // Index by all edition abbreviations\n for (const editionAbbr of Object.keys(reporter.editions)) {\n const key = editionAbbr.toLowerCase()\n if (!byAbbreviation.has(key)) {\n byAbbreviation.set(key, [])\n }\n byAbbreviation.get(key)?.push(reporter)\n }\n\n // Index all variations for fuzzy matching\n for (const [variant, _canonical] of Object.entries(\n reporter.variations || {},\n )) {\n const variantKey = variant.toLowerCase()\n if (!byAbbreviation.has(variantKey)) {\n byAbbreviation.set(variantKey, [])\n }\n byAbbreviation.get(variantKey)?.push(reporter)\n }\n }\n }\n\n cached = {\n byAbbreviation,\n all,\n }\n return cached\n}\n\n/**\n * Get cached reporter database synchronously (degraded mode support)\n *\n * Returns null if reporters not loaded yet. This enables the library to\n * work in degraded mode without reporter validation.\n *\n * @returns Cached database or null if not loaded\n *\n * @example\n * const db = getReportersSync()\n * if (db) {\n * // Full mode: validate citations\n * } else {\n * // Degraded mode: extract without validation\n * }\n */\nexport function getReportersSync(): ReportersDatabase | null {\n return cached\n}\n\n/**\n * Find reporters by abbreviation (case-insensitive)\n *\n * Loads reporter database if not already loaded. Returns all reporters\n * matching the abbreviation (including variant forms).\n *\n * @param abbr - Reporter abbreviation to look up\n * @returns Promise resolving to matching reporters (empty array if none)\n *\n * @example\n * const reporters = await findReportersByAbbreviation('F.2d')\n * // [{ abbreviation: 'F.2d', name: 'Federal Reporter, Second Series', ... }]\n *\n * @example\n * const unknown = await findReportersByAbbreviation('NONEXISTENT')\n * // [] (empty array, not error)\n */\nexport async function findReportersByAbbreviation(\n abbr: string,\n): Promise<ReporterEntry[]> {\n const db = await loadReporters()\n return db.byAbbreviation.get(abbr.toLowerCase()) ?? []\n}\n"],"mappings":"AAuEA,IAAI,EAAmC,KAcvC,eAAsB,GAA4C,CAChE,GAAI,EAAQ,OAAO,EAGnB,IAAM,EAAO,MAAM,OAAO,4BAA6B,CACrD,OAAQ,CAAE,KAAM,OAAQ,CACzB,EAEK,EAAiB,IAAI,IACrB,EAAuB,EAAE,CAGzB,EAAiB,EAAK,SAAW,EAMvC,IAAK,GAAM,CAAC,EAAgB,KAAc,OAAO,QAAQ,EAAc,CACrE,IAAK,IAAM,KAAY,EAAW,CAChC,EAAI,KAAK,EAAS,CAGlB,IAAK,IAAM,KAAe,OAAO,KAAK,EAAS,SAAS,CAAE,CACxD,IAAM,EAAM,EAAY,aAAa,CAChC,EAAe,IAAI,EAAI,EAC1B,EAAe,IAAI,EAAK,EAAE,CAAC,CAE7B,EAAe,IAAI,EAAI,EAAE,KAAK,EAAS,CAIzC,IAAK,GAAM,CAAC,EAAS,KAAe,OAAO,QACzC,EAAS,YAAc,EAAE,CAC1B,CAAE,CACD,IAAM,EAAa,EAAQ,aAAa,CACnC,EAAe,IAAI,EAAW,EACjC,EAAe,IAAI,EAAY,EAAE,CAAC,CAEpC,EAAe,IAAI,EAAW,EAAE,KAAK,EAAS,EASpD,MAJA,GAAS,CACP,iBACA,MACD,CACM,EAmBT,SAAgB,GAA6C,CAC3D,OAAO,EAoBT,eAAsB,EACpB,EAC0B,CAE1B,OADW,MAAM,GAAe,EACtB,eAAe,IAAI,EAAK,aAAa,CAAC,EAAI,EAAE"}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e.type===`case`||e.type===`statute`||e.type===`journal`||e.type===`neutral`||e.type===`publicLaw`||e.type===`federalRegister`}function t(e){return e.type===`id`||e.type===`supra`||e.type===`shortFormCase`}function n(e){return e.type===`case`}function r(e,t){return e.type===t}function i(e){throw Error(`Unexpected value: ${e}`)}function a(e){return e.replace(/<[^>]+>/g,``)}function o(e){return e.replace(/[\t\n\r]+/g,` `).replace(/ {2,}/g,` `)}function s(e){return e.normalize(`NFKC`)}function c(e){return e.replace(/[\u201C\u201D]/g,`"`).replace(/[\u2018\u2019]/g,`'`)}function l(e,t=[a,o,s,c]){let n=e,r=new Map,i=new Map;for(let t=0;t<=e.length;t++)r.set(t,t),i.set(t,t);for(let e of t){let t=n,a=e(n);if(t!==a){let{newCleanToOriginal:e,newOriginalToClean:o}=u(t,a,r,i);r=e,i=o,n=a}}return{cleaned:n,transformationMap:{cleanToOriginal:r,originalToClean:i},warnings:[]}}function u(e,t,n,r){let i=new Map,a=new Map,o=0,s=0;for(;o<=e.length||s<=t.length;){if(o>=e.length&&s>=t.length){let e=n.get(o)??o;i.set(s,e),a.set(e,s);break}if(o>=e.length){let e=n.get(o)??o;i.set(s,e),s++;continue}if(s>=t.length){let e=n.get(o)??o;a.set(e,s),o++;continue}if(e[o]===t[s]){let e=n.get(o)??o;i.set(s,e),a.set(e,s),o++,s++}else{let r=!1;for(let i=1;i<=20&&!(o+i>=e.length);i++)if(e[o+i]===t[s]){for(let e=0;e<i;e++){let t=n.get(o+e)??o+e;a.set(t,s)}o+=i,r=!0;break}if(r)continue;for(let a=1;a<=20&&!(s+a>=t.length);a++)if(e[o]===t[s+a]){let e=n.get(o)??o;for(let t=0;t<a;t++)i.set(s+t,e);s+=a,r=!0;break}if(r)continue;let c=n.get(o)??o;i.set(s,c),a.set(c,s),o++,s++}}return{newCleanToOriginal:i,newOriginalToClean:a}}const d=[{id:`federal-reporter`,regex:/\b(\d+)\s+(F\.|F\.2d|F\.3d|F\.\s?Supp\.|F\.\s?Supp\.\s?2d|F\.\s?Supp\.\s?3d)\s+(\d+)\b/g,description:`Federal Reporter (F., F.2d, F.3d, F.Supp., etc.)`,type:`case`},{id:`supreme-court`,regex:/\b(\d+)\s+(U\.S\.|S\.\s?Ct\.|L\.\s?Ed\.(?:\s?2d)?)\s+(\d+)\b/g,description:`U.S. Supreme Court reporters`,type:`case`},{id:`state-reporter`,regex:/\b(\d+)\s+([A-Z][A-Za-z\.]+(?:\s?2d|\s?3d)?)\s+(\d+)\b/g,description:`State reporters (broad pattern, validated against reporters-db in Phase 3)`,type:`case`}],f=[{id:`usc`,regex:/\b(\d+)\s+U\.S\.C\.?\s+§+\s*(\d+)\b/g,description:`U.S. Code citations (e.g., "42 U.S.C. § 1983")`,type:`statute`},{id:`state-code`,regex:/\b([A-Z][a-z]+\.?\s+[A-Za-z\.]+\s+Code)\s+§\s*(\d+)\b/g,description:`State code citations (broad pattern, e.g., "Cal. Penal Code § 187")`,type:`statute`}],p=[{id:`law-review`,regex:/\b(\d+)\s+([A-Z][A-Za-z\.\s]+)\s+(\d+)\b/g,description:`Law review citations (e.g., "120 Harv. L. Rev. 500"), validated against journals-db in Phase 3`,type:`journal`}],m=[{id:`westlaw`,regex:/\b(\d{4})\s+WL\s+(\d+)\b/g,description:`WestLaw citations (e.g., "2021 WL 123456")`,type:`neutral`},{id:`lexis`,regex:/\b(\d{4})\s+U\.S\.\s+LEXIS\s+(\d+)\b/g,description:`LexisNexis citations (e.g., "2021 U.S. LEXIS 5000")`,type:`neutral`},{id:`public-law`,regex:/\bPub\.\s?L\.\s?No\.\s?(\d+-\d+)\b/g,description:`Public Law citations (e.g., "Pub. L. No. 117-58")`,type:`publicLaw`},{id:`federal-register`,regex:/\b(\d+)\s+Fed\.\s?Reg\.\s+(\d+)\b/g,description:`Federal Register citations (e.g., "86 Fed. Reg. 12345")`,type:`federalRegister`}],h=[{id:`id`,regex:/\b[Ii]d\.(?:\s+at\s+(\d+))?/g,description:`Id. citations (e.g., "Id." or "Id. at 253")`,type:`case`},{id:`ibid`,regex:/\b[Ii]bid\.(?:\s+at\s+(\d+))?/g,description:`Ibid. citations (e.g., "Ibid." or "Ibid. at 125")`,type:`case`},{id:`supra`,regex:/\b([A-Z][a-zA-Z]+(?:(?:\s+v\.?\s+|\s+)[A-Z][a-zA-Z]+)*),?\s+supra(?:,?\s+at\s+(\d+))?/g,description:`Supra citations (e.g., "Smith, supra" or "Smith, supra, at 460")`,type:`case`},{id:`shortFormCase`,regex:/\b(\d+)\s+([A-Z][A-Za-z.\s]+?(?:\d[a-z])?)\s+at\s+(\d+)\b/g,description:`Short-form case citations (e.g., "500 F.2d at 125")`,type:`case`}];function g(e,t=[...d,...f,...p,...m,...h]){let n=[];for(let r of t)try{let t=e.matchAll(r.regex);for(let e of t)n.push({text:e[0],span:{cleanStart:e.index,cleanEnd:e.index+e[0].length},type:r.type,patternId:r.id})}catch(e){console.warn(`Pattern ${r.id} threw error, skipping:`,e instanceof Error?e.message:String(e));continue}return n.sort((e,t)=>e.span.cleanStart-t.span.cleanStart),n}function _(e,t){let{text:n,span:r}=e,i=/^(\d+)\s+([A-Za-z0-9.\s]+)\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse case citation: ${n}`);let a=Number.parseInt(i[1],10),o=i[2].trim(),s=Number.parseInt(i[3],10),c=/,\s*(\d+)/.exec(n),l=c?Number.parseInt(c[1],10):void 0,u=/\((?:[^)]*\s)?(\d{4})\)/.exec(n),d=u?Number.parseInt(u[1],10):void 0,f=/\(([^)]*[A-Za-z][^)]*)\)/.exec(n),p=f?f[1].trim():void 0,m=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,h=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd,g=.5;return`F.,F.2d,F.3d,F.4th,U.S.,S. Ct.,L. Ed.,P.,P.2d,P.3d,A.,A.2d,A.3d,N.E.,N.E.2d,N.E.3d,N.W.,N.W.2d,S.E.,S.E.2d,S.W.,S.W.2d,S.W.3d,So.,So. 2d,So. 3d`.split(`,`).some(e=>o.includes(e))&&(g+=.3),d!==void 0&&d<=new Date().getFullYear()&&(g+=.2),g=Math.min(g,1),{type:`case`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:m,originalEnd:h},confidence:g,matchedText:n,processTimeMs:0,patternsChecked:1,volume:a,reporter:o,page:s,pincite:l,court:p,year:d}}function v(e,t){let{text:n,span:r}=e,i=/^(?:(\d+)\s+)?([A-Za-z.\s]+?)\s*§\s*(\d+[A-Za-z0-9\-]*)/.exec(n);if(!i)throw Error(`Failed to parse statute citation: ${n}`);let a=i[1]?Number.parseInt(i[1],10):void 0,o=i[2].trim(),s=i[3],c=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,l=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd,u=.5;return[`U.S.C.`,`C.F.R.`,`Cal. Civ. Code`,`Cal. Penal Code`,`N.Y. Civ. Prac. L. & R.`,`Tex. Civ. Prac. & Rem. Code`].some(e=>o.includes(e))&&(u+=.3),u=Math.min(u,1),{type:`statute`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:c,originalEnd:l},confidence:u,matchedText:n,processTimeMs:0,patternsChecked:1,title:a,code:o,section:s}}function y(e,t){let{text:n,span:r}=e,i=/^(\d+)\s+([A-Za-z.\s]+?)\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse journal citation: ${n}`);let a=Number.parseInt(i[1],10),o=i[2].trim(),s=Number.parseInt(i[3],10),c=/,\s*(\d+)/.exec(n),l=c?Number.parseInt(c[1],10):void 0,u=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,d=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`journal`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:u,originalEnd:d},confidence:.6,matchedText:n,processTimeMs:0,patternsChecked:1,volume:a,journal:o,abbreviation:o,page:s,pincite:l}}function b(e,t){let{text:n,span:r}=e,i=/^(\d{4})\s+(WL|LEXIS|U\.S\.\s+LEXIS)\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse neutral citation: ${n}`);let a=Number.parseInt(i[1],10),o=i[2],s=i[3],c=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,l=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`neutral`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:c,originalEnd:l},confidence:1,matchedText:n,processTimeMs:0,patternsChecked:1,year:a,court:o,documentNumber:s}}function x(e,t){let{text:n,span:r}=e,i=/Pub\.\s?L\.(?:\s?No\.)?\s?(\d+)-(\d+)/.exec(n);if(!i)throw Error(`Failed to parse public law citation: ${n}`);let a=Number.parseInt(i[1],10),o=Number.parseInt(i[2],10),s=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,c=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`publicLaw`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:s,originalEnd:c},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,congress:a,lawNumber:o}}function S(e,t){let{text:n,span:r}=e,i=/^(\d+)\s+Fed\.\s?Reg\.\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse Federal Register citation: ${n}`);let a=Number.parseInt(i[1],10),o=Number.parseInt(i[2],10),s=/\((?:.*?\s)?(\d{4})\)/.exec(n),c=s?Number.parseInt(s[1],10):void 0,l=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,u=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`federalRegister`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:l,originalEnd:u},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,volume:a,page:o,year:c}}function C(e,t){let{text:n,span:r}=e,i=/[Ii](?:d|bid)\.(?:\s+at\s+(\d+))?/.exec(n);if(!i)throw Error(`Failed to parse Id. citation: ${n}`);let a=i[1]?Number.parseInt(i[1],10):void 0,o=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,s=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`id`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:o,originalEnd:s},confidence:1,matchedText:n,processTimeMs:0,patternsChecked:1,pincite:a}}function w(e,t){let{text:n,span:r}=e,i=/\b([A-Z][a-zA-Z]+(?:(?:\s+v\.?\s+|\s+)[A-Z][a-zA-Z]+)*),?\s+supra(?:,?\s+at\s+(\d+))?/.exec(n);if(!i)throw Error(`Failed to parse supra citation: ${n}`);let a=i[1],o=i[2]?Number.parseInt(i[2],10):void 0,s=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,c=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`supra`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:s,originalEnd:c},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,partyName:a,pincite:o}}function T(e,t){let{text:n,span:r}=e,i=/(\d+)\s+([A-Z][A-Za-z.\s]+?(?:\d[a-z])?)\s+at\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse short-form case citation: ${n}`);let a=Number.parseInt(i[1],10),o=i[2].trim(),s=Number.parseInt(i[3],10),c=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,l=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`shortFormCase`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:c,originalEnd:l},confidence:.7,matchedText:n,processTimeMs:0,patternsChecked:1,volume:a,reporter:o,pincite:s}}function E(e,t,n=/\n\n+/g){let r=new Map,i=[0],a;for(;(a=n.exec(e))!==null;)i.push(a.index+a[0].length);i.push(e.length);for(let e=0;e<t.length;e++){let n=t[e].span.originalStart,a=0;for(let e=0;e<i.length-1;e++)if(n>=i[e]&&n<i[e+1]){a=e;break}r.set(e,a)}return r}function D(e,t,n,r){if(r===`none`)return!0;let i=n.get(e),a=n.get(t);return i===void 0||a===void 0?!0:i===a}function O(e,t){if(e.length===0)return t.length;if(t.length===0)return e.length;let n=Array.from({length:e.length+1},()=>Array(t.length+1).fill(0));for(let t=0;t<=e.length;t++)n[t][0]=t;for(let e=0;e<=t.length;e++)n[0][e]=e;for(let r=1;r<=e.length;r++)for(let i=1;i<=t.length;i++)e[r-1]===t[i-1]?n[r][i]=n[r-1][i-1]:n[r][i]=1+Math.min(n[r-1][i],n[r][i-1],n[r-1][i-1]);return n[e.length][t.length]}function k(e,t){let n=e.toLowerCase(),r=t.toLowerCase(),i=O(n,r),a=Math.max(n.length,r.length);return a===0?1:1-i/a}var A=class{constructor(e,t,n={}){this.citations=e,this.text=t,this.options={scopeStrategy:n.scopeStrategy??`paragraph`,autoDetectParagraphs:n.autoDetectParagraphs??!0,paragraphBoundaryPattern:n.paragraphBoundaryPattern??/\n\n+/g,fuzzyPartyMatching:n.fuzzyPartyMatching??!0,partyMatchThreshold:n.partyMatchThreshold??.8,allowNestedResolution:n.allowNestedResolution??!1,reportUnresolved:n.reportUnresolved??!0},this.context={citationIndex:0,allCitations:e,lastFullCitation:void 0,fullCitationHistory:new Map,paragraphMap:new Map},this.options.autoDetectParagraphs&&(this.context.paragraphMap=E(t,e,this.options.paragraphBoundaryPattern))}resolve(){let t=[];for(let n=0;n<this.citations.length;n++){this.context.citationIndex=n;let r=this.citations[n],i;switch(r.type){case`id`:i=this.resolveId(r);break;case`supra`:i=this.resolveSupra(r);break;case`shortFormCase`:i=this.resolveShortFormCase(r);break;default:e(r)&&(this.context.lastFullCitation=n,this.trackFullCitation(r,n));break}t.push({...r,resolution:i})}return t}resolveId(e){let t=this.context.citationIndex,n;for(let e=t-1;e>=0;e--)if(this.citations[e].type===`case`){n=e;break}return n===void 0?this.createFailureResult(`No preceding full case citation found`):this.isWithinScope(n,t)?{resolvedTo:n,confidence:1}:this.createFailureResult(`Antecedent citation outside scope boundary`)}resolveSupra(e){let t=this.context.citationIndex,n=this.normalizePartyName(e.partyName),r;for(let[e,i]of this.context.fullCitationHistory){if(!this.isWithinScope(i,t))continue;let a=k(n,e);(!r||a>r.similarity)&&(r={index:i,similarity:a})}if(!r)return this.createFailureResult(`No full citation found in scope`);if(r.similarity<this.options.partyMatchThreshold)return this.createFailureResult(`Party name similarity ${r.similarity.toFixed(2)} below threshold ${this.options.partyMatchThreshold}`);let i=[];return r.similarity<1&&i.push(`Fuzzy match: similarity ${r.similarity.toFixed(2)}`),{resolvedTo:r.index,confidence:r.similarity,warnings:i.length>0?i:void 0}}resolveShortFormCase(e){let t=this.context.citationIndex;for(let n=t-1;n>=0;n--){let r=this.citations[n];if(r.type===`case`&&r.volume===e.volume&&this.normalizeReporter(r.reporter)===this.normalizeReporter(e.reporter))return this.isWithinScope(n,t)?{resolvedTo:n,confidence:.95}:this.createFailureResult(`Matching citation outside scope boundary`)}return this.createFailureResult(`No matching full case citation found`)}trackFullCitation(e,t){if(e.type===`case`){let n=this.extractPartyName(e);if(n){let e=this.normalizePartyName(n);this.context.fullCitationHistory.set(e,t)}}}extractPartyName(e){let t=e.span.originalStart,n=Math.max(0,t-100),r=this.text.substring(n,t),i=r.match(/([A-Z][a-zA-Z]*(?:\s+[A-Z][a-zA-Z]*)*)\s+v\.?\s+[A-Z][a-zA-Z]*(?:\s+[A-Z][a-zA-Z]*)*,\s*$/);return i?i[1].trim():r.match(/([A-Z][a-zA-Z]*(?:\s+[A-Z][a-zA-Z]*)*),\s*$/)?.[1].trim()}normalizePartyName(e){return e.toLowerCase().replace(/\s+/g,` `).trim()}normalizeReporter(e){return e.toLowerCase().replace(/\s+/g,``).replace(/\./g,``)}isWithinScope(e,t){return D(e,t,this.context.paragraphMap,this.options.scopeStrategy)}createFailureResult(e){if(this.options.reportUnresolved)return{resolvedTo:void 0,failureReason:e,confidence:0}}};function j(e,t,n){return new A(e,t,n).resolve()}function M(e,t){let n=performance.now(),{cleaned:r,transformationMap:i,warnings:a}=l(e,t?.cleaners),o=g(r,t?.patterns||[...m,...h,...d,...f,...p]),s=[],c=new Set;for(let e of o){let t=`${e.span.cleanStart}-${e.span.cleanEnd}`;c.has(t)||(c.add(t),s.push(e))}let u=[];for(let e of s){let t;switch(e.type){case`case`:t=e.patternId===`id`||e.patternId===`ibid`?C(e,i):e.patternId===`supra`?w(e,i):e.patternId===`shortFormCase`?T(e,i):_(e,i);break;case`statute`:t=v(e,i);break;case`journal`:t=y(e,i);break;case`neutral`:t=b(e,i);break;case`publicLaw`:t=x(e,i);break;case`federalRegister`:t=S(e,i);break;default:continue}a.length>0&&(t.warnings=[...t.warnings||[],...a]),t.processTimeMs=performance.now()-n,u.push(t)}return t?.resolve?j(u,e,t.resolutionOptions):u}async function N(e,t){return M(e,t)}exports.DocumentResolver=A,exports.assertUnreachable=i,exports.cleanText=l,exports.extractCase=_,exports.extractCitations=M,exports.extractCitationsAsync=N,exports.extractFederalRegister=S,exports.extractJournal=y,exports.extractNeutral=b,exports.extractPublicLaw=x,exports.extractStatute=v,exports.isCaseCitation=n,exports.isCitationType=r,exports.isFullCitation=e,exports.isShortFormCitation=t,exports.resolveCitations=j,exports.tokenize=g;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return e.type===`case`||e.type===`statute`||e.type===`journal`||e.type===`neutral`||e.type===`publicLaw`||e.type===`federalRegister`||e.type===`statutesAtLarge`}function t(e){return e.type===`id`||e.type===`supra`||e.type===`shortFormCase`}function n(e){return e.type===`case`}function r(e,t){return e.type===t}function i(e){throw Error(`Unexpected value: ${e}`)}function a(e){return e.replace(/<[^>]+>/g,``)}function o(e){return e.replace(/[\t\n\r]+/g,` `).replace(/ {2,}/g,` `)}function s(e){return e.normalize(`NFKC`)}function c(e){return e.replace(/[\u201C\u201D]/g,`"`).replace(/[\u2018\u2019]/g,`'`)}function l(e,t=[a,o,s,c]){let n=e,r=new Map,i=new Map;for(let t=0;t<=e.length;t++)r.set(t,t),i.set(t,t);for(let e of t){let t=n,a=e(n);if(t!==a){let{newCleanToOriginal:e,newOriginalToClean:o}=u(t,a,r,i);r=e,i=o,n=a}}return{cleaned:n,transformationMap:{cleanToOriginal:r,originalToClean:i},warnings:[]}}function u(e,t,n,r){let i=new Map,a=new Map,o=0,s=0;for(;o<=e.length||s<=t.length;){if(o>=e.length&&s>=t.length){let e=n.get(o)??o;i.set(s,e),a.set(e,s);break}if(o>=e.length){let e=n.get(o)??o;i.set(s,e),s++;continue}if(s>=t.length){let e=n.get(o)??o;a.set(e,s),o++;continue}if(e[o]===t[s]){let e=n.get(o)??o;i.set(s,e),a.set(e,s),o++,s++}else{let r=!1;for(let i=1;i<=20&&!(o+i>=e.length);i++)if(e[o+i]===t[s]){for(let e=0;e<i;e++){let t=n.get(o+e)??o+e;a.set(t,s)}o+=i,r=!0;break}if(r)continue;for(let a=1;a<=20&&!(s+a>=t.length);a++)if(e[o]===t[s+a]){let e=n.get(o)??o;for(let t=0;t<a;t++)i.set(s+t,e);s+=a,r=!0;break}if(r)continue;let c=n.get(o)??o;i.set(s,c),a.set(c,s),o++,s++}}return{newCleanToOriginal:i,newOriginalToClean:a}}const d=[{id:`federal-reporter`,regex:/\b(\d+(?:-\d+)?)\s+(F\.|F\.2d|F\.3d|F\.4th|F\.\s?Supp\.|F\.\s?Supp\.\s?2d|F\.\s?Supp\.\s?3d|F\.\s?Supp\.\s?4th)\s+(\d+)\b/g,description:`Federal Reporter (F., F.2d, F.3d, F.4th, F.Supp., etc.)`,type:`case`},{id:`supreme-court`,regex:/\b(\d+(?:-\d+)?)\s+(U\.\s?S\.|S\.\s?Ct\.|L\.\s?Ed\.(?:\s?2d)?)\s+(\d+)\b/g,description:`U.S. Supreme Court reporters`,type:`case`},{id:`state-reporter`,regex:/\b(\d+(?:-\d+)?)\s+([A-Z][A-Za-z.]+(?:\s?2d|\s?3d|\s?4th|\s?5th)?)\s+(\d+)\b/g,description:`State reporters (broad pattern, validated against reporters-db in Phase 3)`,type:`case`}],f=[{id:`usc`,regex:/\b(\d+)\s+U\.S\.C\.?\s+§+\s*(\d+[A-Za-z]*)\b/g,description:`U.S. Code citations (e.g., "42 U.S.C. § 1983")`,type:`statute`},{id:`state-code`,regex:/\b([A-Z][a-z]+\.?\s+[A-Za-z.]+\s+Code)\s+§\s*(\d+[A-Za-z]*)\b/g,description:`State code citations (broad pattern, e.g., "Cal. Penal Code § 187")`,type:`statute`}],p=[{id:`law-review`,regex:/\b(\d+(?:-\d+)?)\s+([A-Z][A-Za-z.\s]+)\s+(\d+)\b/g,description:`Law review citations (e.g., "120 Harv. L. Rev. 500"), validated against journals-db in Phase 3`,type:`journal`}],m=[{id:`westlaw`,regex:/\b(\d{4})\s+WL\s+(\d+)\b/g,description:`WestLaw citations (e.g., "2021 WL 123456")`,type:`neutral`},{id:`lexis`,regex:/\b(\d{4})\s+U\.S\.\s+LEXIS\s+(\d+)\b/g,description:`LexisNexis citations (e.g., "2021 U.S. LEXIS 5000")`,type:`neutral`},{id:`public-law`,regex:/\bPub\.\s?L\.\s?No\.\s?(\d+-\d+)\b/g,description:`Public Law citations (e.g., "Pub. L. No. 117-58")`,type:`publicLaw`},{id:`federal-register`,regex:/\b(\d+(?:-\d+)?)\s+Fed\.\s?Reg\.\s+(\d+)\b/g,description:`Federal Register citations (e.g., "86 Fed. Reg. 12345")`,type:`federalRegister`},{id:`statutes-at-large`,regex:/\b(\d+(?:-\d+)?)\s+Stat\.\s+(\d+)\b/g,description:`Statutes at Large citations (e.g., "124 Stat. 119")`,type:`statutesAtLarge`},{id:`compact-law-review`,regex:/\b(\d+(?:-\d+)?)\s+([A-Z][A-Za-z.]+L\.(?:Rev|J|Q)\.)\s+(\d+)\b/g,description:`Compact law review citations without spaces (e.g., "93 Harv.L.Rev. 752")`,type:`journal`}],h=[{id:`id`,regex:/\b[Ii]d\.(?:\s+at\s+(\d+))?/g,description:`Id. citations (e.g., "Id." or "Id. at 253")`,type:`case`},{id:`ibid`,regex:/\b[Ii]bid\.(?:\s+at\s+(\d+))?/g,description:`Ibid. citations (e.g., "Ibid." or "Ibid. at 125")`,type:`case`},{id:`supra`,regex:/\b([A-Z][a-zA-Z]+(?:(?:\s+v\.?\s+|\s+)[A-Z][a-zA-Z]+)*)\s*,?\s+supra(?:,?\s+at\s+(\d+))?/g,description:`Supra citations (e.g., "Smith, supra" or "Smith, supra, at 460")`,type:`case`},{id:`shortFormCase`,regex:/\b(\d+(?:-\d+)?)\s+([A-Z][A-Za-z.\s]+?(?:\d[a-z])?)\s+at\s+(\d+)\b/g,description:`Short-form case citations (e.g., "500 F.2d at 125")`,type:`case`}];function g(e,t=[...d,...f,...p,...m,...h]){let n=[];for(let r of t)try{let t=e.matchAll(r.regex);for(let e of t)n.push({text:e[0],span:{cleanStart:e.index,cleanEnd:e.index+e[0].length},type:r.type,patternId:r.id})}catch(e){console.warn(`Pattern ${r.id} threw error, skipping:`,e instanceof Error?e.message:String(e))}return n.sort((e,t)=>e.span.cleanStart-t.span.cleanStart),n}function _(e){let t=Number.parseInt(e,10);return String(t)===e?t:e}const v=/(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec)\.?/;function y(e){let t=e.replace(/\s*\d{4}\s*$/,``).trim();return t=t.replace(RegExp(`\\s*,?\\s*\\d{1,2}\\s*,?\\s*$`),``).trim(),t=t.replace(RegExp(`\\s*${v.source}\\s*$`),``).trim(),t=t.replace(/,\s*$/,``).trim(),t&&/[A-Za-z]/.test(t)?t:void 0}function b(e,t,n){let{text:r,span:i}=e,a=/^(\d+(?:-\d+)?)\s+([A-Za-z0-9.\s]+)\s+(\d+)/.exec(r);if(!a)throw Error(`Failed to parse case citation: ${r}`);let o=_(a[1]),s=a[2].trim(),c=Number.parseInt(a[3],10),l=/,\s*(\d+)/.exec(r),u=l?Number.parseInt(l[1],10):void 0,d=/\((?:[^)]*\s)?(\d{4})\)/.exec(r),f=d?Number.parseInt(d[1],10):void 0,p=/\(([^)]*[A-Za-z][^)]*)\)/.exec(r),m=p?y(p[1]):void 0;if(n&&f===void 0){let e=n.substring(i.cleanEnd),t=/^(?:,\s*\d+)*\s*\(([^)]+)\)/.exec(e);if(t){let n=t[1],r=/(\d{4})/.exec(n);r&&(f=Number.parseInt(r[1],10));let i=y(n);if(i&&(m=i),u===void 0){let t=/^,\s*(\d+)/.exec(e);t&&(u=Number.parseInt(t[1],10))}}}!m&&/^(?:U\.?\s?S\.|S\.?\s?Ct\.|L\.?\s?Ed\.)/.test(s)&&(m=`scotus`);let h=t.cleanToOriginal.get(i.cleanStart)??i.cleanStart,g=t.cleanToOriginal.get(i.cleanEnd)??i.cleanEnd,v=.5;if(`F.,F.2d,F.3d,F.4th,U.S.,S. Ct.,L. Ed.,P.,P.2d,P.3d,A.,A.2d,A.3d,N.E.,N.E.2d,N.E.3d,N.W.,N.W.2d,S.E.,S.E.2d,S.W.,S.W.2d,S.W.3d,So.,So. 2d,So. 3d`.split(`,`).some(e=>s.includes(e))&&(v+=.3),f!==void 0){let e=new Date().getFullYear();f<=e&&(v+=.2)}return v=Math.min(v,1),{type:`case`,text:r,span:{cleanStart:i.cleanStart,cleanEnd:i.cleanEnd,originalStart:h,originalEnd:g},confidence:v,matchedText:r,processTimeMs:0,patternsChecked:1,volume:o,reporter:s,page:c,pincite:u,court:m,year:f}}function x(e,t){let{text:n,span:r}=e,i=/^(?:(\d+)\s+)?([A-Za-z.\s]+?)\s*§\s*(\d+[A-Za-z0-9-]*)/.exec(n);if(!i)throw Error(`Failed to parse statute citation: ${n}`);let a=i[1]?Number.parseInt(i[1],10):void 0,o=i[2].trim(),s=i[3],c=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,l=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd,u=.5;return[`U.S.C.`,`C.F.R.`,`Cal. Civ. Code`,`Cal. Penal Code`,`N.Y. Civ. Prac. L. & R.`,`Tex. Civ. Prac. & Rem. Code`].some(e=>o.includes(e))&&(u+=.3),u=Math.min(u,1),{type:`statute`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:c,originalEnd:l},confidence:u,matchedText:n,processTimeMs:0,patternsChecked:1,title:a,code:o,section:s}}function S(e,t){let{text:n,span:r}=e,i=/^(\d+(?:-\d+)?)\s+([A-Za-z.\s]+?)\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse journal citation: ${n}`);let a=i[1],o=/^\d+$/.test(a)?Number.parseInt(a,10):a,s=i[2].trim(),c=Number.parseInt(i[3],10),l=/,\s*(\d+)/.exec(n),u=l?Number.parseInt(l[1],10):void 0,d=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,f=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`journal`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:d,originalEnd:f},confidence:.6,matchedText:n,processTimeMs:0,patternsChecked:1,volume:o,journal:s,abbreviation:s,page:c,pincite:u}}function C(e,t){let{text:n,span:r}=e,i=/^(\d{4})\s+(WL|LEXIS|U\.S\.\s+LEXIS)\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse neutral citation: ${n}`);let a=Number.parseInt(i[1],10),o=i[2],s=i[3],c=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,l=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`neutral`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:c,originalEnd:l},confidence:1,matchedText:n,processTimeMs:0,patternsChecked:1,year:a,court:o,documentNumber:s}}function w(e,t){let{text:n,span:r}=e,i=/Pub\.\s?L\.(?:\s?No\.)?\s?(\d+)-(\d+)/.exec(n);if(!i)throw Error(`Failed to parse public law citation: ${n}`);let a=Number.parseInt(i[1],10),o=Number.parseInt(i[2],10),s=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,c=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`publicLaw`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:s,originalEnd:c},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,congress:a,lawNumber:o}}function T(e,t){let{text:n,span:r}=e,i=/^(\d+(?:-\d+)?)\s+Fed\.\s?Reg\.\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse Federal Register citation: ${n}`);let a=i[1],o=/^\d+$/.test(a)?Number.parseInt(a,10):a,s=Number.parseInt(i[2],10),c=/\((?:.*?\s)?(\d{4})\)/.exec(n),l=c?Number.parseInt(c[1],10):void 0,u=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,d=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`federalRegister`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:u,originalEnd:d},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,volume:o,page:s,year:l}}function E(e,t){let{text:n,span:r}=e,i=/^(\d+(?:-\d+)?)\s+Stat\.\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse Statutes at Large citation: ${n}`);let a=i[1],o=/^\d+$/.test(a)?Number.parseInt(a,10):a,s=Number.parseInt(i[2],10),c=/\((?:.*?\s)?(\d{4})\)/.exec(n),l=c?Number.parseInt(c[1],10):void 0,u=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,d=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`statutesAtLarge`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:u,originalEnd:d},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,volume:o,page:s,year:l}}function D(e,t){let{text:n,span:r}=e,i=/[Ii](?:d|bid)\.(?:\s+at\s+(\d+))?/.exec(n);if(!i)throw Error(`Failed to parse Id. citation: ${n}`);let a=i[1]?Number.parseInt(i[1],10):void 0,o=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,s=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`id`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:o,originalEnd:s},confidence:1,matchedText:n,processTimeMs:0,patternsChecked:1,pincite:a}}function O(e,t){let{text:n,span:r}=e,i=/\b([A-Z][a-zA-Z]+(?:(?:\s+v\.?\s+|\s+)[A-Z][a-zA-Z]+)*)\s*,?\s+supra(?:,?\s+at\s+(\d+))?/.exec(n);if(!i)throw Error(`Failed to parse supra citation: ${n}`);let a=i[1],o=i[2]?Number.parseInt(i[2],10):void 0,s=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,c=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`supra`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:s,originalEnd:c},confidence:.9,matchedText:n,processTimeMs:0,patternsChecked:1,partyName:a,pincite:o}}function k(e,t){let{text:n,span:r}=e,i=/(\d+(?:-\d+)?)\s+([A-Z][A-Za-z.\s]+?(?:\d[a-z])?)\s+at\s+(\d+)/.exec(n);if(!i)throw Error(`Failed to parse short-form case citation: ${n}`);let a=i[1],o=/^\d+$/.test(a)?Number.parseInt(a,10):a,s=i[2].trim(),c=Number.parseInt(i[3],10),l=t.cleanToOriginal.get(r.cleanStart)??r.cleanStart,u=t.cleanToOriginal.get(r.cleanEnd)??r.cleanEnd;return{type:`shortFormCase`,text:n,span:{cleanStart:r.cleanStart,cleanEnd:r.cleanEnd,originalStart:l,originalEnd:u},confidence:.7,matchedText:n,processTimeMs:0,patternsChecked:1,volume:o,reporter:s,pincite:c}}function A(e,t,n=/\n\n+/g){let r=new Map,i=[0],a;for(;(a=n.exec(e))!==null;)i.push(a.index+a[0].length);i.push(e.length);for(let e=0;e<t.length;e++){let n=t[e].span.originalStart,a=0;for(let e=0;e<i.length-1;e++)if(n>=i[e]&&n<i[e+1]){a=e;break}r.set(e,a)}return r}function j(e,t,n,r){if(r===`none`)return!0;let i=n.get(e),a=n.get(t);return i===void 0||a===void 0?!0:i===a}function M(e,t){if(e.length===0)return t.length;if(t.length===0)return e.length;let n=Array.from({length:e.length+1},()=>Array(t.length+1).fill(0));for(let t=0;t<=e.length;t++)n[t][0]=t;for(let e=0;e<=t.length;e++)n[0][e]=e;for(let r=1;r<=e.length;r++)for(let i=1;i<=t.length;i++)e[r-1]===t[i-1]?n[r][i]=n[r-1][i-1]:n[r][i]=1+Math.min(n[r-1][i],n[r][i-1],n[r-1][i-1]);return n[e.length][t.length]}function N(e,t){let n=e.toLowerCase(),r=t.toLowerCase(),i=M(n,r),a=Math.max(n.length,r.length);return a===0?1:1-i/a}var P=class{constructor(e,t,n={}){this.citations=e,this.text=t,this.options={scopeStrategy:n.scopeStrategy??`paragraph`,autoDetectParagraphs:n.autoDetectParagraphs??!0,paragraphBoundaryPattern:n.paragraphBoundaryPattern??/\n\n+/g,fuzzyPartyMatching:n.fuzzyPartyMatching??!0,partyMatchThreshold:n.partyMatchThreshold??.8,allowNestedResolution:n.allowNestedResolution??!1,reportUnresolved:n.reportUnresolved??!0},this.context={citationIndex:0,allCitations:e,lastFullCitation:void 0,fullCitationHistory:new Map,paragraphMap:new Map},this.options.autoDetectParagraphs&&(this.context.paragraphMap=A(t,e,this.options.paragraphBoundaryPattern))}resolve(){let t=[];for(let n=0;n<this.citations.length;n++){this.context.citationIndex=n;let r=this.citations[n],i;switch(r.type){case`id`:i=this.resolveId(r);break;case`supra`:i=this.resolveSupra(r);break;case`shortFormCase`:i=this.resolveShortFormCase(r);break;default:e(r)&&(this.context.lastFullCitation=n,this.trackFullCitation(r,n));break}t.push({...r,resolution:i})}return t}resolveId(e){let t=this.context.citationIndex,n;for(let e=t-1;e>=0;e--)if(this.citations[e].type===`case`){n=e;break}return n===void 0?this.createFailureResult(`No preceding full case citation found`):this.isWithinScope(n,t)?{resolvedTo:n,confidence:1}:this.createFailureResult(`Antecedent citation outside scope boundary`)}resolveSupra(e){let t=this.context.citationIndex,n=this.normalizePartyName(e.partyName),r;for(let[e,i]of this.context.fullCitationHistory){if(!this.isWithinScope(i,t))continue;let a=N(n,e);(!r||a>r.similarity)&&(r={index:i,similarity:a})}if(!r)return this.createFailureResult(`No full citation found in scope`);if(r.similarity<this.options.partyMatchThreshold)return this.createFailureResult(`Party name similarity ${r.similarity.toFixed(2)} below threshold ${this.options.partyMatchThreshold}`);let i=[];return r.similarity<1&&i.push(`Fuzzy match: similarity ${r.similarity.toFixed(2)}`),{resolvedTo:r.index,confidence:r.similarity,warnings:i.length>0?i:void 0}}resolveShortFormCase(e){let t=this.context.citationIndex;for(let n=t-1;n>=0;n--){let r=this.citations[n];if(r.type===`case`&&r.volume===e.volume&&this.normalizeReporter(r.reporter)===this.normalizeReporter(e.reporter))return this.isWithinScope(n,t)?{resolvedTo:n,confidence:.95}:this.createFailureResult(`Matching citation outside scope boundary`)}return this.createFailureResult(`No matching full case citation found`)}trackFullCitation(e,t){if(e.type===`case`){let n=this.extractPartyName(e);if(n){let e=this.normalizePartyName(n);this.context.fullCitationHistory.set(e,t)}}}extractPartyName(e){let t=e.span.originalStart,n=Math.max(0,t-100),r=this.text.substring(n,t),i=r.match(/([A-Z][a-zA-Z]*(?:\s+[A-Z][a-zA-Z]*)*)\s+v\.?\s+[A-Z][a-zA-Z]*(?:\s+[A-Z][a-zA-Z]*)*,\s*$/);if(i)return this.stripSignalWords(i[1].trim());let a=r.match(/([A-Z][a-zA-Z]*(?:\s+[A-Z][a-zA-Z]*)*),\s*$/);if(a)return this.stripSignalWords(a[1].trim())}stripSignalWords(e){let t=e.replace(/^(?:In(?!\s+re\b)|See(?:\s+[Aa]lso)?|Compare|But(?:\s+[Ss]ee)?|Cf\.?|Also)\s+/i,``).trim();return t.length>0?t:e}normalizePartyName(e){return e.toLowerCase().replace(/\s+/g,` `).trim()}normalizeReporter(e){return e.toLowerCase().replace(/\s+/g,``).replace(/\./g,``)}isWithinScope(e,t){return j(e,t,this.context.paragraphMap,this.options.scopeStrategy)}createFailureResult(e){if(this.options.reportUnresolved)return{resolvedTo:void 0,failureReason:e,confidence:0}}};function F(e,t,n){return new P(e,t,n).resolve()}function I(e,t){let n=performance.now(),{cleaned:r,transformationMap:i,warnings:a}=l(e,t?.cleaners),o=g(r,t?.patterns||[...m,...h,...d,...f,...p]),s=[],c=new Set;for(let e of o){let t=`${e.span.cleanStart}-${e.span.cleanEnd}`;c.has(t)||(c.add(t),s.push(e))}let u=[];for(let e of s){let t;switch(e.type){case`case`:t=e.patternId===`id`||e.patternId===`ibid`?D(e,i):e.patternId===`supra`?O(e,i):e.patternId===`shortFormCase`?k(e,i):b(e,i,r);break;case`statute`:t=x(e,i);break;case`journal`:t=S(e,i);break;case`neutral`:t=C(e,i);break;case`publicLaw`:t=w(e,i);break;case`federalRegister`:t=T(e,i);break;case`statutesAtLarge`:t=E(e,i);break;default:continue}a.length>0&&(t.warnings=[...t.warnings||[],...a]),t.processTimeMs=performance.now()-n,u.push(t)}return t?.resolve?F(u,e,t.resolutionOptions):u}async function L(e,t){return I(e,t)}exports.DocumentResolver=P,exports.assertUnreachable=i,exports.cleanText=l,exports.extractCase=b,exports.extractCitations=I,exports.extractCitationsAsync=L,exports.extractFederalRegister=T,exports.extractJournal=S,exports.extractNeutral=C,exports.extractPublicLaw=w,exports.extractStatute=x,exports.extractStatutesAtLarge=E,exports.isCaseCitation=n,exports.isCitationType=r,exports.isFullCitation=e,exports.isShortFormCitation=t,exports.resolveCitations=F,exports.tokenize=g;
2
2
  //# sourceMappingURL=index.cjs.map