From c33fd45617061bf3aab2c6959b98eb064ccce0f1 Mon Sep 17 00:00:00 2001 From: Dan Knauss Date: Sun, 5 Jul 2026 17:49:23 -0600 Subject: [PATCH 1/4] docs: record footprint and performance metrics Add a hand-verified metrics reference (docs/current-metrics.md) with re-derivation commands for LOC, installed storage footprint, and runtime query overhead. Surface the headline figures in a README.md table and a readme.txt "Performance & Footprint" section. Key facts recorded: static save() output means zero added DB queries per page (no render_callback, options, cron, custom tables, or CPTs), ~2.2 MB installed footprint, and a ~1.4 KB front-end runtime. Co-Authored-By: Claude Opus 4.8 --- README.md | 17 ++++++++++ docs/current-metrics.md | 71 +++++++++++++++++++++++++++++++++++++++++ readme.txt | 15 +++++++++ 3 files changed, 103 insertions(+) create mode 100644 docs/current-metrics.md diff --git a/README.md b/README.md index 282a153..44a4396 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,23 @@ Both demo Blueprints explicitly request PHP `intl` support because editor-time C Developer-facing CI/runtime coverage details are listed in the development section below. +## Footprint & Performance + +Borges is a static-output block: formatted bibliography HTML, JSON-LD, and COinS are baked into post content at save time, so **published pages add zero database queries and zero server-side formatting** — the citeproc engine and metadata lookups run only while you edit. All figures below are hand-verified; re-derivation commands live in [`docs/current-metrics.md`](docs/current-metrics.md). + +| Metric | Value | +|---|---| +| First-party PHP (main plugin file) | ~1,880 LOC (single file) | +| JS source (`src/`) | ~8,850 LOC | +| Frontend runtime shipped to visitors | `view.js` ~1.4 KB + `style-index.css` ~2.9 KB, enqueued only when the block is present | +| Installed footprint | ~2.2 MB (citeproc-php engine ~1.0 MB, translations 724 KB, assets 328 KB, curated CSL styles 60 KB) | +| Distributed ZIP (compressed) | ~0.9–1 MB | +| **Added DB queries per page** | **0** — regardless of block or citation count | +| Autoloaded options / cron / custom tables / custom post types | none | +| `render_callback` on the frontend | none (static `save()` only) | + +The only per-visitor cost is the small `view.js`/`style-index.css` pair, loaded solely on pages that contain a bibliography. Deactivating the plugin leaves the rendered bibliographies intact as static HTML. + ## Recent Release Highlights - **1.3.4** — Refreshes the translation template plus 19 seed PO/MO locale pairs, adds CI validation for i18n artifacts, clarifies the bundled seed versus official language-pack policy, and archives historical planning notes out of active docs. diff --git a/docs/current-metrics.md b/docs/current-metrics.md new file mode 100644 index 0000000..251500b --- /dev/null +++ b/docs/current-metrics.md @@ -0,0 +1,71 @@ +# Current metrics + +Hand-verified size, footprint, and runtime-overhead metrics for Borges Bibliography Builder. +Each number carries the exact command used to re-derive it, so the figures can be re-checked +on demand rather than trusted on faith. Re-run the relevant command and update the number **in +the same commit** whenever the underlying quantity changes. + +Last verified: **2026-07-05** against `main` (commit `49f623b`). + +## Lines of code + +| Metric | Value | Re-derivation command | +|---|---|---| +| Main plugin file (`bibliography-builder.php`) | **1,881** | `wc -l bibliography-builder.php` | +| All first-party PHP (excl. vendor, tests, scripts, packages, output, node_modules) | **1,982** | `find . -name '*.php' -not -path './vendor/*' -not -path './node_modules/*' -not -path './tests/*' -not -path './packages/*' -not -path './scripts/*' -not -path './output/*' -print0 \| xargs -0 wc -l \| tail -1` | +| JS source (`src/`, excl. `*.test.js`) | **8,851** | `find ./src -name '*.js' -not -name '*.test.js' -print0 \| xargs -0 wc -l \| tail -1` | +| Shipped frontend runtime (`build/view.js`, minified) | **1,449 bytes** | `wc -c < build/view.js` | + +The only PHP that executes at runtime on a visitor request path is `bibliography-builder.php` +(REST registration + block registration); the CSL formatting engine under `vendor/` runs +**only** for editor-time REST calls. `scripts/*.php` are dev tooling and are not packaged. + +## Storage footprint (installed) + +Measured from a full release build (`npm run package:release`), which copies the shipped +files and installs runtime Composer dependencies with `--no-dev`, then prunes tests/docs/images +from `vendor/`. + +| Component | Size | Re-derivation command | +|---|---|---| +| `vendor/` — citeproc-php engine + `seboettg/collection` + `myclabs/php-enum`, pruned | **~1.0 MB** | `du -sh output/release/borges-bibliography-builder/vendor` (after `npm run package:release`) | +| `languages/` — seed PO/MO/JSON translations | **724 KB** | `du -sh languages` | +| `build/` — editor + frontend assets | **328 KB** | `du -sh build` | +| `packages/` — curated CSL styles + locales | **60 KB** | `du -sh packages` | +| PHP + `block.json` + `readme.txt` + `LICENSE` + `THIRD-PARTY-NOTICES.txt` | **~100 KB** | — | +| **Total installed** | **~2.2 MB** | `du -sh output/release/borges-bibliography-builder` (after `npm run package:release`) | +| Distributed ZIP (compressed) | **~0.9–1 MB** | `du -h output/release/borges-bibliography-builder.zip` | + +Notes: +- `vendor/seboettg/citeproc-php` is **3.2 MB** unpruned and **~536 KB** after the release + script strips tests/docs. The pruning is what keeps the installed footprint near 2 MB. +- `packages/` bundles a **curated subset** of CSL styles (the nine the plugin ships), not the + full upstream `citation-style-language/styles` repository (~40 MB). This is a deliberate + footprint control, not an accident of packaging. + +## Runtime / query overhead + +The block uses **static `save()` output with no `render_callback`** — formatted bibliography +HTML, JSON-LD, and COinS are serialized into `post_content` at edit time. The visitor request +path therefore adds **zero** database queries and **zero** citeproc/PHP formatting work. + +| Overhead on the frontend (per published page) | Value | Re-derivation | +|---|---|---| +| Additional database queries | **0** | Static save; no persistent storage — see audit below | +| REST calls | **0** | `POST /format` and `GET /pmid/{pmid}` fire only in the editor | +| `render_callback` invocations | **0** | Block registers no server render | +| Autoloaded options / rows in `wp_options` | **0** | No `add_option`/`update_option`/`register_setting` | +| Cron events | **0** | No `wp_schedule_event` | +| Custom post types / custom tables | **0** | No `register_post_type` / `dbDelta` | +| Enqueued frontend assets (only when block present) | `view.js` ~1.4 KB + `style-index.css` ~2.9 KB | `wc -c build/view.js build/style-index.css` | + +Persistence/hook audit (expected output: **NONE**): + +``` +grep -rEl "add_option|update_option|register_setting|register_post_type|dbDelta|wp_schedule_event" \ + --include='*.php' . | grep -vE 'vendor|tests|node_modules' +``` + +The "average queries per page" figure is a flat **0 additional queries**, independent of the +number of bibliography blocks or citations on the page — all expensive resolution (Crossref +DOI, NCBI/PMC PMID) and CSL formatting happens at edit time and never touches a visitor. diff --git a/readme.txt b/readme.txt index b165682..de3e167 100644 --- a/readme.txt +++ b/readme.txt @@ -102,6 +102,21 @@ PHP 7.4+ and WordPress 6.4+. Borges Bibliography Builder is tested up to WordPre 8. Export the whole bibliography from the sidebar: copy as plain text, or download CSL-JSON, BibTeX, BibLaTeX, or RIS. 9. Readers can expand the per-entry Cite / Export panel on the published page to copy a citation or download it as RIS, CSL-JSON, BibTeX, or BibLaTeX. +== Performance & Footprint == + +Borges is a static-output block. Formatted bibliography HTML, JSON-LD, and COinS are baked into your post content when you save, so the citeproc formatting engine and the DOI/PubMed lookups run **only in the editor** — never on the front end. + +What this means for a published page: + +* **Zero added database queries** — no matter how many bibliographies or citations the page contains. Query load does not grow with your content. +* **No `render_callback`, no REST calls, no shortcodes** on the front end. Output is static HTML from the block's `save()`. +* **No persistent storage** — the plugin creates no options (nothing added to the `wp_options` autoload), no custom tables, no custom post types, and no cron events. +* **Tiny front-end payload** — only a small view script (~1.4 KB) and stylesheet (~2.9 KB) load, and only on pages that actually contain a bibliography. + +Installed footprint is roughly **2.2 MB** (the bundled citeproc-php formatting engine accounts for about half; the rest is translations, editor/front-end assets, and a curated set of citation styles). The downloadable ZIP is about 0.9–1 MB compressed. + +Because output is static, your bibliographies remain intact as plain HTML even if the plugin is deactivated. + == Known Limitations == **OSCOLA grouped bibliography** — OSCOLA convention requires the bibliography to be divided into source-type groups (cases, legislation, books, articles, online sources). Borges currently renders a single alphabetized list regardless of style. A dismissible notice in the editor explains this when OSCOLA is selected. Grouped-bibliography support is planned for a future release. From 3e619e30a1255eccd6c9c463d5a65c5d91221ee7 Mon Sep 17 00:00:00 2001 From: Dan Knauss Date: Sun, 5 Jul 2026 18:09:52 -0600 Subject: [PATCH 2/4] docs: correct wp_options and packages/ footprint claims Address automated review on PR #67 (Codex P2 + Copilot): - wp_options: the editor-time cache (bibliography_builder_cache_set) falls back to non-autoloaded, expiring _transient_bbb_* rows when no persistent object cache is present. Narrow the "0 rows / no persistent storage / creates no options" wording to "no autoloaded options / no long-lived settings" and document the editor-only transient fallback. The frontend "0 added queries per page" claim is unchanged and correct. - packages/ is not a separate shipped component: package-release.sh rm -rf's the staged packages/ after Composer installs those path packages into vendor/citation-style-language/*. Fold the 60 KB into the vendor/ figure; installed total corrected ~2.2 MB -> ~2.1 MB. Co-Authored-By: Claude Opus 4.8 --- README.md | 6 ++++-- docs/current-metrics.md | 32 +++++++++++++++++++++++--------- readme.txt | 4 ++-- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 44a4396..1e993cb 100644 --- a/README.md +++ b/README.md @@ -76,14 +76,16 @@ Borges is a static-output block: formatted bibliography HTML, JSON-LD, and COinS | First-party PHP (main plugin file) | ~1,880 LOC (single file) | | JS source (`src/`) | ~8,850 LOC | | Frontend runtime shipped to visitors | `view.js` ~1.4 KB + `style-index.css` ~2.9 KB, enqueued only when the block is present | -| Installed footprint | ~2.2 MB (citeproc-php engine ~1.0 MB, translations 724 KB, assets 328 KB, curated CSL styles 60 KB) | +| Installed footprint | ~2.1 MB (`vendor/` ~1.0 MB incl. citeproc-php and curated CSL styles, translations 724 KB, assets 328 KB) | | Distributed ZIP (compressed) | ~0.9–1 MB | | **Added DB queries per page** | **0** — regardless of block or citation count | -| Autoloaded options / cron / custom tables / custom post types | none | +| Autoloaded options / registered settings / cron / custom tables / custom post types | none | | `render_callback` on the frontend | none (static `save()` only) | The only per-visitor cost is the small `view.js`/`style-index.css` pair, loaded solely on pages that contain a bibliography. Deactivating the plugin leaves the rendered bibliographies intact as static HTML. +Editor-time DOI/PMID and formatting results are cached in the object cache when one is present, or otherwise in short-lived, non-autoloaded `_transient_bbb_*` transients — written only while editing, never on a visitor request. + ## Recent Release Highlights - **1.3.4** — Refreshes the translation template plus 19 seed PO/MO locale pairs, adds CI validation for i18n artifacts, clarifies the bundled seed versus official language-pack policy, and archives historical planning notes out of active docs. diff --git a/docs/current-metrics.md b/docs/current-metrics.md index 251500b..9616f27 100644 --- a/docs/current-metrics.md +++ b/docs/current-metrics.md @@ -28,20 +28,24 @@ from `vendor/`. | Component | Size | Re-derivation command | |---|---|---| -| `vendor/` — citeproc-php engine + `seboettg/collection` + `myclabs/php-enum`, pruned | **~1.0 MB** | `du -sh output/release/borges-bibliography-builder/vendor` (after `npm run package:release`) | +| `vendor/` — citeproc-php engine + `seboettg/collection` + `myclabs/php-enum` + curated `citation-style-language/styles` & `/locales`, pruned | **~1.0 MB** | `du -sh output/release/borges-bibliography-builder/vendor` (after `npm run package:release`) | | `languages/` — seed PO/MO/JSON translations | **724 KB** | `du -sh languages` | | `build/` — editor + frontend assets | **328 KB** | `du -sh build` | -| `packages/` — curated CSL styles + locales | **60 KB** | `du -sh packages` | | PHP + `block.json` + `readme.txt` + `LICENSE` + `THIRD-PARTY-NOTICES.txt` | **~100 KB** | — | -| **Total installed** | **~2.2 MB** | `du -sh output/release/borges-bibliography-builder` (after `npm run package:release`) | +| **Total installed** | **~2.1 MB** | `du -sh output/release/borges-bibliography-builder` (after `npm run package:release`) | | Distributed ZIP (compressed) | **~0.9–1 MB** | `du -h output/release/borges-bibliography-builder.zip` | +The source tree's `packages/` directory (60 KB) is **not** a separate shipped component: the +release script (`scripts/package-release.sh`) Composer-installs those path packages into +`vendor/citation-style-language/*` and then deletes the staged `packages/` (`rm -rf`). The +curated CSL styles are therefore counted inside the `vendor/` figure above. + Notes: - `vendor/seboettg/citeproc-php` is **3.2 MB** unpruned and **~536 KB** after the release script strips tests/docs. The pruning is what keeps the installed footprint near 2 MB. -- `packages/` bundles a **curated subset** of CSL styles (the nine the plugin ships), not the - full upstream `citation-style-language/styles` repository (~40 MB). This is a deliberate - footprint control, not an accident of packaging. +- The bundled `citation-style-language/styles` is a **curated subset** (the nine styles the + plugin ships), not the full upstream repository (~40 MB). This is a deliberate footprint + control, not an accident of packaging. ## Runtime / query overhead @@ -51,21 +55,31 @@ path therefore adds **zero** database queries and **zero** citeproc/PHP formatti | Overhead on the frontend (per published page) | Value | Re-derivation | |---|---|---| -| Additional database queries | **0** | Static save; no persistent storage — see audit below | +| Additional database queries | **0** | Static save; nothing on the block runs on the frontend — see audit below | | REST calls | **0** | `POST /format` and `GET /pmid/{pmid}` fire only in the editor | | `render_callback` invocations | **0** | Block registers no server render | -| Autoloaded options / rows in `wp_options` | **0** | No `add_option`/`update_option`/`register_setting` | +| Autoloaded options / registered settings | **0** | No `add_option`/`update_option`/`register_setting` | | Cron events | **0** | No `wp_schedule_event` | | Custom post types / custom tables | **0** | No `register_post_type` / `dbDelta` | | Enqueued frontend assets (only when block present) | `view.js` ~1.4 KB + `style-index.css` ~2.9 KB | `wc -c build/view.js build/style-index.css` | -Persistence/hook audit (expected output: **NONE**): +Persistence/hook audit — no persistent settings, options, cron, CPTs, or custom tables +(expected output: **NONE**): ``` grep -rEl "add_option|update_option|register_setting|register_post_type|dbDelta|wp_schedule_event" \ --include='*.php' . | grep -vE 'vendor|tests|node_modules' ``` +**One caveat on `wp_options`.** The plugin's editor-time cache +(`bibliography_builder_cache_set()`) writes to the persistent object cache via `wp_cache_set()` +when one is available, and otherwise falls back to `set_transient()` — which stores +**non-autoloaded, expiring** `_transient_bbb_*` rows in `wp_options`. Those rows are written +**only during editor REST calls** (`/format`, `/pmid`) as short-lived caches of upstream +lookups — never on a visitor request, and never added to the autoload set. So there are no +long-lived settings and nothing on the autoload path, but "zero rows ever touch `wp_options`" +would be inaccurate on a site without an external object cache. + The "average queries per page" figure is a flat **0 additional queries**, independent of the number of bibliography blocks or citations on the page — all expensive resolution (Crossref DOI, NCBI/PMC PMID) and CSL formatting happens at edit time and never touches a visitor. diff --git a/readme.txt b/readme.txt index de3e167..2ca31ea 100644 --- a/readme.txt +++ b/readme.txt @@ -110,10 +110,10 @@ What this means for a published page: * **Zero added database queries** — no matter how many bibliographies or citations the page contains. Query load does not grow with your content. * **No `render_callback`, no REST calls, no shortcodes** on the front end. Output is static HTML from the block's `save()`. -* **No persistent storage** — the plugin creates no options (nothing added to the `wp_options` autoload), no custom tables, no custom post types, and no cron events. +* **No long-lived settings** — the plugin registers no settings or autoloaded options, no custom tables, no custom post types, and no cron events. Editor-time DOI/PMID and formatting results are cached in the object cache when one is present, or otherwise in short-lived, non-autoloaded transients, written only while editing. * **Tiny front-end payload** — only a small view script (~1.4 KB) and stylesheet (~2.9 KB) load, and only on pages that actually contain a bibliography. -Installed footprint is roughly **2.2 MB** (the bundled citeproc-php formatting engine accounts for about half; the rest is translations, editor/front-end assets, and a curated set of citation styles). The downloadable ZIP is about 0.9–1 MB compressed. +Installed footprint is roughly **2.1 MB** (the bundled citeproc-php formatting engine accounts for about half; the rest is translations, editor/front-end assets, and a curated set of citation styles). The downloadable ZIP is about 0.9–1 MB compressed. Because output is static, your bibliographies remain intact as plain HTML even if the plugin is deactivated. From dec30ba15c2883cdd4a0757110a1fdc2e69e1cc8 Mon Sep 17 00:00:00 2001 From: Dan Knauss Date: Sun, 5 Jul 2026 18:27:48 -0600 Subject: [PATCH 3/4] docs: refine transient-cache and DOI-cache accuracy Address Codex re-review P3 notes on PR #67: - The editor-time cache calls both wp_cache_set() and set_transient() unconditionally (two independent function_exists guards), not an object-cache-else-transient fallback. With a persistent object cache no wp_options row is written; without one, set_transient() materializes the non-autoloaded _transient_bbb_* rows. Reword the caveat to match. - DOI imports are deduped in a browser-session JS Map (src/lib/parser.js), not the PHP object/transient cache (only the formatter and pmid groups exist server-side). Drop DOI from the server-side caching claim in both readmes and note the browser-session dedupe instead. The first-party PHP LOC (1,982) is unchanged: the documented command counts the three generated build/*.asset.php stubs. Co-Authored-By: Claude Opus 4.8 --- README.md | 2 +- docs/current-metrics.md | 20 ++++++++++++-------- readme.txt | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1e993cb..30a8348 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ Borges is a static-output block: formatted bibliography HTML, JSON-LD, and COinS The only per-visitor cost is the small `view.js`/`style-index.css` pair, loaded solely on pages that contain a bibliography. Deactivating the plugin leaves the rendered bibliographies intact as static HTML. -Editor-time DOI/PMID and formatting results are cached in the object cache when one is present, or otherwise in short-lived, non-autoloaded `_transient_bbb_*` transients — written only while editing, never on a visitor request. +Editor-time PMID and formatting results are cached in the object cache and in short-lived, non-autoloaded `_transient_bbb_*` transients — written only while editing, never on a visitor request. (DOI imports are deduped in a browser-session cache, not stored server-side.) ## Recent Release Highlights diff --git a/docs/current-metrics.md b/docs/current-metrics.md index 9616f27..bfbf9f4 100644 --- a/docs/current-metrics.md +++ b/docs/current-metrics.md @@ -71,14 +71,18 @@ grep -rEl "add_option|update_option|register_setting|register_post_type|dbDelta| --include='*.php' . | grep -vE 'vendor|tests|node_modules' ``` -**One caveat on `wp_options`.** The plugin's editor-time cache -(`bibliography_builder_cache_set()`) writes to the persistent object cache via `wp_cache_set()` -when one is available, and otherwise falls back to `set_transient()` — which stores -**non-autoloaded, expiring** `_transient_bbb_*` rows in `wp_options`. Those rows are written -**only during editor REST calls** (`/format`, `/pmid`) as short-lived caches of upstream -lookups — never on a visitor request, and never added to the autoload set. So there are no -long-lived settings and nothing on the autoload path, but "zero rows ever touch `wp_options`" -would be inaccurate on a site without an external object cache. +**One caveat on `wp_options`.** On every store, the plugin's editor-time cache +(`bibliography_builder_cache_set()`) calls **both** `wp_cache_set()` and `set_transient()` — +they are two independent `if ( function_exists() )` guards, not an object-cache-else-transient +fallback. With a persistent object cache drop-in active, `set_transient()` also routes to the +object cache and **no** option row is written; without one, it materializes +**non-autoloaded, expiring** `_transient_bbb_*` rows in `wp_options`. Either way the write +happens **only during editor REST calls** (`/format`, `/pmid`) as short-lived caches of +upstream lookups — never on a visitor request, and never added to the autoload set. So there +are no long-lived settings and nothing on the autoload path, but "zero rows ever touch +`wp_options`" would be inaccurate on a site without an external object cache. (DOI imports are +deduped separately in a browser-session JS `Map` in `src/lib/parser.js` and never reach this +PHP cache.) The "average queries per page" figure is a flat **0 additional queries**, independent of the number of bibliography blocks or citations on the page — all expensive resolution (Crossref diff --git a/readme.txt b/readme.txt index 2ca31ea..d1ff88f 100644 --- a/readme.txt +++ b/readme.txt @@ -110,7 +110,7 @@ What this means for a published page: * **Zero added database queries** — no matter how many bibliographies or citations the page contains. Query load does not grow with your content. * **No `render_callback`, no REST calls, no shortcodes** on the front end. Output is static HTML from the block's `save()`. -* **No long-lived settings** — the plugin registers no settings or autoloaded options, no custom tables, no custom post types, and no cron events. Editor-time DOI/PMID and formatting results are cached in the object cache when one is present, or otherwise in short-lived, non-autoloaded transients, written only while editing. +* **No long-lived settings** — the plugin registers no settings or autoloaded options, no custom tables, no custom post types, and no cron events. Editor-time PMID and formatting results are cached in the object cache and in short-lived, non-autoloaded transients, written only while editing. DOI imports are deduped in a browser-session cache, not stored server-side. * **Tiny front-end payload** — only a small view script (~1.4 KB) and stylesheet (~2.9 KB) load, and only on pages that actually contain a bibliography. Installed footprint is roughly **2.1 MB** (the bundled citeproc-php formatting engine accounts for about half; the rest is translations, editor/front-end assets, and a curated set of citation styles). The downloadable ZIP is about 0.9–1 MB compressed. From 863a6d82e2c56f51313cf2708801563f2cb26361 Mon Sep 17 00:00:00 2001 From: Dan Knauss Date: Sun, 5 Jul 2026 18:41:24 -0600 Subject: [PATCH 4/4] docs: make PHP LOC and footprint metrics clean-checkout reproducible Address Codex re-review P3 notes on PR #67: - build/ is gitignored (produced by npm run build), so counting it made the first-party PHP LOC environment-dependent: 1,982 in a built tree vs 1,979 on a clean checkout (the three generated build/*.asset.php stubs). Exclude build/ from the LOC command for a stable 1,979. - package-release.sh copies the gitignored build/, so the installed footprint recipe fails on a clean checkout without building first. Add an explicit `npm run build` prerequisite, and to the view.js row. Co-Authored-By: Claude Opus 4.8 --- docs/current-metrics.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/current-metrics.md b/docs/current-metrics.md index bfbf9f4..27cbef0 100644 --- a/docs/current-metrics.md +++ b/docs/current-metrics.md @@ -12,9 +12,9 @@ Last verified: **2026-07-05** against `main` (commit `49f623b`). | Metric | Value | Re-derivation command | |---|---|---| | Main plugin file (`bibliography-builder.php`) | **1,881** | `wc -l bibliography-builder.php` | -| All first-party PHP (excl. vendor, tests, scripts, packages, output, node_modules) | **1,982** | `find . -name '*.php' -not -path './vendor/*' -not -path './node_modules/*' -not -path './tests/*' -not -path './packages/*' -not -path './scripts/*' -not -path './output/*' -print0 \| xargs -0 wc -l \| tail -1` | +| All first-party PHP (excl. vendor, tests, scripts, packages, output, node_modules, generated `build/`) | **1,979** | `find . -name '*.php' -not -path './vendor/*' -not -path './node_modules/*' -not -path './tests/*' -not -path './packages/*' -not -path './scripts/*' -not -path './output/*' -not -path './build/*' -print0 \| xargs -0 wc -l \| tail -1` | | JS source (`src/`, excl. `*.test.js`) | **8,851** | `find ./src -name '*.js' -not -name '*.test.js' -print0 \| xargs -0 wc -l \| tail -1` | -| Shipped frontend runtime (`build/view.js`, minified) | **1,449 bytes** | `wc -c < build/view.js` | +| Shipped frontend runtime (`build/view.js`, minified) | **1,449 bytes** | `npm run build` then `wc -c < build/view.js` | The only PHP that executes at runtime on a visitor request path is `bibliography-builder.php` (REST registration + block registration); the CSL formatting engine under `vendor/` runs @@ -26,6 +26,10 @@ Measured from a full release build (`npm run package:release`), which copies the files and installs runtime Composer dependencies with `--no-dev`, then prunes tests/docs/images from `vendor/`. +**Prerequisite:** `build/` is gitignored (produced by `npm run build`), and +`scripts/package-release.sh` copies it, so run **`npm run build`** first on a clean checkout — +otherwise `package:release` (and the `du -sh build` row below) fails with `cannot stat build`. + | Component | Size | Re-derivation command | |---|---|---| | `vendor/` — citeproc-php engine + `seboettg/collection` + `myclabs/php-enum` + curated `citation-style-language/styles` & `/locales`, pruned | **~1.0 MB** | `du -sh output/release/borges-bibliography-builder/vendor` (after `npm run package:release`) |