diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 9a97573..5dbc789 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -32,8 +32,9 @@ after completion. in `3d5d3de` and `539b6b3`) - **Phase 03** — 1.3.x release prep (complete; `v1.3.3` is the current public release baseline) -- **Phase 04** — frontend Cite/Export affordances (active next feature - track) +- **Phase 04** — frontend Cite/Export affordances (implementation + code-complete on branch `phase-04/cite-export-affordances` / PR #37; + pending the plan 04-04 human browser-verify checkpoint before merge) - **Phase 05** — writable bibliography REST/Abilities design (memo complete; implementation deferred) diff --git a/.planning/STATE.md b/.planning/STATE.md index bedc628..c30201b 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -1,6 +1,6 @@ # Project State -_Last reviewed: 2026-06-14._ +_Last reviewed: 2026-06-17._ ## Current Focus @@ -23,8 +23,12 @@ _Last reviewed: 2026-06-14._ - `b44a899` Add direct access guard to PMID helpers 3. Keep the release artifact, WordPress.org SVN output, Playground blueprints, and docs aligned whenever DOI/PMID/BibTeX import behavior changes. -4. Next feature track remains frontend Cite/Export affordances, unless a - release or Playground regression takes priority. +4. Phase 04 (frontend Cite/Export affordances) is **implementation + code-complete** on branch `phase-04/cite-export-affordances` (PR #37), + covering plans 04-01 through 04-04. All automated gates pass (570 Jest + tests, lint, build); the only outstanding item is the plan 04-04 human + browser-verify checkpoint (visual confirmation in the editor + frontend), + which must be completed in a browser-capable session before merge. ## Current Priority Order diff --git a/.planning/phases/04-frontend-cite-export-affordances/04-01-SUMMARY.md b/.planning/phases/04-frontend-cite-export-affordances/04-01-SUMMARY.md new file mode 100644 index 0000000..c1767e8 --- /dev/null +++ b/.planning/phases/04-frontend-cite-export-affordances/04-01-SUMMARY.md @@ -0,0 +1,36 @@ +--- +phase: 04-frontend-cite-export-affordances +plan: 01 +status: complete +--- + +# 04-01 Summary — Foundation: attribute + export + deprecation + +Lays the three foundations required before any `save()` shape change in Plan 02. + +## What changed + +- **block.json** — added two attributes following the `outputCoins`/`outputCslJson` pattern: + - `outputCiteExport` (boolean, default `false`) — the opt-in for per-entry cite/export affordances. + - `bibliographyId` (string, default `""`) — stable per-block id for the future writable REST work (REST-API-M0-BLOCK-ID). +- **src/edit.js** — added a one-shot `useEffect([])` that assigns `crypto.randomUUID()` to `bibliographyId` on first insertion when empty (idempotent on later renders). +- **src/lib/export.js** — added the `export` keyword to `cslToRisEntry`; the function body is unchanged. `save()` can now generate per-entry RIS synchronously in Plan 02. +- **src/deprecated.js** — prepended a new `deprecated[0]` that freezes the current pre-Phase-4 `save()` shape (mirrors `src/save.js`: `sortEntries: true, headingTag: 'p', entryTag: 'cite'`, no `
`). Existing entries shifted to `[1]`–`[5]`. This is the migration gate that keeps already-saved blocks valid once `
` is introduced. + +## Tests + +- **src/lib/export.test.js** — three `cslToRisEntry` cases: named-export importability, `TY - JOUR` opener / `ER - ` terminator, and `AU` line for a named author. +- **src/deprecated.test.js** — new case asserting `deprecated[0]` renders `
  • ` with no `
    `; existing index references shifted by one. + +## Deviation from plan + +The plan's `` snippet (authored 2026-05-10) described a "current" `deprecated[0]` without `includeDeprecatedBiblioEntryRole`. The live `deprecated.js` had since gained that option, while live `src/save.js` does **not** emit the role. The new `deprecated[0]` was therefore matched to the **actual current `save.js` shape** (no role, no `linkVisibleUrls` arg since it defaults true) rather than the stale snapshot — same intent, accurate to current state. + +## Verification + +- `npm test` — 554 passed, 2 skipped (perf benchmarks), 0 failed. +- `lint:js`, `lint:css`, `lint:php`, `npm run build` — all pass. + +## Next + +Wave 2 — Plan 02 (save markup `
    ` panels) and Plan 03 (editor pre-computation of BibTeX/BibLaTeX export strings). diff --git a/.planning/phases/04-frontend-cite-export-affordances/04-02-SUMMARY.md b/.planning/phases/04-frontend-cite-export-affordances/04-02-SUMMARY.md new file mode 100644 index 0000000..2a9de04 --- /dev/null +++ b/.planning/phases/04-frontend-cite-export-affordances/04-02-SUMMARY.md @@ -0,0 +1,34 @@ +--- +phase: 04-frontend-cite-export-affordances +plan: 02 +status: complete +--- + +# 04-02 Summary — Save markup: `
    ` cite/export panels + +Adds the core visible feature: per-entry `
    `/`` disclosure panels in the static `save()` output, gated on the `outputCiteExport` opt-in. Zero-JS — everything is baked into post content at save time. + +## What changed + +- **src/save-markup.js** + - Imports `cslToRisEntry` from `./lib/export`. + - Adds `includeCiteExport = false` option. + - When enabled, each `
  • ` (after the optional COinS span) gains a `
    ` containing: + - a visible cite-text `

    ` (`displayOverride || formattedText`), readable without JS; + - RIS and CSL-JSON download ``s built synchronously as `data:` URIs (`encodeURIComponent`-encoded); + - BibTeX and BibLaTeX download ``s, rendered only when the per-citation `exportBibtex` / `exportBiblatex` strings exist (produced by Plan 04-03). + - All export links carry a `download="citation-."` attribute and `rel="noopener"`. +- **src/save.js** — passes `includeCiteExport: attributes.outputCiteExport ?? false`. + +## Tests (src/save.test.js — new `save cite/export disclosure panels` block) + +Opt-in gating (off by default), `

    ` + `Cite / Export` summary, RIS + CSL-JSON data-URI links with correct download names, conditional BibTeX/BibLaTeX links, download-attribute count (4 when all present), visible cite text, and an XSS check (a `', + }, + }), + ], + }); + expect(markup).toContain('%3Cscript%3E'); + expect(markup).not.toContain(''); + }); +}); diff --git a/src/style.scss b/src/style.scss index 90cfb21..75f4cf8 100644 --- a/src/style.scss +++ b/src/style.scss @@ -70,3 +70,42 @@ .wp-block-bibliography-builder-bibliography .Z3988 { display: none; } + +// Cite / Export disclosure panels — reset hanging-indent inheritance so the +// panel is flush-left, and make the summary/links readable and non-italic. +.wp-block-bibliography-builder-bibliography +details.bibliography-builder-cite-export { + text-indent: 0; + padding-left: 0; + margin-top: 0.4em; + font-size: 0.875em; +} + +.wp-block-bibliography-builder-bibliography +details.bibliography-builder-cite-export +summary { + display: inline-block; + font-style: normal; + font-weight: 400; + color: currentcolor; + cursor: pointer; +} + +.wp-block-bibliography-builder-bibliography +details.bibliography-builder-cite-export +.bibliography-builder-cite-text { + margin: 0.4em 0; + font-style: normal; + white-space: pre-wrap; +} + +.wp-block-bibliography-builder-bibliography +details.bibliography-builder-cite-export +.bibliography-builder-export-links { + display: flex; + flex-wrap: wrap; + gap: 0.5em; + margin: 0.4em 0 0; + padding: 0; + list-style: none; +}