openclerk-core
v0.3.0
Published
Platform-agnostic citation parsing, Bluebook rule-checking, and citation-lookup provider logic shared across OpenClerk's Word, Google Docs, and LibreOffice integrations.
Downloads
598
Readme
openclerk-core
Platform-agnostic citation parsing, Bluebook rule-checking, and citation-lookup provider logic shared across OpenClerk's Word add-in, and its planned Google Docs and LibreOffice integrations.
This package holds no document-editor-specific code — no Office.js, no Google Apps Script, no DOM APIs. It was extracted from openclerk-word so that logic doesn't have to be duplicated (or drift out of sync) across each platform integration.
What's in here
src/providers/— the citation-lookup provider plugin architecture (CitationProviderinterface, a registry, and implementations for CourtListener, Westlaw, LexisNexis, Bloomberg Law, and USPTO Patent Center), plus citation parsing (citationParser.ts), pincite-page handling (pincitePages.ts), and cited-opinion-text extraction (opinionTextExtractor.ts).citationParser.tsalso does eyecite-style citation resolution:extractCitationTokensfinds full, short-form (444 U.S. at 495),Id., andsupracitations in running text;clusterCitationTokensgroups them by which case each one refers to; andfindOrphanedCitationssurfaces a short-form/Id./supracitation with no resolvable antecedent.hallucinationCheck.ts'scheckCitationsForHallucinationschecks a list of citations against a list ofCitationProviders and reports any that none of them can verify — seetests/hallucinationCheck.test.ts, which runs this against real text from the Mata v. Avianca filing at the center of the widely reported ChatGPT-fabricated-citation incident, and confirms the two fabricated cases in it are correctly flagged as unverified. (The PDF itself, and the OCR pipeline used to recover its text, live in openclerk-web — that's a heavy, browser-upload-specific concern this platform-agnostic package deliberately doesn't carry.) Resolving a citation's locator (reporter/volume/page) is not the same as confirming the case is real — CourtListener's citation-lookup API, for one, resolves purely by locator, so it returns whatever real case is actually published there even if the case name typed alongside it names something else entirely.checkCitationsForHallucinationsguards against this withcaseNamesMatch: a provider result only counts asverifiedViawhen its returned case name actually corresponds to the citation's own parsed name; a locator that resolves to a genuine but differently-named case is reported via the result'snameMismatchfield instead — a stronger fabrication signal than a plain miss, since it means the reporter/volume/page is real but misattributed.src/bluebook/— Bluebook citation format-checking across the 20th/21st/22nd editions, including reporter/case-name/state abbreviation data vendored from reporters-db (src/bluebook/generated/) and a hand-maintainedmanualCorrections.tsfor community-contributed fixes.src/utils.ts— shared string/HTML helpers (text normalization, HTML escaping, hyperlink URL safety checks).
Usage
Published to the npm registry — a CI workflow (.github/workflows/publish.yml) runs npm
publish whenever a vX.Y.Z tag is pushed, authenticated via npm Trusted
Publishing (OIDC) rather than a stored token: no
NPM_TOKEN secret exists in this repo. prepare builds src/ -> lib/ at publish time, the
same as any other npm package; consumers never run a build step themselves.
Trusted Publishing requires a one-time setup on npmjs.com's package settings page (Settings ->
Trusted Publisher -> GitHub Actions), specifying this org/repo/workflow filename exactly. npm
doesn't allow configuring a trusted publisher for a package that doesn't exist yet, so the very
first publish of a new package has to happen manually (npm publish from an authenticated local
session) before trusted publishing can be turned on for every release after that.
{
"dependencies": {
"openclerk-core": "^0.2.6"
}
}import { parseCaseCitation, bluebookRuleSetRegistry, citationProviderRegistry } from "openclerk-core";(Earlier versions were consumed as a git dependency instead — abandoned because installing a git
dependency requires its prepare script to run at install time on the consumer's machine, which
some npm setups block behind an allowScripts allowlist that a fresh git dependency can't satisfy
due to a known npm/cli bug, even with an explicit
allowScripts entry. Registry installs don't have this problem: prepare only ever runs once, at
publish time, on this repo's own CI.)
Development
npm install
npm run build # compiles src/ -> lib/ (CommonJS + .d.ts)
npm test # runs the Jest suiteTo cut a release: bump version in package.json, merge, then git tag vX.Y.Z && git push origin
vX.Y.Z — the tag push triggers the publish workflow, which fails closed if the tag doesn't match
package.json's version.
To pick up upstream reporters-db updates:
npm run bluebook:update-dataLicense
MIT
