eyecite-ts 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -8
- package/dist/annotate/index.cjs.map +1 -1
- package/dist/annotate/index.d.cts +1 -1
- package/dist/annotate/index.d.mts +1 -1
- package/dist/annotate/index.mjs.map +1 -1
- package/dist/{citation-25ZydLsu.d.mts → citation-BwXdJTA9.d.mts} +177 -12
- package/dist/citation-BwXdJTA9.d.mts.map +1 -0
- package/dist/{citation-Cymq3pJ-.d.cts → citation-By8QXtGC.d.cts} +177 -12
- package/dist/citation-By8QXtGC.d.cts.map +1 -0
- package/dist/data/index.cjs.map +1 -1
- package/dist/data/index.d.cts +90 -90
- package/dist/data/index.d.cts.map +1 -1
- package/dist/data/index.d.mts +90 -90
- package/dist/data/index.d.mts.map +1 -1
- package/dist/data/index.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -128
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +110 -128
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/knownCodes-CI-vnoBO.cjs.map +1 -1
- package/dist/knownCodes-MkDSiR1j.mjs.map +1 -1
- package/dist/types-BfYnmSHC.d.mts +115 -0
- package/dist/types-BfYnmSHC.d.mts.map +1 -0
- package/dist/types-C_5aOCZ1.d.cts +115 -0
- package/dist/types-C_5aOCZ1.d.cts.map +1 -0
- package/dist/utils/index.cjs +7 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +122 -0
- package/dist/utils/index.d.cts.map +1 -0
- package/dist/utils/index.d.mts +122 -0
- package/dist/utils/index.d.mts.map +1 -0
- package/dist/utils/index.mjs +7 -0
- package/dist/utils/index.mjs.map +1 -0
- package/package.json +10 -1
- package/dist/citation-25ZydLsu.d.mts.map +0 -1
- package/dist/citation-Cymq3pJ-.d.cts.map +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { t as Citation, x as ShortFormCitation } from "./citation-By8QXtGC.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/footnotes/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* A detected footnote zone in the text.
|
|
6
|
+
* Positions are in input-text (raw) coordinates.
|
|
7
|
+
*/
|
|
8
|
+
interface FootnoteZone {
|
|
9
|
+
/** Start position in input-text coordinates */
|
|
10
|
+
start: number;
|
|
11
|
+
/** End position in input-text coordinates */
|
|
12
|
+
end: number;
|
|
13
|
+
/** Footnote number (1, 2, 3...) */
|
|
14
|
+
footnoteNumber: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Result of footnote detection — sorted by start position.
|
|
18
|
+
*/
|
|
19
|
+
type FootnoteMap = FootnoteZone[];
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/resolve/types.d.ts
|
|
22
|
+
/**
|
|
23
|
+
* Scope boundary strategy for resolution.
|
|
24
|
+
* Determines how far back to search for antecedent citations.
|
|
25
|
+
*/
|
|
26
|
+
type ScopeStrategy = "paragraph" | "section" | "footnote" | "none";
|
|
27
|
+
/**
|
|
28
|
+
* Options for citation resolution.
|
|
29
|
+
*/
|
|
30
|
+
interface ResolutionOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Scope boundary strategy (default: 'paragraph')
|
|
33
|
+
* - paragraph: Only resolve within same paragraph
|
|
34
|
+
* - section: Only resolve within same section
|
|
35
|
+
* - footnote: Only resolve within same footnote
|
|
36
|
+
* - none: Resolve across entire document
|
|
37
|
+
*/
|
|
38
|
+
scopeStrategy?: ScopeStrategy;
|
|
39
|
+
/**
|
|
40
|
+
* Auto-detect paragraph boundaries from text (default: true)
|
|
41
|
+
* Uses paragraphBoundaryPattern to split text
|
|
42
|
+
*/
|
|
43
|
+
autoDetectParagraphs?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Regex pattern to detect paragraph boundaries (default: /\n\n+/)
|
|
46
|
+
* Only used if autoDetectParagraphs is true
|
|
47
|
+
*/
|
|
48
|
+
paragraphBoundaryPattern?: RegExp;
|
|
49
|
+
/**
|
|
50
|
+
* Enable fuzzy party name matching for supra resolution (default: true)
|
|
51
|
+
* Uses Levenshtein distance to handle typos and variations
|
|
52
|
+
*/
|
|
53
|
+
fuzzyPartyMatching?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Similarity threshold for fuzzy party matching (default: 0.8)
|
|
56
|
+
* Range: 0-1 where 1.0 is exact match
|
|
57
|
+
* Only used if fuzzyPartyMatching is true
|
|
58
|
+
*/
|
|
59
|
+
partyMatchThreshold?: number;
|
|
60
|
+
/**
|
|
61
|
+
* Allow Id. citations to resolve to other short-form citations (default: false)
|
|
62
|
+
* If true: "Smith v. Jones, 500 F.2d 100" -> "Id." -> "Id. at 105"
|
|
63
|
+
* If false: Second Id. fails to resolve (no full citation between them)
|
|
64
|
+
*/
|
|
65
|
+
allowNestedResolution?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Report unresolved citations with failure reasons (default: true)
|
|
68
|
+
* If false: resolution field will be undefined for unresolved citations
|
|
69
|
+
*/
|
|
70
|
+
reportUnresolved?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Footnote zone map for footnote-aware scoping.
|
|
73
|
+
* When scopeStrategy is "footnote" and this is provided, citations are
|
|
74
|
+
* scoped by footnote zones instead of paragraphs.
|
|
75
|
+
*/
|
|
76
|
+
footnoteMap?: FootnoteMap | undefined;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Result of resolving a short-form citation.
|
|
80
|
+
*/
|
|
81
|
+
interface ResolutionResult {
|
|
82
|
+
/**
|
|
83
|
+
* Index of the citation this resolves to.
|
|
84
|
+
* undefined if resolution failed
|
|
85
|
+
*/
|
|
86
|
+
resolvedTo?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Reason for resolution failure (if any)
|
|
89
|
+
*/
|
|
90
|
+
failureReason?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Warnings about ambiguous or uncertain resolutions
|
|
93
|
+
*/
|
|
94
|
+
warnings?: string[];
|
|
95
|
+
/**
|
|
96
|
+
* Confidence in the resolution (0-1)
|
|
97
|
+
* Factors: party name similarity, scope boundary, citation type match
|
|
98
|
+
*/
|
|
99
|
+
confidence: number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Citation with resolution metadata.
|
|
103
|
+
*
|
|
104
|
+
* Uses a distributive conditional type so that `resolution` is only
|
|
105
|
+
* meaningfully present on short-form citations (Id., supra, short-form case).
|
|
106
|
+
* On full citations, `resolution` is typed as `undefined`.
|
|
107
|
+
*/
|
|
108
|
+
type ResolvedCitation<C extends Citation = Citation> = C extends ShortFormCitation ? C & {
|
|
109
|
+
resolution: ResolutionResult | undefined;
|
|
110
|
+
} : C & {
|
|
111
|
+
resolution?: undefined;
|
|
112
|
+
};
|
|
113
|
+
//#endregion
|
|
114
|
+
export { FootnoteMap as a, ScopeStrategy as i, ResolutionResult as n, FootnoteZone as o, ResolvedCitation as r, ResolutionOptions as t };
|
|
115
|
+
//# sourceMappingURL=types-C_5aOCZ1.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-C_5aOCZ1.d.cts","names":[],"sources":["../src/footnotes/types.ts","../src/resolve/types.ts"],"mappings":";;;;;;AAIA;UAAiB,YAAA;;EAEf,KAAA;;EAEA,GAAA;;EAEA,cAAA;AAAA;AAMF;;;AAAA,KAAY,WAAA,GAAc,YAAA;;;;;;;KCFd,aAAA;;;;UAKK,iBAAA;;;;AALjB;;;;EAaE,aAAA,GAAgB,aAAA;EARlB;;;;EAcE,oBAAA;;;;;EAMA,wBAAA,GAA2B,MAAA;;;;;EAM3B,kBAAA;;;;;;EAOA,mBAAA;EA0BF;;;;;EAnBE,qBAAA;;;;;EAMA,gBAAA;EA4CU;;;;;EArCV,WAAA,GAAc,WAAA;AAAA;;;;UAMC,gBAAA;;;;;EAKf,UAAA;;;;EAKA,aAAA;;;;EAKA,QAAA;;;;;EAMA,UAAA;AAAA;;;;;;;;KAUU,gBAAA,WAA2B,QAAA,GAAW,QAAA,IAAY,CAAA,SAAU,iBAAA,GACpE,CAAA;EAAM,UAAA,EAAY,gBAAA;AAAA,IAClB,CAAA;EAAM,UAAA;AAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e,t,n){return n===void 0?`${e} ${t}`:`${e} ${t} ${n}`}function t(t){let n=t.normalizedReporter??t.reporter,r=t.hasBlankPage?void 0:t.page;return e(t.volume,n,r)}function n(n){let r=[t(n)];if(n.parallelCitations?.length)for(let t of n.parallelCitations)r.push(e(t.volume,t.reporter,t.page));return r}function r(e){let t=[[10,`X`],[9,`IX`],[5,`V`],[4,`IV`],[1,`I`]],n=``,r=e;for(let[e,i]of t)for(;r>=e;)n+=i,r-=e;return n}function i(e){switch(e.type){case`case`:{let t=e.normalizedReporter??e.reporter,n;n=e.hasBlankPage?` ___`:e.page===void 0?``:` ${e.page}`;let r=`${e.volume} ${t}${n}`,i=e.pincite===void 0?``:`, ${e.pincite}`,a=e.year===void 0?``:` (${e.year})`;return`${e.caseName?`${e.caseName}, `:``}${r}${i}${a}`}case`statute`:{let t=e.title===void 0?``:`${e.title} `,n=`\u00A7 ${e.section}`,r=e.subsection??``,i=e.hasEtSeq?` et seq.`:``;return`${t}${e.code} ${n}${r}${i}`}case`constitutional`:{let t=`${e.jurisdiction===`US`?`U.S.`:e.jurisdiction??``} Const.`,n=``;return e.article!==void 0&&(n+=` art. ${r(e.article)}`),e.amendment!==void 0&&(n+=` amend. ${r(e.amendment)}`),e.section!==void 0&&(n+=`, \u00A7 ${e.section}`),e.clause!==void 0&&(n+=`, cl. ${e.clause}`),`${t}${n}`}case`journal`:{let t=e.volume===void 0?``:`${e.volume} `,n=e.page===void 0?``:` ${e.page}`,r=e.pincite===void 0?``:`, ${e.pincite}`,i=e.year===void 0?``:` (${e.year})`;return`${t}${e.abbreviation}${n}${r}${i}`}case`neutral`:return`${e.year} ${e.court} ${e.documentNumber}`;case`publicLaw`:return`Pub. L. No. ${e.congress}-${e.lawNumber}`;case`federalRegister`:{let t=e.year===void 0?``:` (${e.year})`;return`${e.volume} Fed. Reg. ${e.page}${t}`}case`statutesAtLarge`:return`${e.volume} Stat. ${e.page}`;case`id`:return e.pincite===void 0?`Id.`:`Id. at ${e.pincite}`;case`supra`:return e.pincite===void 0?`${e.partyName}, supra`:`${e.partyName}, supra, at ${e.pincite}`;case`shortFormCase`:{let t=e.reporter;if(e.pincite!==void 0)return`${e.volume} ${t} at ${e.pincite}`;let n=e.page===void 0?``:` ${e.page}`;return`${e.volume} ${t}${n}`}}}function a(e){return`${e.volume}-${e.reporter}-${e.page??`blank`}`}function o(e){return e.type===`case`}function s(e){return e.resolution}function c(e){let t=new Map,r=new Map,i=[];for(let s=0;s<e.length;s++){let c=e[s];if(!o(c))continue;let l=c.groupId,u=a(c),d=(l?r.get(l):void 0)??r.get(u);if(d!==void 0)i[d].mentions.push(c),t.set(s,d);else{let e=i.length,a={primaryCitation:c,mentions:[c],parallelCitations:n(c)};i.push(a),t.set(s,e),r.set(u,e),l&&r.set(l,e)}}for(let n=0;n<e.length;n++){let r=e[n];if(r.type!==`id`&&r.type!==`supra`&&r.type!==`shortFormCase`)continue;let a=s(r);if(a?.resolvedTo===void 0)continue;let o=t.get(a.resolvedTo);o!==void 0&&(i[o].mentions.push(r),t.set(n,o))}for(let e of i)e.mentions.sort((e,t)=>e.span.originalStart-t.span.originalStart);return i}const l=new Set(`v,vs,U.S,S.Ct,S. Ct,L.Ed,L. Ed,F,F.2d,F.3d,F.4th,F.Supp,F. Supp,A.2d,A.3d,N.E,N.E.2d,N.W,N.W.2d,S.E,S.E.2d,S.W,S.W.2d,S.W.3d,So,So.2d,So.3d,P,P.2d,P.3d,No,Nos,Inc,Corp,Ltd,Co,Ass'n,Dept,Dist,Cir,App,Supp,Rev,Stat,Const,Mr,Mrs,Ms,Dr,Jr,Sr,St,Ct,Atl,Cal,Fla,Ill,Tex,Pa,Md,Va,Wis,Minn,Mich,Mass,Conn,Colo,Ariz,Ark,Ga,La,Ind,Kan,Ky,Miss,Mo,Neb,Nev,Okla,Or,Tenn,Vt,Wash,Wyo,Del,Haw,Ida,Me,Mont,R.I,S.C,S.D,N.C,N.D,N.J,N.M,N.Y,W.Va,U.S.C,C.F.R,Fed,Reg,Pub,Amend,Sec,Art,Cl,Ch,Pt,Vol,Ed,Harv,Yale,Stan,Colum,Geo`.split(`,`));function u(e,t){let n=t;for(;n>0&&e[n-1]!==` `&&e[n-1]!==`
|
|
2
|
+
`;)n--;let r=e.slice(n,t);if(r.length===1&&/[A-Z]/.test(r)){let r=t+1<e.length?e[t+1]:``;if((n>0?e[n-1]:``)===`.`||/[A-Za-z0-9]/.test(r))return!0}let i=r.replace(/\.$/g,``);return!!(l.has(i)||l.has(r))}function d(e,t){for(let n=t-1;n>=0;n--){let r=e[n];if(r===`.`||r===`?`||r===`!`){if(r===`.`&&u(e,n))continue;let i=n+1;if(i<e.length&&/\s/.test(e[i])){let n=i;for(;n<t&&/\s/.test(e[n]);)n++;return n}}}return 0}function f(e,t){for(let n=t;n<e.length;n++){let t=e[n];if(t===`.`||t===`?`||t===`!`){if(t===`.`&&u(e,n))continue;return n+1}}return e.length}function p(e,t,n){let r=n?.type??`sentence`,i=n?.maxLength,a,o;if(r===`paragraph`){let n=e.lastIndexOf(`
|
|
3
|
+
|
|
4
|
+
`,t.start);a=n===-1?0:n+2;let r=e.indexOf(`
|
|
5
|
+
|
|
6
|
+
`,t.end);o=r===-1?e.length:r}else a=d(e,t.start),o=f(e,t.end);let s=e.slice(a,o),c=s.trim(),l=a+(s.length-s.trimStart().length),u=o-(s.length-s.trimEnd().length);if(i&&c.length>i){let e=c.slice(0,i);return{text:e,span:{start:l,end:l+e.length}}}return{text:c,span:{start:l,end:u}}}exports.getSurroundingContext=p,exports.groupByCase=c,exports.toBluebook=i,exports.toReporterKey=t,exports.toReporterKeys=n;
|
|
7
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/utils/reporterKey.ts","../../src/utils/bluebook.ts","../../src/utils/groupByCase.ts","../../src/utils/context.ts"],"sourcesContent":["import type { FullCaseCitation } from \"../types/citation\"\n\n/**\n * Format a volume-reporter-page key from citation fields.\n */\nfunction formatKey(volume: number | string, reporter: string, page: number | undefined): string {\n if (page === undefined) {\n return `${volume} ${reporter}`\n }\n return `${volume} ${reporter} ${page}`\n}\n\n/**\n * Extract the volume-reporter-page lookup key from a case citation.\n *\n * Strips case name, pincite, year, and parenthetical.\n * Uses `normalizedReporter` when available, falls back to `reporter`.\n * Omits the page for blank-page citations.\n *\n * @example\n * ```typescript\n * toReporterKey(citation) // \"550 U.S. 544\"\n * ```\n */\nexport function toReporterKey(citation: FullCaseCitation): string {\n const reporter = citation.normalizedReporter ?? citation.reporter\n const page = citation.hasBlankPage ? undefined : citation.page\n return formatKey(citation.volume, reporter, page)\n}\n\n/**\n * Extract all volume-reporter-page lookup keys from a case citation,\n * including parallel citations.\n *\n * Returns the primary key first, followed by any parallel citation keys.\n *\n * @example\n * ```typescript\n * toReporterKeys(citation) // [\"410 U.S. 113\", \"93 S. Ct. 705\"]\n * ```\n */\nexport function toReporterKeys(citation: FullCaseCitation): string[] {\n const keys = [toReporterKey(citation)]\n\n if (citation.parallelCitations?.length) {\n for (const p of citation.parallelCitations) {\n keys.push(formatKey(p.volume, p.reporter, p.page))\n }\n }\n\n return keys\n}\n","import type { Citation } from \"../types/citation\"\n\n/** Convert an integer to a Roman numeral (1-27 covers all amendments + articles). */\nfunction toRoman(n: number): string {\n const numerals: Array<[number, string]> = [\n [10, \"X\"],\n [9, \"IX\"],\n [5, \"V\"],\n [4, \"IV\"],\n [1, \"I\"],\n ]\n let result = \"\"\n let remaining = n\n for (const [value, numeral] of numerals) {\n while (remaining >= value) {\n result += numeral\n remaining -= value\n }\n }\n return result\n}\n\n/**\n * Reconstruct a canonical Bluebook-style citation string from structured fields.\n *\n * Works across all 11 citation types via the discriminated union.\n * Best-effort: uses whatever fields are available on the citation object.\n *\n * @example\n * ```typescript\n * toBluebook(caseCitation) // \"Bell Atl. Corp. v. Twombly, 550 U.S. 544 (2007)\"\n * toBluebook(statuteCite) // \"42 U.S.C. § 1983\"\n * toBluebook(idCite) // \"Id. at 570\"\n * ```\n */\nexport function toBluebook(citation: Citation): string {\n switch (citation.type) {\n case \"case\": {\n const reporter = citation.normalizedReporter ?? citation.reporter\n let pageStr: string\n if (citation.hasBlankPage) {\n pageStr = \" ___\"\n } else if (citation.page !== undefined) {\n pageStr = ` ${citation.page}`\n } else {\n pageStr = \"\"\n }\n\n const core = `${citation.volume} ${reporter}${pageStr}`\n const pincite = citation.pincite !== undefined ? `, ${citation.pincite}` : \"\"\n const year = citation.year !== undefined ? ` (${citation.year})` : \"\"\n const caseName = citation.caseName ? `${citation.caseName}, ` : \"\"\n\n return `${caseName}${core}${pincite}${year}`\n }\n\n case \"statute\": {\n const title = citation.title !== undefined ? `${citation.title} ` : \"\"\n const section = `\\u00A7 ${citation.section}`\n const subsection = citation.subsection ?? \"\"\n const etSeq = citation.hasEtSeq ? \" et seq.\" : \"\"\n return `${title}${citation.code} ${section}${subsection}${etSeq}`\n }\n\n case \"constitutional\": {\n const jurisdiction = citation.jurisdiction === \"US\" ? \"U.S.\" : (citation.jurisdiction ?? \"\")\n const prefix = `${jurisdiction} Const.`\n\n let body = \"\"\n if (citation.article !== undefined) {\n body += ` art. ${toRoman(citation.article)}`\n }\n if (citation.amendment !== undefined) {\n body += ` amend. ${toRoman(citation.amendment)}`\n }\n if (citation.section !== undefined) {\n body += `, \\u00A7 ${citation.section}`\n }\n if (citation.clause !== undefined) {\n body += `, cl. ${citation.clause}`\n }\n return `${prefix}${body}`\n }\n\n case \"journal\": {\n const vol = citation.volume !== undefined ? `${citation.volume} ` : \"\"\n const page = citation.page !== undefined ? ` ${citation.page}` : \"\"\n const pincite = citation.pincite !== undefined ? `, ${citation.pincite}` : \"\"\n const year = citation.year !== undefined ? ` (${citation.year})` : \"\"\n return `${vol}${citation.abbreviation}${page}${pincite}${year}`\n }\n\n case \"neutral\":\n return `${citation.year} ${citation.court} ${citation.documentNumber}`\n\n case \"publicLaw\":\n return `Pub. L. No. ${citation.congress}-${citation.lawNumber}`\n\n case \"federalRegister\": {\n const year = citation.year !== undefined ? ` (${citation.year})` : \"\"\n return `${citation.volume} Fed. Reg. ${citation.page}${year}`\n }\n\n case \"statutesAtLarge\":\n return `${citation.volume} Stat. ${citation.page}`\n\n case \"id\":\n return citation.pincite !== undefined ? `Id. at ${citation.pincite}` : \"Id.\"\n\n case \"supra\":\n return citation.pincite !== undefined\n ? `${citation.partyName}, supra, at ${citation.pincite}`\n : `${citation.partyName}, supra`\n\n case \"shortFormCase\": {\n const reporter = citation.reporter\n if (citation.pincite !== undefined) {\n return `${citation.volume} ${reporter} at ${citation.pincite}`\n }\n const page = citation.page !== undefined ? ` ${citation.page}` : \"\"\n return `${citation.volume} ${reporter}${page}`\n }\n }\n}\n","import type { Citation, FullCaseCitation } from \"../types/citation\"\nimport type { ResolvedCitation, ResolutionResult } from \"../resolve/types\"\nimport type { CaseGroup } from \"./types\"\nimport { toReporterKeys } from \"./reporterKey\"\n\n/**\n * Build a lookup key for a full case citation: \"volume-reporter-page\".\n * Used to group duplicate full citations that lack a parallel groupId.\n */\nfunction citeKey(c: FullCaseCitation): string {\n return `${c.volume}-${c.reporter}-${c.page ?? \"blank\"}`\n}\n\n/** Type guard: narrow a Citation to FullCaseCitation after checking type === \"case\". */\nfunction isFullCase(cite: Citation): cite is FullCaseCitation {\n return cite.type === \"case\"\n}\n\n/** Extract resolution from a resolved short-form citation. */\nfunction getResolution(cite: ResolvedCitation): ResolutionResult | undefined {\n return (cite as ResolvedCitation & { resolution?: ResolutionResult }).resolution\n}\n\n/**\n * Group resolved citations by underlying case.\n *\n * Composes parallel linking, resolution, and volume/reporter/page identity\n * into `CaseGroup` objects. Non-case citations are ignored. Unresolved\n * short-form citations are excluded.\n *\n * @example\n * ```typescript\n * const citations = extractCitations(text)\n * const resolved = resolveCitations(citations, text)\n * const groups = groupByCase(resolved)\n * ```\n */\nexport function groupByCase(citations: ResolvedCitation[]): CaseGroup[] {\n // Map from citation index -> group index (for short-form resolution lookup)\n const indexToGroup = new Map<number, number>()\n // Map from groupId or citeKey -> group index (for dedup)\n const keyToGroup = new Map<string, number>()\n const groups: CaseGroup[] = []\n\n // First pass: assign full case citations to groups\n for (let i = 0; i < citations.length; i++) {\n const cite = citations[i]\n if (!isFullCase(cite)) continue\n\n // Check if this citation belongs to an existing group\n const gid = cite.groupId\n const key = citeKey(cite)\n const existingIdx = (gid ? keyToGroup.get(gid) : undefined) ?? keyToGroup.get(key)\n\n if (existingIdx !== undefined) {\n // Add to existing group\n groups[existingIdx].mentions.push(cite)\n indexToGroup.set(i, existingIdx)\n } else {\n // Create new group\n const groupIdx = groups.length\n const group: CaseGroup = {\n primaryCitation: cite,\n mentions: [cite],\n parallelCitations: toReporterKeys(cite),\n }\n groups.push(group)\n indexToGroup.set(i, groupIdx)\n keyToGroup.set(key, groupIdx)\n if (gid) {\n keyToGroup.set(gid, groupIdx)\n }\n }\n }\n\n // Second pass: assign short-form citations to their resolved group\n for (let i = 0; i < citations.length; i++) {\n const cite = citations[i]\n if (cite.type !== \"id\" && cite.type !== \"supra\" && cite.type !== \"shortFormCase\") continue\n\n const resolution = getResolution(cite)\n if (resolution?.resolvedTo === undefined) continue\n\n const groupIdx = indexToGroup.get(resolution.resolvedTo)\n if (groupIdx === undefined) continue\n\n groups[groupIdx].mentions.push(cite)\n indexToGroup.set(i, groupIdx)\n }\n\n // Sort mentions within each group by document position\n for (const group of groups) {\n group.mentions.sort((a, b) => a.span.originalStart - b.span.originalStart)\n }\n\n return groups\n}\n","import type { ContextOptions, SurroundingContext } from \"./types\"\n\n/**\n * Legal abbreviations that contain periods but are NOT sentence boundaries.\n * Kept as a static set in this file — does NOT import from src/data/\n * to preserve tree-shaking of the utils entry point.\n */\nconst LEGAL_ABBREVIATIONS = new Set([\n // Court and case abbreviations\n \"v\",\n \"vs\",\n // Reporter abbreviations (common ones)\n \"U.S\",\n \"S.Ct\",\n \"S. Ct\",\n \"L.Ed\",\n \"L. Ed\",\n \"F\",\n \"F.2d\",\n \"F.3d\",\n \"F.4th\",\n \"F.Supp\",\n \"F. Supp\",\n \"A.2d\",\n \"A.3d\",\n \"N.E\",\n \"N.E.2d\",\n \"N.W\",\n \"N.W.2d\",\n \"S.E\",\n \"S.E.2d\",\n \"S.W\",\n \"S.W.2d\",\n \"S.W.3d\",\n \"So\",\n \"So.2d\",\n \"So.3d\",\n \"P\",\n \"P.2d\",\n \"P.3d\",\n // Titles and procedural terms\n \"No\",\n \"Nos\",\n \"Inc\",\n \"Corp\",\n \"Ltd\",\n \"Co\",\n \"Ass'n\",\n \"Dept\",\n \"Dist\",\n \"Cir\",\n \"App\",\n \"Supp\",\n \"Rev\",\n \"Stat\",\n \"Const\",\n // General legal abbreviations\n \"Mr\",\n \"Mrs\",\n \"Ms\",\n \"Dr\",\n \"Jr\",\n \"Sr\",\n \"St\",\n \"Ct\",\n \"Atl\",\n \"Cal\",\n \"Fla\",\n \"Ill\",\n \"Tex\",\n \"Pa\",\n \"Md\",\n \"Va\",\n \"Wis\",\n \"Minn\",\n \"Mich\",\n \"Mass\",\n \"Conn\",\n \"Colo\",\n \"Ariz\",\n \"Ark\",\n \"Ga\",\n \"La\",\n \"Ind\",\n \"Kan\",\n \"Ky\",\n \"Miss\",\n \"Mo\",\n \"Neb\",\n \"Nev\",\n \"Okla\",\n \"Or\",\n \"Tenn\",\n \"Vt\",\n \"Wash\",\n \"Wyo\",\n \"Del\",\n \"Haw\",\n \"Ida\",\n \"Me\",\n \"Mont\",\n \"R.I\",\n \"S.C\",\n \"S.D\",\n \"N.C\",\n \"N.D\",\n \"N.J\",\n \"N.M\",\n \"N.Y\",\n \"W.Va\",\n // Federal abbreviations\n \"U.S.C\",\n \"C.F.R\",\n \"Fed\",\n \"Reg\",\n \"Pub\",\n \"Amend\",\n \"Sec\",\n \"Art\",\n \"Cl\",\n \"Ch\",\n \"Pt\",\n \"Vol\",\n \"Ed\",\n \"Harv\",\n \"Yale\",\n \"Stan\",\n \"Colum\",\n \"Geo\",\n])\n\n/**\n * Check if a period at the given position is likely an abbreviation,\n * not a sentence boundary.\n */\nfunction isAbbreviationPeriod(text: string, dotIndex: number): boolean {\n // Look backwards from the dot to find the word\n let wordStart = dotIndex\n while (wordStart > 0 && text[wordStart - 1] !== \" \" && text[wordStart - 1] !== \"\\n\") {\n wordStart--\n }\n\n const word = text.slice(wordStart, dotIndex)\n\n // Single letter followed by period (e.g., \"U.\", \"S.\", \"F.\")\n // Only treat as abbreviation if part of a dotted sequence:\n // - preceded by a period (like the \"S\" in \"U.S.\")\n // - followed by a letter/digit (like the \"F\" in \"F.2d\")\n if (word.length === 1 && /[A-Z]/.test(word)) {\n const charAfterDot = dotIndex + 1 < text.length ? text[dotIndex + 1] : \"\"\n const charBeforeWord = wordStart > 0 ? text[wordStart - 1] : \"\"\n if (charBeforeWord === \".\" || /[A-Za-z0-9]/.test(charAfterDot)) return true\n }\n\n // Check multi-character abbreviations (strip any trailing dots for lookup)\n const stripped = word.replace(/\\.$/g, \"\")\n if (LEGAL_ABBREVIATIONS.has(stripped)) return true\n\n // Check if the word itself (with internal dots) is known: \"U.S\", \"F.2d\", etc.\n if (LEGAL_ABBREVIATIONS.has(word)) return true\n\n // Number followed by period (ordinals like \"1.\" in list context — not sentence end if no space+uppercase follows)\n // This is handled by the caller's space+uppercase check\n\n return false\n}\n\n/**\n * Find the start of the sentence containing the given position.\n */\nfunction findSentenceStart(text: string, pos: number): number {\n for (let i = pos - 1; i >= 0; i--) {\n const ch = text[i]\n if (ch === \".\" || ch === \"?\" || ch === \"!\") {\n if (ch === \".\" && isAbbreviationPeriod(text, i)) continue\n\n // Check if followed by whitespace (the char after this terminator)\n const next = i + 1\n if (next < text.length && /\\s/.test(text[next])) {\n // Skip whitespace to find the start of the next sentence\n let start = next\n while (start < pos && /\\s/.test(text[start])) start++\n return start\n }\n }\n }\n return 0\n}\n\n/**\n * Find the end of the sentence containing the given position.\n */\nfunction findSentenceEnd(text: string, pos: number): number {\n for (let i = pos; i < text.length; i++) {\n const ch = text[i]\n if (ch === \".\" || ch === \"?\" || ch === \"!\") {\n if (ch === \".\" && isAbbreviationPeriod(text, i)) continue\n return i + 1\n }\n }\n return text.length\n}\n\n/**\n * Find the enclosing sentence or paragraph around a citation span.\n *\n * Legal-text-aware: periods in reporter abbreviations, court names,\n * and procedural terms (Corp., U.S., F.3d, No., v.) are not treated\n * as sentence boundaries.\n *\n * @example\n * ```typescript\n * const ctx = getSurroundingContext(text, { start: 33, end: 52 })\n * // ctx.text: \"In Smith v. Doe, 500 F.2d 123 (2020), the Court held X.\"\n * // ctx.span: { start: 16, end: 71 }\n * ```\n */\nexport function getSurroundingContext(\n text: string,\n span: { start: number; end: number },\n options?: ContextOptions,\n): SurroundingContext {\n const type = options?.type ?? \"sentence\"\n const maxLength = options?.maxLength\n\n let start: number\n let end: number\n\n if (type === \"paragraph\") {\n // Find paragraph boundaries (double newline)\n const beforeSpan = text.lastIndexOf(\"\\n\\n\", span.start)\n start = beforeSpan === -1 ? 0 : beforeSpan + 2\n const afterSpan = text.indexOf(\"\\n\\n\", span.end)\n end = afterSpan === -1 ? text.length : afterSpan\n } else {\n start = findSentenceStart(text, span.start)\n end = findSentenceEnd(text, span.end)\n }\n\n const raw = text.slice(start, end)\n const resultText = raw.trim()\n const trimmedStart = start + (raw.length - raw.trimStart().length)\n const trimmedEnd = end - (raw.length - raw.trimEnd().length)\n\n if (maxLength && resultText.length > maxLength) {\n const truncated = resultText.slice(0, maxLength)\n return {\n text: truncated,\n span: { start: trimmedStart, end: trimmedStart + truncated.length },\n }\n }\n\n return {\n text: resultText,\n span: { start: trimmedStart, end: trimmedEnd },\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { t as Citation, u as FullCaseCitation } from "../citation-By8QXtGC.cjs";
|
|
2
|
+
import { r as ResolvedCitation } from "../types-C_5aOCZ1.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for surrounding context extraction.
|
|
7
|
+
*/
|
|
8
|
+
interface ContextOptions {
|
|
9
|
+
/** Boundary type (default: 'sentence') */
|
|
10
|
+
type?: "sentence" | "paragraph";
|
|
11
|
+
/** Max characters to return (default: 500) */
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result of surrounding context extraction.
|
|
16
|
+
*/
|
|
17
|
+
interface SurroundingContext {
|
|
18
|
+
/** The sentence or paragraph text */
|
|
19
|
+
text: string;
|
|
20
|
+
/** Absolute character offsets in the source document */
|
|
21
|
+
span: {
|
|
22
|
+
start: number;
|
|
23
|
+
end: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A group of citations all referring to the same underlying case.
|
|
28
|
+
*
|
|
29
|
+
* Produced by `groupByCase()` from resolved extraction results.
|
|
30
|
+
* Groups are ordered by first mention in the document.
|
|
31
|
+
*/
|
|
32
|
+
interface CaseGroup {
|
|
33
|
+
/** The first full citation encountered for this case */
|
|
34
|
+
primaryCitation: FullCaseCitation;
|
|
35
|
+
/** All mentions (full, short, id, supra) in document order */
|
|
36
|
+
mentions: ResolvedCitation[];
|
|
37
|
+
/** Distinct reporter strings: ["550 U.S. 544", "127 S. Ct. 1955"] */
|
|
38
|
+
parallelCitations: string[];
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/utils/reporterKey.d.ts
|
|
42
|
+
/**
|
|
43
|
+
* Extract the volume-reporter-page lookup key from a case citation.
|
|
44
|
+
*
|
|
45
|
+
* Strips case name, pincite, year, and parenthetical.
|
|
46
|
+
* Uses `normalizedReporter` when available, falls back to `reporter`.
|
|
47
|
+
* Omits the page for blank-page citations.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* toReporterKey(citation) // "550 U.S. 544"
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function toReporterKey(citation: FullCaseCitation): string;
|
|
55
|
+
/**
|
|
56
|
+
* Extract all volume-reporter-page lookup keys from a case citation,
|
|
57
|
+
* including parallel citations.
|
|
58
|
+
*
|
|
59
|
+
* Returns the primary key first, followed by any parallel citation keys.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* toReporterKeys(citation) // ["410 U.S. 113", "93 S. Ct. 705"]
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function toReporterKeys(citation: FullCaseCitation): string[];
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/utils/bluebook.d.ts
|
|
69
|
+
/**
|
|
70
|
+
* Reconstruct a canonical Bluebook-style citation string from structured fields.
|
|
71
|
+
*
|
|
72
|
+
* Works across all 11 citation types via the discriminated union.
|
|
73
|
+
* Best-effort: uses whatever fields are available on the citation object.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* toBluebook(caseCitation) // "Bell Atl. Corp. v. Twombly, 550 U.S. 544 (2007)"
|
|
78
|
+
* toBluebook(statuteCite) // "42 U.S.C. § 1983"
|
|
79
|
+
* toBluebook(idCite) // "Id. at 570"
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
declare function toBluebook(citation: Citation): string;
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/utils/groupByCase.d.ts
|
|
85
|
+
/**
|
|
86
|
+
* Group resolved citations by underlying case.
|
|
87
|
+
*
|
|
88
|
+
* Composes parallel linking, resolution, and volume/reporter/page identity
|
|
89
|
+
* into `CaseGroup` objects. Non-case citations are ignored. Unresolved
|
|
90
|
+
* short-form citations are excluded.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const citations = extractCitations(text)
|
|
95
|
+
* const resolved = resolveCitations(citations, text)
|
|
96
|
+
* const groups = groupByCase(resolved)
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function groupByCase(citations: ResolvedCitation[]): CaseGroup[];
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/utils/context.d.ts
|
|
102
|
+
/**
|
|
103
|
+
* Find the enclosing sentence or paragraph around a citation span.
|
|
104
|
+
*
|
|
105
|
+
* Legal-text-aware: periods in reporter abbreviations, court names,
|
|
106
|
+
* and procedural terms (Corp., U.S., F.3d, No., v.) are not treated
|
|
107
|
+
* as sentence boundaries.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const ctx = getSurroundingContext(text, { start: 33, end: 52 })
|
|
112
|
+
* // ctx.text: "In Smith v. Doe, 500 F.2d 123 (2020), the Court held X."
|
|
113
|
+
* // ctx.span: { start: 16, end: 71 }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
declare function getSurroundingContext(text: string, span: {
|
|
117
|
+
start: number;
|
|
118
|
+
end: number;
|
|
119
|
+
}, options?: ContextOptions): SurroundingContext;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { type CaseGroup, type ContextOptions, type SurroundingContext, getSurroundingContext, groupByCase, toBluebook, toReporterKey, toReporterKeys };
|
|
122
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/utils/types.ts","../../src/utils/reporterKey.ts","../../src/utils/bluebook.ts","../../src/utils/groupByCase.ts","../../src/utils/context.ts"],"mappings":";;;;;;AAMA;UAAiB,cAAA;;EAEf,IAAA;EAEA;EAAA,SAAA;AAAA;;;;UAMe,kBAAA;;EAEf,IAAA;;EAEA,IAAA;IAAQ,KAAA;IAAe,GAAA;EAAA;AAAA;;;;;;;UASR,SAAA;;EAEf,eAAA,EAAiB,gBAAA;;EAEjB,QAAA,EAAU,gBAAA;ECTI;EDWd,iBAAA;AAAA;;;;;;AA7BF;;;;;AAUA;;;;iBCQgB,aAAA,CAAc,QAAA,EAAU,gBAAA;;;;;;ADKxC;;;;;;iBCYgB,cAAA,CAAe,QAAA,EAAU,gBAAA;;;;;;ADnCzC;;;;;AAUA;;;;;iBEmBgB,UAAA,CAAW,QAAA,EAAU,QAAA;;;;;AF7BrC;;;;;AAUA;;;;;;;iBGqBgB,WAAA,CAAY,SAAA,EAAW,gBAAA,KAAqB,SAAA;;;;;;AH/B5D;;;;;AAUA;;;;;;iBIyMgB,qBAAA,CACd,IAAA,UACA,IAAA;EAAQ,KAAA;EAAe,GAAA;AAAA,GACvB,OAAA,GAAU,cAAA,GACT,kBAAA"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { t as Citation, u as FullCaseCitation } from "../citation-BwXdJTA9.mjs";
|
|
2
|
+
import { r as ResolvedCitation } from "../types-BfYnmSHC.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for surrounding context extraction.
|
|
7
|
+
*/
|
|
8
|
+
interface ContextOptions {
|
|
9
|
+
/** Boundary type (default: 'sentence') */
|
|
10
|
+
type?: "sentence" | "paragraph";
|
|
11
|
+
/** Max characters to return (default: 500) */
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Result of surrounding context extraction.
|
|
16
|
+
*/
|
|
17
|
+
interface SurroundingContext {
|
|
18
|
+
/** The sentence or paragraph text */
|
|
19
|
+
text: string;
|
|
20
|
+
/** Absolute character offsets in the source document */
|
|
21
|
+
span: {
|
|
22
|
+
start: number;
|
|
23
|
+
end: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A group of citations all referring to the same underlying case.
|
|
28
|
+
*
|
|
29
|
+
* Produced by `groupByCase()` from resolved extraction results.
|
|
30
|
+
* Groups are ordered by first mention in the document.
|
|
31
|
+
*/
|
|
32
|
+
interface CaseGroup {
|
|
33
|
+
/** The first full citation encountered for this case */
|
|
34
|
+
primaryCitation: FullCaseCitation;
|
|
35
|
+
/** All mentions (full, short, id, supra) in document order */
|
|
36
|
+
mentions: ResolvedCitation[];
|
|
37
|
+
/** Distinct reporter strings: ["550 U.S. 544", "127 S. Ct. 1955"] */
|
|
38
|
+
parallelCitations: string[];
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/utils/reporterKey.d.ts
|
|
42
|
+
/**
|
|
43
|
+
* Extract the volume-reporter-page lookup key from a case citation.
|
|
44
|
+
*
|
|
45
|
+
* Strips case name, pincite, year, and parenthetical.
|
|
46
|
+
* Uses `normalizedReporter` when available, falls back to `reporter`.
|
|
47
|
+
* Omits the page for blank-page citations.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* toReporterKey(citation) // "550 U.S. 544"
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
declare function toReporterKey(citation: FullCaseCitation): string;
|
|
55
|
+
/**
|
|
56
|
+
* Extract all volume-reporter-page lookup keys from a case citation,
|
|
57
|
+
* including parallel citations.
|
|
58
|
+
*
|
|
59
|
+
* Returns the primary key first, followed by any parallel citation keys.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* toReporterKeys(citation) // ["410 U.S. 113", "93 S. Ct. 705"]
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare function toReporterKeys(citation: FullCaseCitation): string[];
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/utils/bluebook.d.ts
|
|
69
|
+
/**
|
|
70
|
+
* Reconstruct a canonical Bluebook-style citation string from structured fields.
|
|
71
|
+
*
|
|
72
|
+
* Works across all 11 citation types via the discriminated union.
|
|
73
|
+
* Best-effort: uses whatever fields are available on the citation object.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* toBluebook(caseCitation) // "Bell Atl. Corp. v. Twombly, 550 U.S. 544 (2007)"
|
|
78
|
+
* toBluebook(statuteCite) // "42 U.S.C. § 1983"
|
|
79
|
+
* toBluebook(idCite) // "Id. at 570"
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
declare function toBluebook(citation: Citation): string;
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/utils/groupByCase.d.ts
|
|
85
|
+
/**
|
|
86
|
+
* Group resolved citations by underlying case.
|
|
87
|
+
*
|
|
88
|
+
* Composes parallel linking, resolution, and volume/reporter/page identity
|
|
89
|
+
* into `CaseGroup` objects. Non-case citations are ignored. Unresolved
|
|
90
|
+
* short-form citations are excluded.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const citations = extractCitations(text)
|
|
95
|
+
* const resolved = resolveCitations(citations, text)
|
|
96
|
+
* const groups = groupByCase(resolved)
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function groupByCase(citations: ResolvedCitation[]): CaseGroup[];
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/utils/context.d.ts
|
|
102
|
+
/**
|
|
103
|
+
* Find the enclosing sentence or paragraph around a citation span.
|
|
104
|
+
*
|
|
105
|
+
* Legal-text-aware: periods in reporter abbreviations, court names,
|
|
106
|
+
* and procedural terms (Corp., U.S., F.3d, No., v.) are not treated
|
|
107
|
+
* as sentence boundaries.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const ctx = getSurroundingContext(text, { start: 33, end: 52 })
|
|
112
|
+
* // ctx.text: "In Smith v. Doe, 500 F.2d 123 (2020), the Court held X."
|
|
113
|
+
* // ctx.span: { start: 16, end: 71 }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
declare function getSurroundingContext(text: string, span: {
|
|
117
|
+
start: number;
|
|
118
|
+
end: number;
|
|
119
|
+
}, options?: ContextOptions): SurroundingContext;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { type CaseGroup, type ContextOptions, type SurroundingContext, getSurroundingContext, groupByCase, toBluebook, toReporterKey, toReporterKeys };
|
|
122
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/utils/types.ts","../../src/utils/reporterKey.ts","../../src/utils/bluebook.ts","../../src/utils/groupByCase.ts","../../src/utils/context.ts"],"mappings":";;;;;;AAMA;UAAiB,cAAA;;EAEf,IAAA;EAEA;EAAA,SAAA;AAAA;;;;UAMe,kBAAA;;EAEf,IAAA;;EAEA,IAAA;IAAQ,KAAA;IAAe,GAAA;EAAA;AAAA;;;;;;;UASR,SAAA;;EAEf,eAAA,EAAiB,gBAAA;;EAEjB,QAAA,EAAU,gBAAA;ECTI;EDWd,iBAAA;AAAA;;;;;;AA7BF;;;;;AAUA;;;;iBCQgB,aAAA,CAAc,QAAA,EAAU,gBAAA;;;;;;ADKxC;;;;;;iBCYgB,cAAA,CAAe,QAAA,EAAU,gBAAA;;;;;;ADnCzC;;;;;AAUA;;;;;iBEmBgB,UAAA,CAAW,QAAA,EAAU,QAAA;;;;;AF7BrC;;;;;AAUA;;;;;;;iBGqBgB,WAAA,CAAY,SAAA,EAAW,gBAAA,KAAqB,SAAA;;;;;;AH/B5D;;;;;AAUA;;;;;;iBIyMgB,qBAAA,CACd,IAAA,UACA,IAAA;EAAQ,KAAA;EAAe,GAAA;AAAA,GACvB,OAAA,GAAU,cAAA,GACT,kBAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
function e(e,t,n){return n===void 0?`${e} ${t}`:`${e} ${t} ${n}`}function t(t){let n=t.normalizedReporter??t.reporter,r=t.hasBlankPage?void 0:t.page;return e(t.volume,n,r)}function n(n){let r=[t(n)];if(n.parallelCitations?.length)for(let t of n.parallelCitations)r.push(e(t.volume,t.reporter,t.page));return r}function r(e){let t=[[10,`X`],[9,`IX`],[5,`V`],[4,`IV`],[1,`I`]],n=``,r=e;for(let[e,i]of t)for(;r>=e;)n+=i,r-=e;return n}function i(e){switch(e.type){case`case`:{let t=e.normalizedReporter??e.reporter,n;n=e.hasBlankPage?` ___`:e.page===void 0?``:` ${e.page}`;let r=`${e.volume} ${t}${n}`,i=e.pincite===void 0?``:`, ${e.pincite}`,a=e.year===void 0?``:` (${e.year})`;return`${e.caseName?`${e.caseName}, `:``}${r}${i}${a}`}case`statute`:{let t=e.title===void 0?``:`${e.title} `,n=`\u00A7 ${e.section}`,r=e.subsection??``,i=e.hasEtSeq?` et seq.`:``;return`${t}${e.code} ${n}${r}${i}`}case`constitutional`:{let t=`${e.jurisdiction===`US`?`U.S.`:e.jurisdiction??``} Const.`,n=``;return e.article!==void 0&&(n+=` art. ${r(e.article)}`),e.amendment!==void 0&&(n+=` amend. ${r(e.amendment)}`),e.section!==void 0&&(n+=`, \u00A7 ${e.section}`),e.clause!==void 0&&(n+=`, cl. ${e.clause}`),`${t}${n}`}case`journal`:{let t=e.volume===void 0?``:`${e.volume} `,n=e.page===void 0?``:` ${e.page}`,r=e.pincite===void 0?``:`, ${e.pincite}`,i=e.year===void 0?``:` (${e.year})`;return`${t}${e.abbreviation}${n}${r}${i}`}case`neutral`:return`${e.year} ${e.court} ${e.documentNumber}`;case`publicLaw`:return`Pub. L. No. ${e.congress}-${e.lawNumber}`;case`federalRegister`:{let t=e.year===void 0?``:` (${e.year})`;return`${e.volume} Fed. Reg. ${e.page}${t}`}case`statutesAtLarge`:return`${e.volume} Stat. ${e.page}`;case`id`:return e.pincite===void 0?`Id.`:`Id. at ${e.pincite}`;case`supra`:return e.pincite===void 0?`${e.partyName}, supra`:`${e.partyName}, supra, at ${e.pincite}`;case`shortFormCase`:{let t=e.reporter;if(e.pincite!==void 0)return`${e.volume} ${t} at ${e.pincite}`;let n=e.page===void 0?``:` ${e.page}`;return`${e.volume} ${t}${n}`}}}function a(e){return`${e.volume}-${e.reporter}-${e.page??`blank`}`}function o(e){return e.type===`case`}function s(e){return e.resolution}function c(e){let t=new Map,r=new Map,i=[];for(let s=0;s<e.length;s++){let c=e[s];if(!o(c))continue;let l=c.groupId,u=a(c),d=(l?r.get(l):void 0)??r.get(u);if(d!==void 0)i[d].mentions.push(c),t.set(s,d);else{let e=i.length,a={primaryCitation:c,mentions:[c],parallelCitations:n(c)};i.push(a),t.set(s,e),r.set(u,e),l&&r.set(l,e)}}for(let n=0;n<e.length;n++){let r=e[n];if(r.type!==`id`&&r.type!==`supra`&&r.type!==`shortFormCase`)continue;let a=s(r);if(a?.resolvedTo===void 0)continue;let o=t.get(a.resolvedTo);o!==void 0&&(i[o].mentions.push(r),t.set(n,o))}for(let e of i)e.mentions.sort((e,t)=>e.span.originalStart-t.span.originalStart);return i}const l=new Set(`v,vs,U.S,S.Ct,S. Ct,L.Ed,L. Ed,F,F.2d,F.3d,F.4th,F.Supp,F. Supp,A.2d,A.3d,N.E,N.E.2d,N.W,N.W.2d,S.E,S.E.2d,S.W,S.W.2d,S.W.3d,So,So.2d,So.3d,P,P.2d,P.3d,No,Nos,Inc,Corp,Ltd,Co,Ass'n,Dept,Dist,Cir,App,Supp,Rev,Stat,Const,Mr,Mrs,Ms,Dr,Jr,Sr,St,Ct,Atl,Cal,Fla,Ill,Tex,Pa,Md,Va,Wis,Minn,Mich,Mass,Conn,Colo,Ariz,Ark,Ga,La,Ind,Kan,Ky,Miss,Mo,Neb,Nev,Okla,Or,Tenn,Vt,Wash,Wyo,Del,Haw,Ida,Me,Mont,R.I,S.C,S.D,N.C,N.D,N.J,N.M,N.Y,W.Va,U.S.C,C.F.R,Fed,Reg,Pub,Amend,Sec,Art,Cl,Ch,Pt,Vol,Ed,Harv,Yale,Stan,Colum,Geo`.split(`,`));function u(e,t){let n=t;for(;n>0&&e[n-1]!==` `&&e[n-1]!==`
|
|
2
|
+
`;)n--;let r=e.slice(n,t);if(r.length===1&&/[A-Z]/.test(r)){let r=t+1<e.length?e[t+1]:``;if((n>0?e[n-1]:``)===`.`||/[A-Za-z0-9]/.test(r))return!0}let i=r.replace(/\.$/g,``);return!!(l.has(i)||l.has(r))}function d(e,t){for(let n=t-1;n>=0;n--){let r=e[n];if(r===`.`||r===`?`||r===`!`){if(r===`.`&&u(e,n))continue;let i=n+1;if(i<e.length&&/\s/.test(e[i])){let n=i;for(;n<t&&/\s/.test(e[n]);)n++;return n}}}return 0}function f(e,t){for(let n=t;n<e.length;n++){let t=e[n];if(t===`.`||t===`?`||t===`!`){if(t===`.`&&u(e,n))continue;return n+1}}return e.length}function p(e,t,n){let r=n?.type??`sentence`,i=n?.maxLength,a,o;if(r===`paragraph`){let n=e.lastIndexOf(`
|
|
3
|
+
|
|
4
|
+
`,t.start);a=n===-1?0:n+2;let r=e.indexOf(`
|
|
5
|
+
|
|
6
|
+
`,t.end);o=r===-1?e.length:r}else a=d(e,t.start),o=f(e,t.end);let s=e.slice(a,o),c=s.trim(),l=a+(s.length-s.trimStart().length),u=o-(s.length-s.trimEnd().length);if(i&&c.length>i){let e=c.slice(0,i);return{text:e,span:{start:l,end:l+e.length}}}return{text:c,span:{start:l,end:u}}}export{p as getSurroundingContext,c as groupByCase,i as toBluebook,t as toReporterKey,n as toReporterKeys};
|
|
7
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/reporterKey.ts","../../src/utils/bluebook.ts","../../src/utils/groupByCase.ts","../../src/utils/context.ts"],"sourcesContent":["import type { FullCaseCitation } from \"../types/citation\"\n\n/**\n * Format a volume-reporter-page key from citation fields.\n */\nfunction formatKey(volume: number | string, reporter: string, page: number | undefined): string {\n if (page === undefined) {\n return `${volume} ${reporter}`\n }\n return `${volume} ${reporter} ${page}`\n}\n\n/**\n * Extract the volume-reporter-page lookup key from a case citation.\n *\n * Strips case name, pincite, year, and parenthetical.\n * Uses `normalizedReporter` when available, falls back to `reporter`.\n * Omits the page for blank-page citations.\n *\n * @example\n * ```typescript\n * toReporterKey(citation) // \"550 U.S. 544\"\n * ```\n */\nexport function toReporterKey(citation: FullCaseCitation): string {\n const reporter = citation.normalizedReporter ?? citation.reporter\n const page = citation.hasBlankPage ? undefined : citation.page\n return formatKey(citation.volume, reporter, page)\n}\n\n/**\n * Extract all volume-reporter-page lookup keys from a case citation,\n * including parallel citations.\n *\n * Returns the primary key first, followed by any parallel citation keys.\n *\n * @example\n * ```typescript\n * toReporterKeys(citation) // [\"410 U.S. 113\", \"93 S. Ct. 705\"]\n * ```\n */\nexport function toReporterKeys(citation: FullCaseCitation): string[] {\n const keys = [toReporterKey(citation)]\n\n if (citation.parallelCitations?.length) {\n for (const p of citation.parallelCitations) {\n keys.push(formatKey(p.volume, p.reporter, p.page))\n }\n }\n\n return keys\n}\n","import type { Citation } from \"../types/citation\"\n\n/** Convert an integer to a Roman numeral (1-27 covers all amendments + articles). */\nfunction toRoman(n: number): string {\n const numerals: Array<[number, string]> = [\n [10, \"X\"],\n [9, \"IX\"],\n [5, \"V\"],\n [4, \"IV\"],\n [1, \"I\"],\n ]\n let result = \"\"\n let remaining = n\n for (const [value, numeral] of numerals) {\n while (remaining >= value) {\n result += numeral\n remaining -= value\n }\n }\n return result\n}\n\n/**\n * Reconstruct a canonical Bluebook-style citation string from structured fields.\n *\n * Works across all 11 citation types via the discriminated union.\n * Best-effort: uses whatever fields are available on the citation object.\n *\n * @example\n * ```typescript\n * toBluebook(caseCitation) // \"Bell Atl. Corp. v. Twombly, 550 U.S. 544 (2007)\"\n * toBluebook(statuteCite) // \"42 U.S.C. § 1983\"\n * toBluebook(idCite) // \"Id. at 570\"\n * ```\n */\nexport function toBluebook(citation: Citation): string {\n switch (citation.type) {\n case \"case\": {\n const reporter = citation.normalizedReporter ?? citation.reporter\n let pageStr: string\n if (citation.hasBlankPage) {\n pageStr = \" ___\"\n } else if (citation.page !== undefined) {\n pageStr = ` ${citation.page}`\n } else {\n pageStr = \"\"\n }\n\n const core = `${citation.volume} ${reporter}${pageStr}`\n const pincite = citation.pincite !== undefined ? `, ${citation.pincite}` : \"\"\n const year = citation.year !== undefined ? ` (${citation.year})` : \"\"\n const caseName = citation.caseName ? `${citation.caseName}, ` : \"\"\n\n return `${caseName}${core}${pincite}${year}`\n }\n\n case \"statute\": {\n const title = citation.title !== undefined ? `${citation.title} ` : \"\"\n const section = `\\u00A7 ${citation.section}`\n const subsection = citation.subsection ?? \"\"\n const etSeq = citation.hasEtSeq ? \" et seq.\" : \"\"\n return `${title}${citation.code} ${section}${subsection}${etSeq}`\n }\n\n case \"constitutional\": {\n const jurisdiction = citation.jurisdiction === \"US\" ? \"U.S.\" : (citation.jurisdiction ?? \"\")\n const prefix = `${jurisdiction} Const.`\n\n let body = \"\"\n if (citation.article !== undefined) {\n body += ` art. ${toRoman(citation.article)}`\n }\n if (citation.amendment !== undefined) {\n body += ` amend. ${toRoman(citation.amendment)}`\n }\n if (citation.section !== undefined) {\n body += `, \\u00A7 ${citation.section}`\n }\n if (citation.clause !== undefined) {\n body += `, cl. ${citation.clause}`\n }\n return `${prefix}${body}`\n }\n\n case \"journal\": {\n const vol = citation.volume !== undefined ? `${citation.volume} ` : \"\"\n const page = citation.page !== undefined ? ` ${citation.page}` : \"\"\n const pincite = citation.pincite !== undefined ? `, ${citation.pincite}` : \"\"\n const year = citation.year !== undefined ? ` (${citation.year})` : \"\"\n return `${vol}${citation.abbreviation}${page}${pincite}${year}`\n }\n\n case \"neutral\":\n return `${citation.year} ${citation.court} ${citation.documentNumber}`\n\n case \"publicLaw\":\n return `Pub. L. No. ${citation.congress}-${citation.lawNumber}`\n\n case \"federalRegister\": {\n const year = citation.year !== undefined ? ` (${citation.year})` : \"\"\n return `${citation.volume} Fed. Reg. ${citation.page}${year}`\n }\n\n case \"statutesAtLarge\":\n return `${citation.volume} Stat. ${citation.page}`\n\n case \"id\":\n return citation.pincite !== undefined ? `Id. at ${citation.pincite}` : \"Id.\"\n\n case \"supra\":\n return citation.pincite !== undefined\n ? `${citation.partyName}, supra, at ${citation.pincite}`\n : `${citation.partyName}, supra`\n\n case \"shortFormCase\": {\n const reporter = citation.reporter\n if (citation.pincite !== undefined) {\n return `${citation.volume} ${reporter} at ${citation.pincite}`\n }\n const page = citation.page !== undefined ? ` ${citation.page}` : \"\"\n return `${citation.volume} ${reporter}${page}`\n }\n }\n}\n","import type { Citation, FullCaseCitation } from \"../types/citation\"\nimport type { ResolvedCitation, ResolutionResult } from \"../resolve/types\"\nimport type { CaseGroup } from \"./types\"\nimport { toReporterKeys } from \"./reporterKey\"\n\n/**\n * Build a lookup key for a full case citation: \"volume-reporter-page\".\n * Used to group duplicate full citations that lack a parallel groupId.\n */\nfunction citeKey(c: FullCaseCitation): string {\n return `${c.volume}-${c.reporter}-${c.page ?? \"blank\"}`\n}\n\n/** Type guard: narrow a Citation to FullCaseCitation after checking type === \"case\". */\nfunction isFullCase(cite: Citation): cite is FullCaseCitation {\n return cite.type === \"case\"\n}\n\n/** Extract resolution from a resolved short-form citation. */\nfunction getResolution(cite: ResolvedCitation): ResolutionResult | undefined {\n return (cite as ResolvedCitation & { resolution?: ResolutionResult }).resolution\n}\n\n/**\n * Group resolved citations by underlying case.\n *\n * Composes parallel linking, resolution, and volume/reporter/page identity\n * into `CaseGroup` objects. Non-case citations are ignored. Unresolved\n * short-form citations are excluded.\n *\n * @example\n * ```typescript\n * const citations = extractCitations(text)\n * const resolved = resolveCitations(citations, text)\n * const groups = groupByCase(resolved)\n * ```\n */\nexport function groupByCase(citations: ResolvedCitation[]): CaseGroup[] {\n // Map from citation index -> group index (for short-form resolution lookup)\n const indexToGroup = new Map<number, number>()\n // Map from groupId or citeKey -> group index (for dedup)\n const keyToGroup = new Map<string, number>()\n const groups: CaseGroup[] = []\n\n // First pass: assign full case citations to groups\n for (let i = 0; i < citations.length; i++) {\n const cite = citations[i]\n if (!isFullCase(cite)) continue\n\n // Check if this citation belongs to an existing group\n const gid = cite.groupId\n const key = citeKey(cite)\n const existingIdx = (gid ? keyToGroup.get(gid) : undefined) ?? keyToGroup.get(key)\n\n if (existingIdx !== undefined) {\n // Add to existing group\n groups[existingIdx].mentions.push(cite)\n indexToGroup.set(i, existingIdx)\n } else {\n // Create new group\n const groupIdx = groups.length\n const group: CaseGroup = {\n primaryCitation: cite,\n mentions: [cite],\n parallelCitations: toReporterKeys(cite),\n }\n groups.push(group)\n indexToGroup.set(i, groupIdx)\n keyToGroup.set(key, groupIdx)\n if (gid) {\n keyToGroup.set(gid, groupIdx)\n }\n }\n }\n\n // Second pass: assign short-form citations to their resolved group\n for (let i = 0; i < citations.length; i++) {\n const cite = citations[i]\n if (cite.type !== \"id\" && cite.type !== \"supra\" && cite.type !== \"shortFormCase\") continue\n\n const resolution = getResolution(cite)\n if (resolution?.resolvedTo === undefined) continue\n\n const groupIdx = indexToGroup.get(resolution.resolvedTo)\n if (groupIdx === undefined) continue\n\n groups[groupIdx].mentions.push(cite)\n indexToGroup.set(i, groupIdx)\n }\n\n // Sort mentions within each group by document position\n for (const group of groups) {\n group.mentions.sort((a, b) => a.span.originalStart - b.span.originalStart)\n }\n\n return groups\n}\n","import type { ContextOptions, SurroundingContext } from \"./types\"\n\n/**\n * Legal abbreviations that contain periods but are NOT sentence boundaries.\n * Kept as a static set in this file — does NOT import from src/data/\n * to preserve tree-shaking of the utils entry point.\n */\nconst LEGAL_ABBREVIATIONS = new Set([\n // Court and case abbreviations\n \"v\",\n \"vs\",\n // Reporter abbreviations (common ones)\n \"U.S\",\n \"S.Ct\",\n \"S. Ct\",\n \"L.Ed\",\n \"L. Ed\",\n \"F\",\n \"F.2d\",\n \"F.3d\",\n \"F.4th\",\n \"F.Supp\",\n \"F. Supp\",\n \"A.2d\",\n \"A.3d\",\n \"N.E\",\n \"N.E.2d\",\n \"N.W\",\n \"N.W.2d\",\n \"S.E\",\n \"S.E.2d\",\n \"S.W\",\n \"S.W.2d\",\n \"S.W.3d\",\n \"So\",\n \"So.2d\",\n \"So.3d\",\n \"P\",\n \"P.2d\",\n \"P.3d\",\n // Titles and procedural terms\n \"No\",\n \"Nos\",\n \"Inc\",\n \"Corp\",\n \"Ltd\",\n \"Co\",\n \"Ass'n\",\n \"Dept\",\n \"Dist\",\n \"Cir\",\n \"App\",\n \"Supp\",\n \"Rev\",\n \"Stat\",\n \"Const\",\n // General legal abbreviations\n \"Mr\",\n \"Mrs\",\n \"Ms\",\n \"Dr\",\n \"Jr\",\n \"Sr\",\n \"St\",\n \"Ct\",\n \"Atl\",\n \"Cal\",\n \"Fla\",\n \"Ill\",\n \"Tex\",\n \"Pa\",\n \"Md\",\n \"Va\",\n \"Wis\",\n \"Minn\",\n \"Mich\",\n \"Mass\",\n \"Conn\",\n \"Colo\",\n \"Ariz\",\n \"Ark\",\n \"Ga\",\n \"La\",\n \"Ind\",\n \"Kan\",\n \"Ky\",\n \"Miss\",\n \"Mo\",\n \"Neb\",\n \"Nev\",\n \"Okla\",\n \"Or\",\n \"Tenn\",\n \"Vt\",\n \"Wash\",\n \"Wyo\",\n \"Del\",\n \"Haw\",\n \"Ida\",\n \"Me\",\n \"Mont\",\n \"R.I\",\n \"S.C\",\n \"S.D\",\n \"N.C\",\n \"N.D\",\n \"N.J\",\n \"N.M\",\n \"N.Y\",\n \"W.Va\",\n // Federal abbreviations\n \"U.S.C\",\n \"C.F.R\",\n \"Fed\",\n \"Reg\",\n \"Pub\",\n \"Amend\",\n \"Sec\",\n \"Art\",\n \"Cl\",\n \"Ch\",\n \"Pt\",\n \"Vol\",\n \"Ed\",\n \"Harv\",\n \"Yale\",\n \"Stan\",\n \"Colum\",\n \"Geo\",\n])\n\n/**\n * Check if a period at the given position is likely an abbreviation,\n * not a sentence boundary.\n */\nfunction isAbbreviationPeriod(text: string, dotIndex: number): boolean {\n // Look backwards from the dot to find the word\n let wordStart = dotIndex\n while (wordStart > 0 && text[wordStart - 1] !== \" \" && text[wordStart - 1] !== \"\\n\") {\n wordStart--\n }\n\n const word = text.slice(wordStart, dotIndex)\n\n // Single letter followed by period (e.g., \"U.\", \"S.\", \"F.\")\n // Only treat as abbreviation if part of a dotted sequence:\n // - preceded by a period (like the \"S\" in \"U.S.\")\n // - followed by a letter/digit (like the \"F\" in \"F.2d\")\n if (word.length === 1 && /[A-Z]/.test(word)) {\n const charAfterDot = dotIndex + 1 < text.length ? text[dotIndex + 1] : \"\"\n const charBeforeWord = wordStart > 0 ? text[wordStart - 1] : \"\"\n if (charBeforeWord === \".\" || /[A-Za-z0-9]/.test(charAfterDot)) return true\n }\n\n // Check multi-character abbreviations (strip any trailing dots for lookup)\n const stripped = word.replace(/\\.$/g, \"\")\n if (LEGAL_ABBREVIATIONS.has(stripped)) return true\n\n // Check if the word itself (with internal dots) is known: \"U.S\", \"F.2d\", etc.\n if (LEGAL_ABBREVIATIONS.has(word)) return true\n\n // Number followed by period (ordinals like \"1.\" in list context — not sentence end if no space+uppercase follows)\n // This is handled by the caller's space+uppercase check\n\n return false\n}\n\n/**\n * Find the start of the sentence containing the given position.\n */\nfunction findSentenceStart(text: string, pos: number): number {\n for (let i = pos - 1; i >= 0; i--) {\n const ch = text[i]\n if (ch === \".\" || ch === \"?\" || ch === \"!\") {\n if (ch === \".\" && isAbbreviationPeriod(text, i)) continue\n\n // Check if followed by whitespace (the char after this terminator)\n const next = i + 1\n if (next < text.length && /\\s/.test(text[next])) {\n // Skip whitespace to find the start of the next sentence\n let start = next\n while (start < pos && /\\s/.test(text[start])) start++\n return start\n }\n }\n }\n return 0\n}\n\n/**\n * Find the end of the sentence containing the given position.\n */\nfunction findSentenceEnd(text: string, pos: number): number {\n for (let i = pos; i < text.length; i++) {\n const ch = text[i]\n if (ch === \".\" || ch === \"?\" || ch === \"!\") {\n if (ch === \".\" && isAbbreviationPeriod(text, i)) continue\n return i + 1\n }\n }\n return text.length\n}\n\n/**\n * Find the enclosing sentence or paragraph around a citation span.\n *\n * Legal-text-aware: periods in reporter abbreviations, court names,\n * and procedural terms (Corp., U.S., F.3d, No., v.) are not treated\n * as sentence boundaries.\n *\n * @example\n * ```typescript\n * const ctx = getSurroundingContext(text, { start: 33, end: 52 })\n * // ctx.text: \"In Smith v. Doe, 500 F.2d 123 (2020), the Court held X.\"\n * // ctx.span: { start: 16, end: 71 }\n * ```\n */\nexport function getSurroundingContext(\n text: string,\n span: { start: number; end: number },\n options?: ContextOptions,\n): SurroundingContext {\n const type = options?.type ?? \"sentence\"\n const maxLength = options?.maxLength\n\n let start: number\n let end: number\n\n if (type === \"paragraph\") {\n // Find paragraph boundaries (double newline)\n const beforeSpan = text.lastIndexOf(\"\\n\\n\", span.start)\n start = beforeSpan === -1 ? 0 : beforeSpan + 2\n const afterSpan = text.indexOf(\"\\n\\n\", span.end)\n end = afterSpan === -1 ? text.length : afterSpan\n } else {\n start = findSentenceStart(text, span.start)\n end = findSentenceEnd(text, span.end)\n }\n\n const raw = text.slice(start, end)\n const resultText = raw.trim()\n const trimmedStart = start + (raw.length - raw.trimStart().length)\n const trimmedEnd = end - (raw.length - raw.trimEnd().length)\n\n if (maxLength && resultText.length > maxLength) {\n const truncated = resultText.slice(0, maxLength)\n return {\n text: truncated,\n span: { start: trimmedStart, end: trimmedStart + truncated.length },\n }\n }\n\n return {\n text: resultText,\n span: { start: trimmedStart, end: trimmedEnd },\n }\n}\n"],"mappings":"AAKA,SAAS,EAAU,EAAyB,EAAkB,EAAkC,CAI9F,OAHI,IAAS,IAAA,GACJ,GAAG,EAAO,GAAG,IAEf,GAAG,EAAO,GAAG,EAAS,GAAG,IAelC,SAAgB,EAAc,EAAoC,CAChE,IAAM,EAAW,EAAS,oBAAsB,EAAS,SACnD,EAAO,EAAS,aAAe,IAAA,GAAY,EAAS,KAC1D,OAAO,EAAU,EAAS,OAAQ,EAAU,EAAK,CAcnD,SAAgB,EAAe,EAAsC,CACnE,IAAM,EAAO,CAAC,EAAc,EAAS,CAAC,CAEtC,GAAI,EAAS,mBAAmB,OAC9B,IAAK,IAAM,KAAK,EAAS,kBACvB,EAAK,KAAK,EAAU,EAAE,OAAQ,EAAE,SAAU,EAAE,KAAK,CAAC,CAItD,OAAO,EC/CT,SAAS,EAAQ,EAAmB,CAClC,IAAM,EAAoC,CACxC,CAAC,GAAI,IAAI,CACT,CAAC,EAAG,KAAK,CACT,CAAC,EAAG,IAAI,CACR,CAAC,EAAG,KAAK,CACT,CAAC,EAAG,IAAI,CACT,CACG,EAAS,GACT,EAAY,EAChB,IAAK,GAAM,CAAC,EAAO,KAAY,EAC7B,KAAO,GAAa,GAClB,GAAU,EACV,GAAa,EAGjB,OAAO,EAgBT,SAAgB,EAAW,EAA4B,CACrD,OAAQ,EAAS,KAAjB,CACE,IAAK,OAAQ,CACX,IAAM,EAAW,EAAS,oBAAsB,EAAS,SACrD,EACJ,AAGE,EAHE,EAAS,aACD,OACD,EAAS,OAAS,IAAA,GAGjB,GAFA,IAAI,EAAS,OAKzB,IAAM,EAAO,GAAG,EAAS,OAAO,GAAG,IAAW,IACxC,EAAU,EAAS,UAAY,IAAA,GAAsC,GAA1B,KAAK,EAAS,UACzD,EAAO,EAAS,OAAS,IAAA,GAAoC,GAAxB,KAAK,EAAS,KAAK,GAG9D,MAAO,GAFU,EAAS,SAAW,GAAG,EAAS,SAAS,IAAM,KAE3C,IAAO,IAAU,IAGxC,IAAK,UAAW,CACd,IAAM,EAAQ,EAAS,QAAU,IAAA,GAAmC,GAAvB,GAAG,EAAS,MAAM,GACzD,EAAU,UAAU,EAAS,UAC7B,EAAa,EAAS,YAAc,GACpC,EAAQ,EAAS,SAAW,WAAa,GAC/C,MAAO,GAAG,IAAQ,EAAS,KAAK,GAAG,IAAU,IAAa,IAG5D,IAAK,iBAAkB,CAErB,IAAM,EAAS,GADM,EAAS,eAAiB,KAAO,OAAU,EAAS,cAAgB,GAC1D,SAE3B,EAAO,GAaX,OAZI,EAAS,UAAY,IAAA,KACvB,GAAQ,SAAS,EAAQ,EAAS,QAAQ,IAExC,EAAS,YAAc,IAAA,KACzB,GAAQ,WAAW,EAAQ,EAAS,UAAU,IAE5C,EAAS,UAAY,IAAA,KACvB,GAAQ,YAAY,EAAS,WAE3B,EAAS,SAAW,IAAA,KACtB,GAAQ,SAAS,EAAS,UAErB,GAAG,IAAS,IAGrB,IAAK,UAAW,CACd,IAAM,EAAM,EAAS,SAAW,IAAA,GAAoC,GAAxB,GAAG,EAAS,OAAO,GACzD,EAAO,EAAS,OAAS,IAAA,GAAkC,GAAtB,IAAI,EAAS,OAClD,EAAU,EAAS,UAAY,IAAA,GAAsC,GAA1B,KAAK,EAAS,UACzD,EAAO,EAAS,OAAS,IAAA,GAAoC,GAAxB,KAAK,EAAS,KAAK,GAC9D,MAAO,GAAG,IAAM,EAAS,eAAe,IAAO,IAAU,IAG3D,IAAK,UACH,MAAO,GAAG,EAAS,KAAK,GAAG,EAAS,MAAM,GAAG,EAAS,iBAExD,IAAK,YACH,MAAO,eAAe,EAAS,SAAS,GAAG,EAAS,YAEtD,IAAK,kBAAmB,CACtB,IAAM,EAAO,EAAS,OAAS,IAAA,GAAoC,GAAxB,KAAK,EAAS,KAAK,GAC9D,MAAO,GAAG,EAAS,OAAO,aAAa,EAAS,OAAO,IAGzD,IAAK,kBACH,MAAO,GAAG,EAAS,OAAO,SAAS,EAAS,OAE9C,IAAK,KACH,OAAO,EAAS,UAAY,IAAA,GAA2C,MAA/B,UAAU,EAAS,UAE7D,IAAK,QACH,OAAO,EAAS,UAAY,IAAA,GAExB,GAAG,EAAS,UAAU,SADtB,GAAG,EAAS,UAAU,cAAc,EAAS,UAGnD,IAAK,gBAAiB,CACpB,IAAM,EAAW,EAAS,SAC1B,GAAI,EAAS,UAAY,IAAA,GACvB,MAAO,GAAG,EAAS,OAAO,GAAG,EAAS,MAAM,EAAS,UAEvD,IAAM,EAAO,EAAS,OAAS,IAAA,GAAkC,GAAtB,IAAI,EAAS,OACxD,MAAO,GAAG,EAAS,OAAO,GAAG,IAAW,MC/G9C,SAAS,EAAQ,EAA6B,CAC5C,MAAO,GAAG,EAAE,OAAO,GAAG,EAAE,SAAS,GAAG,EAAE,MAAQ,UAIhD,SAAS,EAAW,EAA0C,CAC5D,OAAO,EAAK,OAAS,OAIvB,SAAS,EAAc,EAAsD,CAC3E,OAAQ,EAA8D,WAiBxE,SAAgB,EAAY,EAA4C,CAEtE,IAAM,EAAe,IAAI,IAEnB,EAAa,IAAI,IACjB,EAAsB,EAAE,CAG9B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAU,OAAQ,IAAK,CACzC,IAAM,EAAO,EAAU,GACvB,GAAI,CAAC,EAAW,EAAK,CAAE,SAGvB,IAAM,EAAM,EAAK,QACX,EAAM,EAAQ,EAAK,CACnB,GAAe,EAAM,EAAW,IAAI,EAAI,CAAG,IAAA,KAAc,EAAW,IAAI,EAAI,CAElF,GAAI,IAAgB,IAAA,GAElB,EAAO,GAAa,SAAS,KAAK,EAAK,CACvC,EAAa,IAAI,EAAG,EAAY,KAC3B,CAEL,IAAM,EAAW,EAAO,OAClB,EAAmB,CACvB,gBAAiB,EACjB,SAAU,CAAC,EAAK,CAChB,kBAAmB,EAAe,EAAK,CACxC,CACD,EAAO,KAAK,EAAM,CAClB,EAAa,IAAI,EAAG,EAAS,CAC7B,EAAW,IAAI,EAAK,EAAS,CACzB,GACF,EAAW,IAAI,EAAK,EAAS,EAMnC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAU,OAAQ,IAAK,CACzC,IAAM,EAAO,EAAU,GACvB,GAAI,EAAK,OAAS,MAAQ,EAAK,OAAS,SAAW,EAAK,OAAS,gBAAiB,SAElF,IAAM,EAAa,EAAc,EAAK,CACtC,GAAI,GAAY,aAAe,IAAA,GAAW,SAE1C,IAAM,EAAW,EAAa,IAAI,EAAW,WAAW,CACpD,IAAa,IAAA,KAEjB,EAAO,GAAU,SAAS,KAAK,EAAK,CACpC,EAAa,IAAI,EAAG,EAAS,EAI/B,IAAK,IAAM,KAAS,EAClB,EAAM,SAAS,MAAM,EAAG,IAAM,EAAE,KAAK,cAAgB,EAAE,KAAK,cAAc,CAG5E,OAAO,ECxFT,MAAM,EAAsB,IAAI,IAAI,qgBA0HnC,CAAC,CAMF,SAAS,EAAqB,EAAc,EAA2B,CAErE,IAAI,EAAY,EAChB,KAAO,EAAY,GAAK,EAAK,EAAY,KAAO,KAAO,EAAK,EAAY,KAAO;GAC7E,IAGF,IAAM,EAAO,EAAK,MAAM,EAAW,EAAS,CAM5C,GAAI,EAAK,SAAW,GAAK,QAAQ,KAAK,EAAK,CAAE,CAC3C,IAAM,EAAe,EAAW,EAAI,EAAK,OAAS,EAAK,EAAW,GAAK,GAEvE,IADuB,EAAY,EAAI,EAAK,EAAY,GAAK,MACtC,KAAO,cAAc,KAAK,EAAa,CAAE,MAAO,GAIzE,IAAM,EAAW,EAAK,QAAQ,OAAQ,GAAG,CASzC,MALA,GAHI,EAAoB,IAAI,EAAS,EAGjC,EAAoB,IAAI,EAAK,EAWnC,SAAS,EAAkB,EAAc,EAAqB,CAC5D,IAAK,IAAI,EAAI,EAAM,EAAG,GAAK,EAAG,IAAK,CACjC,IAAM,EAAK,EAAK,GAChB,GAAI,IAAO,KAAO,IAAO,KAAO,IAAO,IAAK,CAC1C,GAAI,IAAO,KAAO,EAAqB,EAAM,EAAE,CAAE,SAGjD,IAAM,EAAO,EAAI,EACjB,GAAI,EAAO,EAAK,QAAU,KAAK,KAAK,EAAK,GAAM,CAAE,CAE/C,IAAI,EAAQ,EACZ,KAAO,EAAQ,GAAO,KAAK,KAAK,EAAK,GAAO,EAAE,IAC9C,OAAO,IAIb,MAAO,GAMT,SAAS,EAAgB,EAAc,EAAqB,CAC1D,IAAK,IAAI,EAAI,EAAK,EAAI,EAAK,OAAQ,IAAK,CACtC,IAAM,EAAK,EAAK,GAChB,GAAI,IAAO,KAAO,IAAO,KAAO,IAAO,IAAK,CAC1C,GAAI,IAAO,KAAO,EAAqB,EAAM,EAAE,CAAE,SACjD,OAAO,EAAI,GAGf,OAAO,EAAK,OAiBd,SAAgB,EACd,EACA,EACA,EACoB,CACpB,IAAM,EAAO,GAAS,MAAQ,WACxB,EAAY,GAAS,UAEvB,EACA,EAEJ,GAAI,IAAS,YAAa,CAExB,IAAM,EAAa,EAAK,YAAY;;EAAQ,EAAK,MAAM,CACvD,EAAQ,IAAe,GAAK,EAAI,EAAa,EAC7C,IAAM,EAAY,EAAK,QAAQ;;EAAQ,EAAK,IAAI,CAChD,EAAM,IAAc,GAAK,EAAK,OAAS,OAEvC,EAAQ,EAAkB,EAAM,EAAK,MAAM,CAC3C,EAAM,EAAgB,EAAM,EAAK,IAAI,CAGvC,IAAM,EAAM,EAAK,MAAM,EAAO,EAAI,CAC5B,EAAa,EAAI,MAAM,CACvB,EAAe,GAAS,EAAI,OAAS,EAAI,WAAW,CAAC,QACrD,EAAa,GAAO,EAAI,OAAS,EAAI,SAAS,CAAC,QAErD,GAAI,GAAa,EAAW,OAAS,EAAW,CAC9C,IAAM,EAAY,EAAW,MAAM,EAAG,EAAU,CAChD,MAAO,CACL,KAAM,EACN,KAAM,CAAE,MAAO,EAAc,IAAK,EAAe,EAAU,OAAQ,CACpE,CAGH,MAAO,CACL,KAAM,EACN,KAAM,CAAE,MAAO,EAAc,IAAK,EAAY,CAC/C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eyecite-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "TypeScript port of eyecite - extract, resolve, and annotate legal citations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -18,6 +18,11 @@
|
|
|
18
18
|
"types": "./dist/annotate/index.d.ts",
|
|
19
19
|
"import": "./dist/annotate/index.mjs",
|
|
20
20
|
"require": "./dist/annotate/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./utils": {
|
|
23
|
+
"types": "./dist/utils/index.d.ts",
|
|
24
|
+
"import": "./dist/utils/index.mjs",
|
|
25
|
+
"require": "./dist/utils/index.cjs"
|
|
21
26
|
}
|
|
22
27
|
},
|
|
23
28
|
"main": "./dist/index.cjs",
|
|
@@ -45,6 +50,10 @@
|
|
|
45
50
|
{
|
|
46
51
|
"path": "dist/index.mjs",
|
|
47
52
|
"limit": "50 KB"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"path": "dist/utils/index.mjs",
|
|
56
|
+
"limit": "3 KB"
|
|
48
57
|
}
|
|
49
58
|
],
|
|
50
59
|
"keywords": [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"citation-25ZydLsu.d.mts","names":[],"sources":["../src/types/span.ts","../src/types/citation.ts"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"citation-Cymq3pJ-.d.cts","names":[],"sources":["../src/types/span.ts","../src/types/citation.ts"],"mappings":"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"}
|