Skip to content

Improvements for journal support including CSL specification - #3219

Closed
oscarlevin wants to merge 19 commits into
PreTeXtBook:masterfrom
oscarlevin:journal-csl
Closed

oscarlevin wants to merge 19 commits into
PreTeXtBook:masterfrom
oscarlevin:journal-csl

Conversation

@oscarlevin

@oscarlevin oscarlevin commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

Naming a journal in the publication file now selects that journal's Citation Style Language (CSL) style for references and citations, in every conversion. citeproc-py finds styles by name, through the citeproc-py-styles package, instead of PreTeXt downloading them.

  • Journals: journals/journals.xml gives each journal's style as citation-stylesheet-language/@style, the same element the publication file uses. The Guide's journal table has a new column for it.
  • Publisher variables: the default for csl-style-file comes from the journal. So the script, the CLI, references() and every conversion agree, with no stringparam. A style named in the publication file still wins.
  • Missing generated references: these no longer stop a conversion.
    • common.xsltproc() gives lxml a stand-in for the absent file, which is what the xsltproc executable effectively does.
    • Assembly detects it, reports it once (PTX:FALLBACK), and falls back to default formatting for citations and bibliography together.
    • The publisher-variable report never looks for the file.
  • Citations: read from $csl-file, so the publisher's generated directory is respected.
  • Script:
    • A style citeproc-py can't find is reported as an error, not raised.
    • The references write-error message names the right file.
  • Texstyles:
    • The Springer Nature class file URL is updated.
    • Required files are unzipped according to @compression="zip", not the URL's suffix; Springer Nature and TPMS are marked.
    • BibTeX-era markup is removed from the texstyle bibliographies, along with the "not implemented" warning.
  • Publication schema: declares citation-stylesheet-language. Only the source is changed; the derived .rnc/.rng are left for the maintainer build.
  • Guide: a new "Bibliography and citation style" subsection explains choosing a style, generating references (pretext generate references or -c references), and the citeproc-py-styles requirement.

Dependency: any style other than citeproc-py's one bundled style needs pip install citeproc-py-styles, about 15 MB as a wheel and 63 MB installed.

🤖 Generated with Claude Code

@rbeezer

rbeezer commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Just a short note, no need to change anything yet, there will be more later.

I think maybe a development road map should just become an issue on GitHub. It could have tasks, and we could just let our assistants manage it.

Not sure I want a lot of AI messing-about in the repo, and I'm not sure diffs on the git history would be the best way to see history/progress.

My work converting PDFs of research articles keeps turning up subtle bugs (excellent!) and I'm just having those sessions make issues. Then I can point a development assistant to the issue for the real work. I think a roadmap could be utilized the same way.

Tangential: where/how we get the CSL style files has been a big question in my mind, so I will take some time to scrutinize this one carefully.

@rbeezer

rbeezer commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

I had Claude do a review of this, suggesting that the Python looked to me to be more complicated than perhaps necessary. This is addressed in the review.

  • If the CSL styles collection is available with "pip install", why not do that? It would alleviate the problem of keeping things up-to-date and not requiring being online for each new style used. Size is a concern, I guess, at ~60 MB.
  • I left this whole question of "how to get/keep a style" unfinished. Maybe we can work incrementally to fix some problems first, then build up a solid foundation.
  • I was not really following this PR when I first reviewed it visually. So Claude's review is not helping me very much - just layering on more uncertainty. In any event, I think this needs more work and I hope the review helps.
  • We can chat next week, if that feels more productive.

@rbeezer

rbeezer commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

Thanks, Oscar. Pulling a journal's CSL style is a good step, and several pieces here fix long-standing problems. I built the branch and ran each path, using a small article with three CSL-structured biblio entries and a citation of each. Each case ran -c references, then -c doc -f latex, as two separate runs of the pretext script.

The journal's style doesn't reach a conversion

get_csl_style() is the only code that puts a journal's style into effect. It does so by writing journal.csl.style into the stringparams it is handed, and its only caller is references(). latex() calls get_latex_style() but not get_csl_style(). So during a conversion, csl-style-file is empty, $b-using-csl-styles is false, and assembly never uses the generated file.

With <journal name="bull-amer-math-soc"/> and no citation-stylesheet-language:

  • -c references downloads american-mathematical-society-numeric.csl and writes csl-bibliography.xml, stamped with that style.
  • -c doc -f latex then uses PreTeXt's default bibliography formatting. It gives no warning that the generated file was ignored.

Adding the same style explicitly with citation-stylesheet-language produces an identical references file, and then the LaTeX does use the formatted entries and citations.

The roadmap puts this resolution in the CLI, where a target's stringparams are assembled. Even if the CLI does that, the pretext script and any other direct user of the library won't. So a journal's style depends on each consumer remembering to call the resolver before every conversion.

A missing references file still stops a conversion

With a CSL style named and no generated references/csl-bibliography.xml, -c doc -f latex fails in the publisher-variable report with Cannot resolve URI …/csl-bibliography.xml, and no .tex file is written. Master does the same, so this predates the PR. The new csl.file.missing parameter is meant to prevent it, but only get_csl_style() sets it, so it helps only during -c references. The comments in pretext-assembly.xsl and in get_csl_style(), and the Guide's "Until that happens PreTeXt formats references in its usual way and says so", describe protection that conversions don't have yet.

The Springer Nature class file arrives as a zip

The new URL (…/content/18782940/data/v12) does serve the template archive, with sn-article-template/sn-jnl.cls inside. But place_latex_package_files() unpacks a download only when url.endswith(".zip"), and this URL doesn't end that way. So the whole archive is saved as sn-jnl.cls, in the build directory and in the cache. pdflatex then fails on it, and the bad file stays cached. Honoring the compression="zip" attribute, which elsevier.xml's commented example already uses, instead of testing the URL's suffix would fix it. The Springer Nature entry would then need that attribute.

The Python could be much smaller

The six new functions come to about 185 lines, plus changes to get_journal_info() and references(). Most of that comes from where things are done, not from what has to be done:

  • Resolution by editing the caller's dictionary. get_csl_style() returns a value but also writes two keys into the caller's stringparams. One of them, csl.file.missing, is an unrelated job. Its docstring spends a paragraph on what happens if it runs twice. And every consumer has to call it before every conversion, which is the problem above.
  • Texstyle inheritance, again. Four functions walk extends one level, and two of them parse the same file. The walk is needed because the merge in pretext-latex-texstyle.xsl takes a dependent's whole metadata element, so a base's csl-style inside metadata is never inherited. The Python therefore uses a different merge rule from the LaTeX stylesheet, and journals-to-table.xsl adds a third version, whose comment asks that they be kept in step. Putting csl-style where the existing merge already inherits it would leave a single lookup: a child of texstyle, or on base files only.
  • A (name, href) pair. The download location travels with the name through five functions, with special cases for when the two come from different places. But every href is the CSL repository URL with the style name inserted, so it could be derived from the name. And because only a journal supplies an href, a style the publisher names is never downloaded.
  • An override nothing uses. No journal in journals.xml uses the new csl attribute on method, and it isn't documented.
  • Repeated work. references() now builds the publisher-variable report twice and calls get_managed_directories() twice.

There is a simpler arrangement.

Let citeproc-py find the style. citeproc-py 0.10 already resolves a bare style name by trying a file path, then its one bundled style, then the citeproc-py-styles package when it is installed. That package has about 2,850 independent styles, plus about 8,000 dependent ones, and all four named here are among them. With it installed, an explicitly named american-mathematical-society-numeric, with no journal and no download, formats correctly. The download code, the href attributes, and the cache directory would all go away. The roadmap chose downloading because citeproc-py-styles is not a CLI dependency, so this is a decision for you and Rob. Without it, one short function that builds the URL from any style's name would do.

Resolve the style name where every conversion already looks. publisher-variables.xsl could compute csl-style-file itself: the publication file's value if given, otherwise the journal's style, read with document() just as pretext-latex-texstyle.xsl and journals-to-table.xsl already read texstyle files. references() would read the report as it does today. The script, the CLI, and every conversion would then agree, with no stringparam to pass. The rule that maps a journal code to its texstyle file would also live in XSL, but journals-to-table.xsl already has it and could share it.

That leaves the missing-file check as the one piece that needs Python, since XSLT 1.0 can't test whether a file exists. Like the style, it has to be set wherever conversions run.

Documentation

  • The Guide says naming a journal formats references in its style "in every output format, with no further setting", and that references are "built when needed and cached". The first section shows neither is the case yet.
  • harvard1 appears as an example in the Guide, in a comment in pretext.py, and in the roadmap. The CSL repository no longer has it (it returns 404), and neither does citeproc-py-styles. citeproc-py 0.10 bundles harvard-cite-them-right.
  • The roadmap repeats the harvard1 claim, and its design, with the resolver in the CLI, is behind the first problem. Dropping that commit, as you offered, seems best.

Schema

3b4a0af84 edits schema/publication-schema.xml but not the files generated from it. Regenerating, with the literate-programming stylesheet and then trang, adds citation-stylesheet-language to publication-schema.rnc and publication-schema.rng. They belong in the same commit. It's good to see this element declared at last, since the publisher variables have read it for some time.

Commits

  • Granularity:
    • 3b4a0af84 mixes the schema with Guide text; documentation goes in its own commit.
    • e972251f0 combines the Python, assembly, publisher variables, and the texstyle stylesheet. It also carries two unrelated changes: the fix of f to bib_file in the references() error message (a real bug) and the removal of 42 blank lines.
    • 792ec581d puts a Guide paragraph with the table generator and its generated table.
  • Topics: CSL: and Docs: are new. The established ones are Script: for the Python library, plus Assembly:, Publisher variables:, Publication schema:, Texstyles:, and Guide:.
  • Typos: "Spring Nature" in 0785a39e8, and "bibliographys" in 49576be67.

What works well

  • Citation replacement now uses $csl-file instead of the literal gen/references/csl-bibliography.xml, so it respects a publisher's generated directory.
  • A mismatched or missing generated file now leaves the author's xref elements in place, so citations and the bibliography fall back together.
  • $b-extracting-biblio keeps the style comparison from opening the generated file while it is being created. A first -c references run, with no file yet, is quiet and correct.
  • The texstyle bibliography elements lose their unused cmd and arg, and the "not implemented correctly yet" warning is gone.
  • When a download fails, the error message says exactly where to save the file by hand.

Claude Opus 5.5, acting as a review assistant for Rob Beezer

oscarlevin and others added 19 commits September 28, 2026 19:19
… archive as a zip

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ver its URL

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n a transform

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he publisher's generated directory

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ssing or mismatched

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…iteproc-py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sing

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o BibTeX style or command

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ats it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… citations

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@oscarlevin

Copy link
Copy Markdown
Member Author

Thanks, Rob, and thanks for the thorough review. I've rebuilt the branch on current master along the lines the review suggested, with two changes of detail explained below. The Python additions went from about 220 lines to about 45, and the PR is now 213 insertions across 18 files.

What changed

  • citeproc-py-styles finds the style. The download code, the href attributes, the cache directory, and the unused csl override on method are all gone. references() hands citeproc-py the bare name as before. If the package is missing, that is now a clear PTX:ERROR naming the package, not a traceback. I'll add the package to the Docker image.
  • The journal's style is resolved in publisher-variables.xsl. A get-default-pub-variable template for citation-stylesheet-language/@style supplies the journal's style whenever the publication file names none. Every conversion, the script, the CLI, and references() now see the same csl-style-file with no stringparam. get_csl_style(), journal.csl.style and csl.file.missing are gone.
  • A missing references file no longer stops a conversion (see the second pushback point below). Assembly reports it as PTX:FALLBACK, and citations and bibliography fall back together.
  • Springer Nature: required files are unzipped when @compression="zip", whatever the URL. Springer Nature and TPMS (whose URL does end in .zip) both carry the attribute now.
  • Harvard: harvard1 is gone from the Guide and the comments.
  • Schema: the literate source declares citation-stylesheet-language. I've left the regenerated .rnc/.rng for your build rather than committing derived files.
  • Commits: the roadmap commit is dropped. The rest is split by topic with the established prefixes, and the bib_file fix is its own commit. The 42 blank lines are left alone.
  • Kept: everything under "What works well": $csl-file for citations, the two falling back together, no mismatch check during extraction, and the texstyle bibliography cleanup.

Two places I went a different way

1. The journal→style mapping lives in journals/journals.xml, not in the texstyle files. Each journal entry gets <citation-stylesheet-language style="..."/>, the same element and attribute as the publication file. My reasons:

  • A CSL style isn't LaTeX. It applies to HTML and every other format, while a texstyle file is the recipe for one journal's LaTeX.
  • Styles are really per journal, not per publisher family. Springer and Elsevier journals differ in reference style while sharing a class file.
  • The lookup is a single XPath from journals.xml, with no extends to follow and no code→texstyle-file mapping to copy into XSL. journals-to-table.xsl reads the same element. So there's one rule, not three.

The catch is that the ten AMS journals each repeat american-mathematical-society-numeric. One line per journal seemed a fair price.

2. The missing-file check isn't something each consumer has to set. Every transform, whether from the script, the CLI or another library user, goes through common.xsltproc(). I added a small lxml resolver there. When the generated csl-bibliography.xml doesn't exist, it returns a stand-in document instead of letting lxml stop. That matches the xsltproc executable, which warns and yields an empty node-set.

With that in place, assembly can test for the file itself. The test is the count you'd left commented out in missing-csl-file, now live. So the check needs no stringparam, and a caller can't forget it.

Along the way, a new $b-consulting-csl-file became the single switch the gauntlet uses. It is true only in a conversion that uses CSL styles on a document that has references. The publisher-variable report overrides it to false(), so the fallback message comes once per conversion and never during -c references. This also fixes a latent bug: the mismatch check tested $missing-csl-file, an RTF that is always true, instead of $b-missing-csl-file.

Verified

I checked these with the script and citeproc-py 0.11.1 plus citeproc-py-styles 0.1.6, on an article with three CSL-structured biblio entries:

  • bull-amer-math-soc, before any references are generated: LaTeX builds with default formatting and a single FALLBACK message.
  • -c references writes a file stamped american-mathematical-society-numeric, with no download.
  • After that, -c doc -f latex and -f html both use the formatted entries and citations, with no further setting.
  • With style="apa" and an uppercase journal code, APA wins. The stale AMS file gives the mismatch warning and a joint fallback, and regenerating gives APA author-date output.
  • A journal article with no references, electron-j-combin (no style), and an empty publication file all build with no CSL messages.
  • Without citeproc-py-styles, -c references gives a single clear error.
  • The Springer Nature class file now arrives as the 55 KB .cls, not the archive.

Open questions

  • An explicitly empty style="" still gets the journal's style, because set-pubfile-variable treats empty as "use the default". Should there be a way to name a journal but decline its CSL style?
  • On the CLI side, pretext build doesn't yet generate references on its own. Until it does, the FALLBACK message tells authors to run pretext generate references. That's for me to take up in the CLI.
  • If you'd like the rest of the old roadmap as a GitHub issue, as you suggested, I can open one.

Claude Opus 5.5, acting for Oscar Levin

@rbeezer

rbeezer commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks, Oscar. The rework answers round 1. A journal's style now reaches every conversion, a missing references file no longer stops a conversion, the Springer Nature class file arrives intact, and the new Python is about 45 lines.

This reviews head 4be592fe9 (19 commits); the HEAD~N offsets below count from it. The branch is now 20 commits behind master, but it still merges cleanly, and the merged result builds the sample article. The builds used Python 3.12 with lxml 6.1.1, citeproc-py 0.10.3 and citeproc-py-styles 0.1.6, and one check also used citeproc-py 0.11.1, the version you tested with.

What remains:

  1. A misspelled style name still ends in a traceback when citeproc-py-styles is installed, which is the configuration the Guide recommends.
  2. The last commit fixes a duplicate message that an earlier commit in this PR introduced. The fix should be folded into 8618339e9.
  3. The derived publication schema is still not regenerated.
  4. The Guide puts all its discussion in the reference entry. The conversational section it belongs in already exists, as an empty stub.
  5. Small items: five comment blocks have one line each off by a column, the new message gets the standard's name wrong, harvard1 survives in the sample article's publication files, and the Springer Nature URL could use the public host.

Round-1 findings: where they stand

Round 1 Now
A journal's style never reached a conversion Fixed: publisher-variables.xsl supplies the default, verified in LaTeX and HTML
A missing references file crashed a conversion Fixed: an lxml resolver plus a test in assembly, and one FALLBACK message
Springer Nature class file saved as a zip archive Fixed through @compression: sn-jnl.cls is 55,857 bytes of text. The TPMS file unpacks too.
Python more complicated than needed (about 220 lines) About 45 lines. The download code, href attributes, cache and unused csl override are gone.
Derived publication schema not regenerated Still not done: left on purpose (section 3)
Guide claims not true of the code All true now (section 4)
harvard1 Gone from the Guide and the code comments. Survives in the sample article's publication files (section 5).
Commit hygiene Split by topic, established topics, roadmap dropped, typos gone, bib_file fix in its own commit

1. Behavior

What was verified

The sample article was copied to scratch, so that no generated file lands in the repository. Its backmatter references hold six CSL-typed biblio, cited 27 times across the document. Variants of its publication file set the journal and the style. Each scenario ran the pretext script with -c references, then with -c doc -f latex or -f html.

  • Journal only (bull-amer-math-soc), before any references were generated: LaTeX and HTML both build, each with one PTX:FALLBACK message and default formatting.
  • -c references writes the file, stamped american-mathematical-society-numeric, with no download.
  • After that, LaTeX and HTML both use the AMS entries and citations. The backmatter list is reordered (Lay [1], Judson [2]), and every item in the citation demonstration list is still present, renumbered. In HTML, [2, 1, 4] becomes [1, 2, 3].
  • Journal plus style="apa", against the stale AMS file: a mismatch warning, and citations and bibliography fall back together. Regenerating gives APA author-date citations such as (Lay, 1993).
  • The same mismatched run on the PR's base gives no warning and silently uses the AMS citations. So the latent bug you describe, an RTF tested as a boolean, which is always true, is real, and this PR fixes it.
  • An uppercase journal code finds the AMS style. electron-j-combin, which has no style, gives no CSL messages.
  • A project path containing a space: the resolver finds the file when it is present, and supplies the stand-in when it is absent.
  • citeproc-py-styles absent: one clear PTX:ERROR that names the package.
  • Styles: all four styles in journals.xml resolve, and 16 of the 17 journals carry one. Dependent styles resolve too, such as aapg-bulletin, with or without a dependent/ prefix.

1.1 A misspelled style name still ends in a traceback

references() now wraps the style lookup in except ValueError. But citeproc-py raises ValueError only when citeproc-py-styles is absent. With the package installed, as the Guide and the PR tell authors to do, an unknown name raises citeproc_styles.errors.StyleNotFoundError, which derives directly from Exception, so it escapes as a traceback. I measured this with style="no-such-style-anywhere", under citeproc-py 0.10.3 and 0.11.1 alike. A typo in a style name is the likeliest mistake an author will make. Catching Exception at that point would cover both packages, since the message comes from whichever one failed.

1.2 Your question: an empty style=""

I confirmed that style="" alongside a journal still gets the journal's style, because an empty value means "use the default". Whether authors need a way to decline a journal's style is Rob's decision.

1.3 The Springer Nature URL

The new href is on cms-resources.apps.public.k8s.springernature.io, which looks like the Kubernetes host behind Springer's public address. resource-cms.springernature.com/…/data/v12 serves the identical 901,814-byte archive, and seems less likely to move. v12 is the current version: v13 returns 404 on both hosts, and the old v13.zip URL returns 400.

2. Commit story: fold 4be592fe9 into 8618339e9

Every commit builds. Each of the 19 commits, and the base, built the sample article to LaTeX with two publication files, one naming the journal and one naming nothing, and every run exited 0. The journal's style first takes effect at 1e627fc01 (HEAD~8), when journals.xml gains its styles, as it should.

A second run per commit, with an explicit style and no references file, shows a defect that lives entirely inside the PR:

Commit FALLBACK messages, conversion FALLBACK messages, -c references
base 20d105454 stops with Cannot resolve URI 0
d78fe0e99 (HEAD~14), the resolver 0 (default formatting, silently) 0
8618339e9 (HEAD~13) through 182a6108e (HEAD~1) 2 1
4be592fe9 (HEAD) 1 0

8618339e9 puts the missing-file test in a global variable. libxslt computes a global variable in every stylesheet that imports assembly, including the publisher-variable report. So every conversion printed the message twice. And -c references printed it during the very run that writes the file. 4be592fe9 repairs that. Both commits are in this PR, so folding the repair into 8618339e9 means the history never duplicates the message. 182a6108e (HEAD~1) finishes applying the switch that 8618339e9 introduced, so folding it in too would let the switch arrive whole.

3. Publication schema

290d4715e (HEAD~15) changes only the literate source. Regenerating it (litprog, then trang) adds 3 lines to publication-schema.rnc and 5 to publication-schema.rng. You left them for the maintainer's build, as with css/dist. But for the schema the convention is the reverse: the derived files go in the same commit as the source.

4. Guide

  • Accuracy. Every claim now holds. The style applies in every output format, PreTeXt falls back and says so, the -c references route works, and references() refuses a style that puts citations in notes. The edited Guide validates against the dev schema with no messages, the same as its base. The journal table regenerates identically from journals-to-table.xsl.
  • Placement. The new common-csl subsection is three paragraphs of discussion in the reference chapter. The Guide's convention is a sentence or two there, plus a cross-reference, with the discussion in a conversational section that links back. That section already exists: topic-references, "(*) References (Lists of Works Cited)", an empty stub in doc/guide/author/topics.xml.

5. Smaller items

  • Message wording. The new FALLBACK message says "Citation Stylesheet Language" and "publisher file". The standard is the Citation Style Language, as the Guide and the journals.xml comment say, and the Guide's term is "publication file". The mismatch warning, which predates the PR, has the same two slips.
  • harvard1 survives in comments in examples/sample-article/publication.xml, publication-alegreya.xml and publication-print.xml. These include "Default is "harvard1"", which is wrong on two counts: the default is empty, and the style no longer exists.
  • Comment alignment. In each of five new comment blocks, one line's --> is a column off from the rest:
    • journals/journals.xml line 24, one column right
    • xsl/latex/pretext-latex-texstyle.xsl line 760, one column left
    • xsl/pretext-assembly.xsl line 1173, one column left
    • xsl/pretext-assembly.xsl line 1338, one column left
    • xsl/publisher-variables.xsl line 287, one column left

6. Commit hygiene

  • No commit has a body. Each commit keeps to one area. The Guide is in its own commit, and the generated table rides with its generator, which is right for a derived file.
  • The topics are established: Script:, Assembly:, Publisher variables:, Publication schema:, Texstyles:, Guide:, and Journals: (one earlier use).
  • a412eaea3 (HEAD~17) names an attribute in its subject without the @. It should be "@compression".
  • The subjects run long. Five of the 19 exceed 80 characters, and a715d1d8c (HEAD~12) is 103. On master, the median of the last 1,000 subjects is 58 characters, 90% are 71 or fewer, and none exceeds 100.

7. What is right

  • The journal's style is resolved in publisher-variables.xsl. There is one lookup, and the script, pretext-cli, references() and every conversion agree, with no parameter to pass.
  • Your first different choice, the style in journals.xml rather than the texstyle files, works well. It is a single XPath with no extends to follow, the table reads the same element, and a style belongs to a journal, not to a LaTeX class.
  • Your second, the resolver in common.xsltproc(), works too. It answers for exactly one file name, so any other missing file still fails as loudly as before. No caller can forget it, and it handles paths with spaces.
  • The mismatch check works for the first time.
  • The texstyle cleanup is safe. Nothing in the code reads bibliography-style or the removed cmd/arg.
  • Everything round 1 listed as working well is kept.

Verification

  • The sample article, copied to scratch with eight publication-file variants. Scenarios: journal only, before and after -c references; journal plus APA against a stale file, then regenerated; uppercase code; a journal with no style; style=""; an unknown style; a dependent style; a path with a space, the file present and absent; citeproc-py-styles absent. LaTeX throughout, and HTML for the main path.
  • All 19 commits and the base: a LaTeX build with two publication files, then a build and -c references with an explicit style and no references file.
  • The mismatch case at the base 20d105454.
  • place_latex_package_files() for springer-nature and theory-probab-math-statist, with the results checked by file. The Springer URLs on both hosts, for v12, v13 and v14.
  • The publication schema regenerated from the PR's source and compared. The Guide validated in its version form against pretext-dev.rng, at the base and at the head. The journal table regenerated and compared.
  • The style lookup probed directly under citeproc-py 0.10.3 and 0.11.1.

Claude Opus 5.5, acting as a review assistant for Rob Beezer

@rbeezer

rbeezer commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

I'll address the minor issues here as part of a merge

@rbeezer

rbeezer commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Oscar, rather than ask for another round, I've made the round-2 changes myself on a copy of this branch, and it will go in from there. Your commits keep your name, dates and messages, apart from shorter subjects. Because it will be merged by cherry-picking the commits, GitHub will show this PR as closed rather than merged.

The branch is rebuilt on current master, which is 20 commits newer than your base; nothing conflicted. It now has 18 commits: your 19, less two folded into earlier ones, plus one new commit.

What changed

  • A misspelled style name. The style lookup in references() now catches any exception, not only ValueError. So with citeproc-py-styles installed, its StyleNotFoundError is reported too, and a misspelled style ends in one PTX:ERROR in both configurations.
  • The duplicate message. "Assembly: detect a missing file of generated references and citations" now includes the report's override from "Publisher variables: the report never consults generated references", and two of the three changes from "Assembly: one switch decides whether generated references are consulted". The third changes a line that "Assembly: missing or mismatched references leave citations as authored" adds, so it went there. The missing-file message is now printed once at every commit, and never during -c references.
  • Publication schema. The schema commit now includes the regenerated publication-schema.rnc and publication-schema.rng.
  • Springer Nature. The href now uses resource-cms.springernature.com, which serves the identical archive.
  • The standard's name. Both the new FALLBACK message and the older mismatch warning now say "Citation Style Language", as does the comment above the style in publisher-variables.xsl.
  • Guide. The discussion moved from the reference entry into the "References (Lists of Works Cited)" topic, which had been an empty stub. The reference entry is now a short entry, and the two link to each other.
  • Comments. The five comment blocks with one line a column off are aligned, each in the commit that wrote it.
  • Subjects. All are 70 characters or fewer, and the attribute is now quoted as "@compression".
  • Sample article. A new commit replaces the harvard1 comments in its three publication files.

Left as they were: "publisher file" in the messages, since the existing messages use it throughout; "Citation Stylesheet Language" in a comment in pretext.py, in the pretext script's help, and in the element's name; and an empty style="" alongside a journal, which still gets the journal's style.

Verification

  • Every commit: the sample article, built to LaTeX with a journal, with no style, and with a style but no generated references, plus -c references. The first five commits stop on a style with no generated references, as master does; every other build completes. From the detection commit on, the missing-file message appeared once in the conversion and not at all in -c references.
  • The final branch:
    • A journal alone gives references stamped american-mathematical-society-numeric, which the LaTeX uses with no fallback.
    • A misspelled style gives one PTX:ERROR, with citeproc-py-styles installed and without it, and no traceback.
    • Regenerating the publication schema a second time changes nothing.
    • The Guide validates against the development schema, with no messages, as before.
    • The Springer Nature class file arrives as text, 55,857 bytes.

Claude Opus 5.5, acting as a coding assistant for Rob Beezer

rbeezer added a commit that referenced this pull request Oct 1, 2026
@rbeezer

rbeezer commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Thanks, @oscarlevin. Merged with changes detailed above. Great to have this decided and resolved.

@rbeezer rbeezer closed this Oct 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants