app/lib/publications/coins.mjs
44 lines and 2 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| coinsTitle | 21 to 48 | 11 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
| <anonymous:46> | 46 to 46 | 1 | No data: no coverage report in this map | No data: no coverage report in this map | No data: no mutants in this code |
Imports
It imports app/lib/publications/entities.mjs, app/lib/publications/exports.mjs. Imported by app/routes/publications.tsx.
Source
// COinS: Zotero and its relatives scan for .Z3988 and read only the title attribute, so the span stays
// empty. Index only: a list page cannot carry per-paper citation_* tags, and paper pages already do.
import { canonicalAuthor } from "./exports.mjs";
import { decodeEntities } from "./entities.mjs";
const GENRE = {
article: "article",
review: "article",
abstract: "conference",
chapter: "bookitem",
"teaching-resource": "document",
};
/**
* Key order is fixed so the output is a pure function of the values; check:machine-readable compares bytes.
*
* @param {any} paper
* @returns {string}
*/
export function coinsTitle(paper) {
/** @type {[string, string][]} */
const pairs = [
["ctx_ver", "Z39.88-2004"],
["rft_val_fmt", "info:ofi/fmt:kev:mtx:journal"],
["rft.genre", GENRE[/** @type {keyof typeof GENRE} */ (paper.type)] ?? "article"],
["rft.atitle", decodeEntities(paper.title)],
];
if (paper.journal) pairs.push(["rft.jtitle", decodeEntities(paper.journal)]);
if (paper.year) pairs.push(["rft.date", String(paper.year)]);
if (paper.volume) pairs.push(["rft.volume", String(paper.volume)]);
if (paper.issue) pairs.push(["rft.issue", String(paper.issue)]);
if (paper.firstPage) pairs.push(["rft.spage", paper.firstPage]);
if (paper.lastPage) pairs.push(["rft.epage", paper.lastPage]);
// One rft.au per author: a joined string reads as one author with a very long name.
for (const name of paper.authors ?? []) {
pairs.push(["rft.au", canonicalAuthor(name)]);
}
if (paper.doi) {
// info:doi/ is the form OpenURL specifies; a bare DOI in rft_id is not.
pairs.push(["rft_id", `info:doi/${paper.doi}`]);
}
// encodeURIComponent, not URLSearchParams, which encodes a space as +, a literal plus here.
return pairs
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join("&");
}