diff --git a/lib/content/find-replace.sx b/lib/content/find-replace.sx index 4c22e179..2b9b34f5 100644 --- a/lib/content/find-replace.sx +++ b/lib/content/find-replace.sx @@ -1,8 +1,9 @@ ;; content-on-sx — global find/replace across text-bearing blocks. ;; -;; Replaces every occurrence of `from` with `to` in the text field of text / -;; heading / code / quote blocks, tree-wide (via the transform layer). For -;; renaming a term throughout a document. Immutable; case-sensitive. +;; Replaces every occurrence of `from` with `to` in the `text` field of +;; text / heading / code / quote / callout blocks, tree-wide (via the transform +;; layer). For renaming a term throughout a document. Immutable; case-sensitive. +;; (Same text-bearing set asText/stats/summary treat as content.) ;; ;; Requires (loaded by harness): block.sx, transform.sx (content/map-blocks). @@ -17,7 +18,9 @@ (define fr-has-text? - (fn (b) (fr-in? (blk-type b) (list "text" "heading" "code" "quote")))) + (fn + (b) + (fr-in? (blk-type b) (list "text" "heading" "code" "quote" "callout")))) (define content/find-replace diff --git a/lib/content/scoreboard.json b/lib/content/scoreboard.json index 4531cd82..1dbed8dc 100644 --- a/lib/content/scoreboard.json +++ b/lib/content/scoreboard.json @@ -21,7 +21,7 @@ "flatten": {"pass": 10, "fail": 0}, "transform": {"pass": 12, "fail": 0}, "normalize": {"pass": 11, "fail": 0}, - "find-replace": {"pass": 10, "fail": 0}, + "find-replace": {"pass": 12, "fail": 0}, "stats": {"pass": 17, "fail": 0}, "summary": {"pass": 14, "fail": 0}, "index": {"pass": 13, "fail": 0}, @@ -42,7 +42,7 @@ "md-doc": {"pass": 12, "fail": 0}, "fed": {"pass": 20, "fail": 0} }, - "total_pass": 750, + "total_pass": 752, "total_fail": 0, - "total": 750 + "total": 752 } diff --git a/lib/content/scoreboard.md b/lib/content/scoreboard.md index 15c1ba85..09e808d9 100644 --- a/lib/content/scoreboard.md +++ b/lib/content/scoreboard.md @@ -25,7 +25,7 @@ _Generated by `lib/content/conformance.sh`_ | flatten | 10 | 0 | 10 | | transform | 12 | 0 | 12 | | normalize | 11 | 0 | 11 | -| find-replace | 10 | 0 | 10 | +| find-replace | 12 | 0 | 12 | | stats | 17 | 0 | 17 | | summary | 14 | 0 | 14 | | index | 13 | 0 | 13 | @@ -45,4 +45,4 @@ _Generated by `lib/content/conformance.sh`_ | md-import | 38 | 0 | 38 | | md-doc | 12 | 0 | 12 | | fed | 20 | 0 | 20 | -| **Total** | **750** | **0** | **750** | +| **Total** | **752** | **0** | **752** | diff --git a/lib/content/tests/find-replace.sx b/lib/content/tests/find-replace.sx index 67e721d9..742dc3c0 100644 --- a/lib/content/tests/find-replace.sx +++ b/lib/content/tests/find-replace.sx @@ -3,6 +3,7 @@ (st-bootstrap-classes!) (content/bootstrap!) (content-bootstrap-section!) +(content-bootstrap-callout!) (define d @@ -76,6 +77,32 @@ (str (blk-send (doc-find r2 "q") "text")) "new saying") +;; ── callout text is now covered (consistency with asText/stats/summary) ── +(content-test + "replace callout text" + (str + (blk-send + (doc-find + (content/find-replace + (doc-append (doc-empty "d") (mk-callout "co" "note" "Foo here")) + "Foo" + "Bar") + "co") + "text")) + "Bar here") +(content-test + "callout kind untouched by text replace" + (str + (blk-send + (doc-find + (content/find-replace + (doc-append (doc-empty "d") (mk-callout "co" "note" "x")) + "note" + "X") + "co") + "kind")) + "note") + ;; ── no match → unchanged render ── (content-test "no match" diff --git a/plans/content-on-sx.md b/plans/content-on-sx.md index 6187f5fd..7bf39f68 100644 --- a/plans/content-on-sx.md +++ b/plans/content-on-sx.md @@ -19,7 +19,7 @@ injected adapter, not core. ## Status (rolling) -`bash lib/content/conformance.sh` → **750/750** (Phases 1–4 COMPLETE + ~34 extensions, hardened: HTML/SX escaping, Markdown render + import/export incl. tables & frontmatter (full round-trip), CvRDT flat + nested-tree + durable replication, tree-aware validation, snapshot cache, doc metadata, plain-text render, nested block trees + deep editing + flatten + relative reorder, doc stats + summary + multi-doc index, table + callout + media blocks, HTML page wrapper + SEO page, doc composition + id-remap, portable data + wire serialization, block query + transforms + find/replace, TOC + anchored headings + outline, normalization) +`bash lib/content/conformance.sh` → **752/752** (Phases 1–4 COMPLETE + ~34 extensions, hardened: HTML/SX escaping, Markdown render + import/export incl. tables & frontmatter (full round-trip), CvRDT flat + nested-tree + durable replication, tree-aware validation, snapshot cache, doc metadata, plain-text render, nested block trees + deep editing + flatten + relative reorder, doc stats + summary + multi-doc index, table + callout + media blocks, HTML page wrapper + SEO page, doc composition + id-remap, portable data + wire serialization, block query + transforms + find/replace, TOC + anchored headings + outline, normalization) ## Ground rules @@ -113,6 +113,13 @@ lib/content/api.sx ── (content/edit) (content/render) (content/history) ─ ## Progress log +- 2026-06-07 — Consistency: `find-replace` now covers `callout` text. `fr-has-text?` + (find-replace.sx) added `callout` to its text-bearing block kinds, matching + `asText`/stats/summary which already treat callout bodies as prose. Previously a + `content/find-replace` over a doc containing callouts silently skipped them. +2 + find-replace tests (replace callout text; callout kind untouched by text replace). + 752/752 (41 suites). + - 2026-06-07 — Hardening: fixed a real layer seam (surfaced in the architecture review) — by-id ops (update/delete) now act TREE-WIDE. `ct-replace-id` / `ct-remove-id` (doc.sx) descend into any block carrying a `children` list, so