paperlint 10.1.0 → 10.1.1
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/package.json
CHANGED
|
@@ -184,10 +184,19 @@ if [ -f "$BLG" ]; then
|
|
|
184
184
|
grep -E "^(You're|I'm skipping|Repeated entry|I couldn't open)" "$BLG" | sed 's/^/ /' | head -12
|
|
185
185
|
fi
|
|
186
186
|
# A cited key that never made it into the .bbl is the same failure seen from the other side.
|
|
187
|
+
# An IEEEtran BST control entry (`@IEEEtranBSTCTL`, activated by `\bstctlcite{key}`) is cited
|
|
188
|
+
# in the .aux like any key, but IEEEtran reads it as configuration and never prints it as a
|
|
189
|
+
# \bibitem — so it is not a missing reference. A key is exempt only when IEEEtran itself reports
|
|
190
|
+
# reading it as a control entry: the .blg line `** IEEEtran BST control entry "key" detected.`,
|
|
191
|
+
# which every IEEEtran*.bst prints. BibTeX wrote that line after parsing the build's own databases,
|
|
192
|
+
# so a record in a .bib the build does not read, inside `@comment{…}`, or misspelled exempts
|
|
193
|
+
# nothing, and every layout BibTeX accepts is recognised without parsing .bib files here.
|
|
187
194
|
if [ -f "$BASE.aux" ] && [ -f "$BASE.bbl" ]; then
|
|
188
195
|
missing=0
|
|
196
|
+
ctl=$(sed -n 's/^\*\* IEEEtran BST control entry "\(.*\)" detected\.$/\1/p' "$BASE.blg" 2>/dev/null | sort -u)
|
|
189
197
|
while read -r key; do
|
|
190
198
|
[ -z "$key" ] && continue
|
|
199
|
+
printf '%s\n' "$ctl" | grep -qxF -- "$key" && continue
|
|
191
200
|
grep -qF "{$key}" "$BASE.bbl" || { echo " cited but NOT in the bibliography: $key"; missing=$((missing+1)); }
|
|
192
201
|
done < <(grep -oE '\\citation\{[^}]*\}' "$BASE.aux" | sed 's/.*{//;s/}//' | tr ',' '\n' | sort -u)
|
|
193
202
|
[ "$missing" -gt 0 ] && { echo " CITED-BUT-ABSENT references: $missing"; blgerr=$((blgerr+missing)); }
|
|
@@ -295,3 +295,105 @@ await checkSkill("render-paper");
|
|
|
295
295
|
: ` under ${root}/`),
|
|
296
296
|
);
|
|
297
297
|
}
|
|
298
|
+
|
|
299
|
+
// ── AN IEEEtran BST CONTROL ENTRY IS NOT A MISSING REFERENCE ─────────────────
|
|
300
|
+
// `\\bstctlcite{key}` cites an `@IEEEtranBSTCTL{key, …}` entry, so the key lands in the .aux like any
|
|
301
|
+
// citation, but IEEEtran reads it as configuration and never prints a \\bibitem for it. The
|
|
302
|
+
// "cited but NOT in the bibliography" check failed a real IEEE paper on exactly that key (an
|
|
303
|
+
// "et al. after six authors" setting). The exemption comes only from IEEEtran's own .blg line
|
|
304
|
+
// `** IEEEtran BST control entry "key" detected.`: BibTeX wrote it after parsing the build's
|
|
305
|
+
// databases, so a record BibTeX never read (a .bib the build does not use, a record inside
|
|
306
|
+
// `@comment{…}`) or a misspelled key exempts nothing, and a genuinely missing key is still reported.
|
|
307
|
+
{
|
|
308
|
+
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
309
|
+
const CHECK = join(HERE, "check-render.sh");
|
|
310
|
+
// `detected` = the keys IEEEtran reported in the .blg as control entries it read.
|
|
311
|
+
const paper = (citations, detected = ["BSTcontrol"]) => {
|
|
312
|
+
const dir = realpathSync(mkdtempSync(join(tmpdir(), "bstctl-")));
|
|
313
|
+
writeFileSync(
|
|
314
|
+
join(dir, "paper.tex"),
|
|
315
|
+
"\\documentclass{IEEEtran}\n\\begin{document}\n\\bstctlcite{BSTcontrol}\nText \\cite{real}.\n\\bibliographystyle{IEEEtran}\n\\bibliography{refs}\n\\end{document}\n",
|
|
316
|
+
);
|
|
317
|
+
writeFileSync(
|
|
318
|
+
join(dir, "paper.aux"),
|
|
319
|
+
citations.map((k) => `\\citation{${k}}`).join("\n") +
|
|
320
|
+
"\n\\bibstyle{IEEEtran}\n\\bibdata{refs}\n",
|
|
321
|
+
);
|
|
322
|
+
writeFileSync(
|
|
323
|
+
join(dir, "paper.bbl"),
|
|
324
|
+
"\\begin{thebibliography}{1}\n\\bibitem{real}\nA real reference, 2026.\n\\end{thebibliography}\n",
|
|
325
|
+
);
|
|
326
|
+
writeFileSync(
|
|
327
|
+
join(dir, "paper.blg"),
|
|
328
|
+
"This is BibTeX, Version 0.99e\nDatabase file #1: refs.bib\n-- IEEEtran.bst version 1.14 (2015/08/26) by Michael Shell.\n" +
|
|
329
|
+
detected
|
|
330
|
+
.map((k) => `** IEEEtran BST control entry "${k}" detected.\n`)
|
|
331
|
+
.join("") +
|
|
332
|
+
"\nDone.\n",
|
|
333
|
+
);
|
|
334
|
+
writeFileSync(
|
|
335
|
+
join(dir, "paper.log"),
|
|
336
|
+
"This is pdfTeX\nOutput written on paper.pdf (1 page, 1000 bytes).\n",
|
|
337
|
+
);
|
|
338
|
+
const r = spawnSync("bash", [CHECK, dir, "paper"], {
|
|
339
|
+
encoding: "utf8",
|
|
340
|
+
env: { ...process.env, NO_COMPILE: "1" },
|
|
341
|
+
});
|
|
342
|
+
// The script must run to its verdict: a run that stopped early prints no complaint either, and
|
|
343
|
+
// "no complaint" is what the exemption case asserts. stderr and the bash version name the cause.
|
|
344
|
+
assert.match(
|
|
345
|
+
r.stdout,
|
|
346
|
+
/^(PASS|FAIL)\b/m,
|
|
347
|
+
`check-render.sh stopped before its verdict (exit ${r.status}, ${BASH_VERSION}):\n` +
|
|
348
|
+
`--- stdout\n${r.stdout}--- stderr\n${r.stderr}`,
|
|
349
|
+
);
|
|
350
|
+
return r;
|
|
351
|
+
};
|
|
352
|
+
const BASH_VERSION = spawnSync("bash", ["--version"], {
|
|
353
|
+
encoding: "utf8",
|
|
354
|
+
}).stdout.split("\n")[0];
|
|
355
|
+
|
|
356
|
+
const ctlOnly = paper(["BSTcontrol", "real"]);
|
|
357
|
+
assert.doesNotMatch(
|
|
358
|
+
ctlOnly.stdout,
|
|
359
|
+
/CITED-BUT-ABSENT/,
|
|
360
|
+
`a control key IEEEtran reported reading was flagged as a missing reference:\n${ctlOnly.stdout}`,
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
// A key that starts with "-" is still a key, not a grep option.
|
|
364
|
+
const dashKey = paper(["-ctl", "real"], ["-ctl"]);
|
|
365
|
+
assert.doesNotMatch(
|
|
366
|
+
dashKey.stdout,
|
|
367
|
+
/CITED-BUT-ABSENT/,
|
|
368
|
+
`a control key starting with "-" was flagged:\n${dashKey.stdout}`,
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
// A misspelled \\bstctlcite key: IEEEtran detected a different key, so this one is not exempt.
|
|
372
|
+
const typo = paper(["BSTcontrl", "real"]);
|
|
373
|
+
assert.match(
|
|
374
|
+
typo.stdout,
|
|
375
|
+
/cited but NOT in the bibliography: BSTcontrl/,
|
|
376
|
+
`a \\bstctlcite key IEEEtran did not report must be flagged:\n${typo.stdout}`,
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
// A record BibTeX never read — in a .bib the build does not use, or inside @comment{…} — leaves
|
|
380
|
+
// no "detected" line, so the key is not exempt.
|
|
381
|
+
const unread = paper(["BSTcontrol", "real"], []);
|
|
382
|
+
assert.match(
|
|
383
|
+
unread.stdout,
|
|
384
|
+
/cited but NOT in the bibliography: BSTcontrol/,
|
|
385
|
+
`a control key IEEEtran never reported reading must be flagged:\n${unread.stdout}`,
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
const withGap = paper(["BSTcontrol", "real", "gone"]);
|
|
389
|
+
assert.match(
|
|
390
|
+
withGap.stdout,
|
|
391
|
+
/cited but NOT in the bibliography: gone/,
|
|
392
|
+
`a key with no \\bibitem must still be reported:\n${withGap.stdout}`,
|
|
393
|
+
);
|
|
394
|
+
assert.doesNotMatch(
|
|
395
|
+
withGap.stdout,
|
|
396
|
+
/bibliography: BSTcontrol/,
|
|
397
|
+
withGap.stdout,
|
|
398
|
+
);
|
|
399
|
+
}
|