;; Extension — global find/replace across every text-bearing field. (st-bootstrap-classes!) (content/bootstrap!) (content-bootstrap-section!) (content-bootstrap-callout!) (content-bootstrap-table!) (define d (doc-append (doc-append (doc-append (doc-empty "d") (mk-heading "h" 1 "Foo title")) (mk-text "p" "the Foo is here")) (mk-section "s" (list (mk-text "n" "nested Foo") (mk-image "img" "/foo.png" "Foo alt"))))) (define r (content/find-replace d "Foo" "Bar")) ;; ── replaces in heading + text ── (content-test "replace heading" (str (blk-send (doc-deep-find r "h") "text")) "Bar title") (content-test "replace text" (str (blk-send (doc-deep-find r "p") "text")) "the Bar is here") (content-test "replace nested text" (str (blk-send (doc-deep-find r "n") "text")) "nested Bar") ;; ── image alt IS a text field (asText ^ alt), so it is rewritten ── (content-test "image alt replaced" (str (blk-send (doc-deep-find r "img") "alt")) "Bar alt") ;; ── but src is a URL, not prose, so it stays put ── (content-test "image src untouched" (str (blk-send (doc-deep-find r "img") "src")) "/foo.png") ;; ── immutable ── (content-test "original unchanged" (str (blk-send (doc-deep-find d "p") "text")) "the Foo is here") ;; ── multiple occurrences in one block ── (content-test "all occurrences" (str (blk-send (doc-find (content/find-replace (doc-append (doc-empty "d") (mk-text "p" "a a a")) "a" "b") "p") "text")) "b b b") ;; ── code + quote text replaced ── (define d2 (doc-append (doc-append (doc-empty "d") (mk-code "c" "sx" "(old)")) (mk-quote "q" "src" "old saying"))) (define r2 (content/find-replace d2 "old" "new")) (content-test "replace code" (str (blk-send (doc-find r2 "c") "text")) "(new)") (content-test "replace quote" (str (blk-send (doc-find r2 "q") "text")) "new saying") ;; ── callout text is 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") ;; ── list items are rewritten (asText folds items) ── (define rl (content/find-replace (doc-append (doc-empty "d") (mk-list "l" false (list "Foo one" "two Foo"))) "Foo" "Bar")) (content-test "replace first list item" (str (first (blk-send (doc-find rl "l") "items"))) "Bar one") (content-test "replace second list item" (str (first (rest (blk-send (doc-find rl "l") "items")))) "two Bar") ;; ── table headers + cells are rewritten (asText folds rows) ── (define rt (content/find-replace (doc-append (doc-empty "d") (mk-table "t" (list "Foo head") (list (list "a Foo" "b")))) "Foo" "Bar")) (content-test "replace table header" (str (first (table-headers (doc-find rt "t")))) "Bar head") (content-test "replace table cell" (str (first (first (table-rows (doc-find rt "t"))))) "a Bar") ;; ── no match → unchanged render ── (content-test "no match" (asHTML (content/find-replace d "zzz" "qqq")) (asHTML d))