@citation-js/core

Parses and converts bibliographic metadata between BibTeX, CSL-JSON, RIS, Wikidata, and other citation formats through a pluggable parser architecture.

Library
npm
v0.8.2
208stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
66/100Good
Development Activity76
Maintenance36
Community72
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
79/100Good
Architecture80
Code Quality68
Innovation78
Learning Curve90

@citation-js/core is the engine behind Citation.js, a JavaScript library that normalizes bibliographic metadata from disparate sources - BibTeX, RIS, Wikidata JSON, BibJSON, and DOI records - into a common CSL-JSON representation, then re-exports it as formatted citations in styles like APA, Vancouver, and Chicago. The Cite class is the primary entry point: it accepts almost any recognizable input, parses it through a chain of registered format plugins, and exposes methods to add, sort, filter, and format the resulting reference list, either synchronously or through an async API for network-backed sources like Wikidata and DOI lookups.

Rather than hard-coding format support, core ships a plugin registry (plugins.add/plugins.input/plugins.output/plugins.dict) that lets separate packages - plugin-bibtex, plugin-csl, plugin-ris, plugin-doi, plugin-wikidata, plugin-bibjson, and third-party plugins - register their own input parsers, output formatters, and citation-style dictionaries at runtime. A companion Translator utility declaratively maps properties between a plugin’s native schema and CSL-JSON, so new format support can be added without touching core’s parsing logic.

What You Get

  • Cite class - constructor for parsing, storing, and reformatting bibliographic entries from almost any recognized input.
  • Plugin registry - plugins.add/remove/has/list API for registering input parsers, output formatters, and CSL dictionaries.
  • Translator utility - declarative source-to-target property mapping for converting between a plugin’s native schema and CSL-JSON.
  • Async API - Cite.async() for input sources that require network requests, like Wikidata and DOI lookups.
  • Graph-based input chain resolution - automatic format detection and parser chaining so callers don’t have to specify an input type.

Common Use Cases

  • Converting a BibTeX bibliography to APA- or Vancouver-formatted HTML for a webpage.
  • Normalizing citation exports from multiple reference managers into one CSL-JSON dataset.
  • Fetching and formatting a reference directly from a DOI or Wikidata identifier.
  • Building a custom citation-format plugin on top of a stable parsing/formatting core.

Under The Hood

Architecture The Cite class (packages/core/src/Cite/index.js) composes mixins - log, options, set, sort, get, static - onto its prototype via Object.assign rather than deep class inheritance, keeping each concern in its own file. Parsing is decoupled from the Cite class entirely: plugins/input/chain.js implements a ChainParser that treats format conversion as a graph-traversal problem - it repeatedly applies registered type/data parsers to walk the input’s format graph toward a target format (default @csl/list+object), recording each hop for debugging and enforcing a maxChainLength to avoid infinite loops. The plugin system (plugins/index.js) is an in-memory registry keyed by plugin reference, delegating to per-type registries (input, output, dict, config) via a small Register class. Because every one of the eight published packages in this monorepo (core, cli, and six format plugins) depends on this exact registry/chain-parser contract, changing chain resolution or the Register interface would require coordinated changes across the whole monorepo.

Tech Stack Plain ES-module JavaScript, transpiled via Babel to two output targets - a CommonJS lib/ build and an ES-module lib-mjs/ build - so consumers get both require() and import support from one source tree. The monorepo is managed with npm workspaces plus Lerna, with each of the eight sub-packages versioned and published independently. Core’s only runtime dependencies are two sibling packages, @citation-js/date and @citation-js/name, plus sync-fetch for synchronous HTTP requests so the non-async constructor can still resolve network-backed inputs like DOIs. Docs are generated with JSDoc from inline annotations, and CI runs on GitHub Actions.

Code Quality Tests use Mocha with expect.js (mocha -c -R dot -r @babel/register test/*.spec.js), run per-package via lerna run test; core’s suite covers iteration, save-log behavior, async/callback duality, and plugin re-registration against fixture data. Coverage is measured with nyc/istanbul and reported as lcov for CI. Linting is StandardJS via a shared Babel-aware ESLint parser, enforced in a preversion hook. There is no TypeScript - the codebase is untyped JS with JSDoc annotations standing in for static types, so there’s no compiler-level correctness guarantee, though error handling is largely explicit (cause-chained conversion errors, a strict option and chain-length guard on the parser).

API Design The public API favors minimal ceremony: new Cite(anything) auto-detects format through a type-parser registry instead of requiring callers to declare an input type, and the constructor doubles as a factory when called without new. The graph-based ChainParser is the most distinctive design choice for a citation library - plugins only need to define format detection and a to-CSL parser, and the chain resolver generically finds a path from any registered format to CSL-JSON, so adding a new format needs one converter into CSL rather than pairwise converters against every existing format. Documentation is thorough and tutorial-driven, and the two-line quick start (new Cite('Q21972834').format(...)) keeps first-use boilerplate low relative to comparable bibliography tooling.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search