Write full GPL citation styles and locales from the style manuals - #103
Merged
Merged
Conversation
The nine bundled CSL styles were ~2 KB stand-ins: every given name
initialized; no volume, issue, pages, editors, translators, editions,
or access dates. The official CSL styles are CC BY-SA 3.0, which the
repo's license policy (SPEC.md, THIRD-PARTY-NOTICES.txt) and
WordPress.org rule out, so each style is written for Borges from its
manual and stays GPL-2.0-or-later: Chicago notes-bibliography and
author-date (17th), APA 7, MLA 9, Harvard (Cite Them Right), IEEE,
Vancouver (Citing Medicine), OSCOLA, and ABNT NBR 6023.
The en-US, en-GB, and pt-BR locales gain month names, quotation
marks, and role terms; pt-BR was an English copy, so ABNT printed
English. Harvard now formats with en-GB.
citeproc-php 2.7 workarounds in the formatter:
- one CiteProc instance per entry (name state leaked across entries:
after an "et al." entry, later entries lost their "and");
- literal names mapped to family-only names (they rendered empty, so
organization authors vanished);
- page-first derived for OSCOLA;
- cleanup of " ," before labels, hyphenated initials ("J.- woo"),
and commas/periods inside closing quotes for en-US styles.
Style-side conventions and every quirk are in docs/csl-styles.md and
docs/external-eccentricities.md. Sort keys moved to separate macros so
the sort-coordination tests still pass without disturbing name state.
Tests: CslStyleGoldenTest pins every style's output for a 20-item
corpus (and fails on a stale vendor/ copy); FormatterAdaptationTest
covers the workarounds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #103 +/- ##
==========================================
+ Coverage 86.65% 86.75% +0.09%
==========================================
Files 52 52
Lines 5367 5406 +39
Branches 597 597
==========================================
+ Hits 4651 4690 +39
Misses 235 235
Partials 481 481 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
dknauss
marked this pull request as ready for review
September 26, 2026 17:18
7 tasks done
dknauss
pushed a commit
that referenced
this pull request
Sep 26, 2026
Full GPL CSL styles and locales (#103), Phase 05 M0-M3 (stable IDs, review routes and abilities, opt-in citation and block write routes: #104, #106), the save-markup language fix, reference-manager .bib fixes, the Playground demo page (#102), and the runtime matrix on the release package with formatter-parity and write-route checks (#105). Version bumped in the plugin header, block.json, readme.txt Stable tag, the POT header, and the package manifests. CHANGELOG [Unreleased] is dated as 1.7.0; readme.txt gains a user-facing changelog entry, an Upgrade Notice, and an FAQ note on the opt-in write routes. README highlights and STATE/ROADMAP move to the 1.7.0 baseline. Tested up to stays 7.1: WordPress latest is 7.1.2, which CI's runtime matrix exercises, including formatter parity across all nine styles. package-release.sh now also prunes .git directories from vendor/. When Composer falls back from dist to a git clone (as it did in this sandbox), the ZIP otherwise carried 4 MB of git metadata. Release checklist gates run locally: lint:js, lint:css, lint:i18n, npm audit (0), composer audit (none), Jest 873 passed / 2 skipped, PHPUnit 318 OK (the 4 vendor deprecations already on main), build, package:release (552,718-byte ZIP). citeproc-php v2.7.1 is current. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
dknauss
added a commit
that referenced
this pull request
Sep 26, 2026
* chore(release): 1.7.0 Full GPL CSL styles and locales (#103), Phase 05 M0-M3 (stable IDs, review routes and abilities, opt-in citation and block write routes: #104, #106), the save-markup language fix, reference-manager .bib fixes, the Playground demo page (#102), and the runtime matrix on the release package with formatter-parity and write-route checks (#105). Version bumped in the plugin header, block.json, readme.txt Stable tag, the POT header, and the package manifests. CHANGELOG [Unreleased] is dated as 1.7.0; readme.txt gains a user-facing changelog entry, an Upgrade Notice, and an FAQ note on the opt-in write routes. README highlights and STATE/ROADMAP move to the 1.7.0 baseline. Tested up to stays 7.1: WordPress latest is 7.1.2, which CI's runtime matrix exercises, including formatter parity across all nine styles. package-release.sh now also prunes .git directories from vendor/. When Composer falls back from dist to a git clone (as it did in this sandbox), the ZIP otherwise carried 4 MB of git metadata. Release checklist gates run locally: lint:js, lint:css, lint:i18n, npm audit (0), composer audit (none), Jest 873 passed / 2 skipped, PHPUnit 318 OK (the 4 vendor deprecations already on main), build, package:release (552,718-byte ZIP). citeproc-php v2.7.1 is current. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 * Parse each CSL style once per format request CiteProc::render() calls init() every time, which builds a new Context, reads and parses the locale file, and rebuilds the style's object tree: about 3 ms, against well under 1 ms to render an entry. With one render per entry (the fix that stopped an "et al." entry from dropping the next entry's "and"), 50 entries took about 90 ms, against about 8 ms in 1.6.0 with its short stand-in styles. Bibliography_Builder_Reusable_CiteProc parses once, records every property of every object in the parsed style tree, and before each later render restores them, resets the Context's per-render lists, and zeroes Layout's static cited-item counter. Each entry renders against the state a fresh parse would give it: 50 entries now take about 25 ms. The nine style goldens still match byte for byte. A new test formats the corpus in reverse order, putting the "et al." and APA 21+ entries ahead of the short author lists, and requires every entry to match its golden line; with the restore disabled, both the goldens and the new test fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 * Drop the #[\Override] attribute from the reusable formatter PHP 7.4 reads an attribute on its own line as a comment (php -l on 7.4 passes, and so does the PHP 7.4 runtime smoke), but Copilot flagged it as a 7.4 parse error, and compatibility scanners can do the same. It does nothing at runtime, so drop it, and turn off Psalm's MissingOverrideAttribute, which cannot apply to a plugin that supports PHP 7.4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2 --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
What changed?
The nine bundled CSL styles and three locales are rewritten in full, each from its own manual:
Before and after, for one journal article:
The full reviewed output for all 20 corpus items in every style is in
tests/fixtures/csl-styles/*.txt.Why were the styles stand-ins? The official CSL styles and locales are CC BY-SA 3.0. That isn't GPL-compatible, and
SPEC.mdandTHIRD-PARTY-NOTICES.txtforbid bundling them. So these are written for Borges from each manual's rules, not copied from the CSL files, and stay GPL-2.0-or-later.Formatter changes. These work around citeproc-php 2.7 behavior; each quirk is in
docs/external-eccentricities.md.CiteProcper entry. Name state leaked between entries: once one entry was cut to "et al.", every later entry lost its "and". This bug was live before this PR.bibliography_builder_prepare_csl_for_formatter():literalnames to family-only names. Organization authors rendered empty, which was also live before this PR;page-firstfor OSCOLA.bibliography_builder_normalize_formatted_text():,and.inside closing quotes for en-US styles.Deliberate deviations, listed in
docs/csl-styles.md:https://links, so OSCOLA drops its angle brackets.Existing posts keep their saved text until an entry is added or edited or the style is changed. The editor never reformats on load.
Heads-up for the planned year suffixes (2020a/2020b, REQ-S4). Formatting each entry on its own means citeproc can't see the whole list. When that feature lands, it will need to assign suffixes itself; the plan already coordinates suffixes with the JS sorter.
SortCoordinationTeststill passes, because the styles keep<sort>blocks, now in separatesort-*macros.Validation
composer test:phppasses (287). It includes:CslStyleGoldenTest, which pins 9 styles × 20 items and fails if thevendor/copy is stale;FormatterAdaptationTest(7 tests).composer lint:phpandcomposer analyze:phppass.npm run lint:jsandnpm run test(872) pass. No JS changed.verify-metrics.shpasses. The LOC rows are updated.save()'s italics and links rely on the title and URL text, which the styles keep as stored.Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01KbVuMPN7YTcV27vwsG3LZ2
Generated by Claude Code