;; content-on-sx — tree-wide block transforms.
;;
;; The write counterpart to query: apply a function to every matching block
;; across the tree (descending into sections), returning a new document. For
;; bulk edits — rewrite image srcs, bump heading levels, sanitise text. Tree
;; detection/rebuild is inline (class + st-iv-get/set!) so this needs no
;; section.sx. Immutable.
;;
;; Requires (loaded by harness): block.sx, doc.sx.

(define
  xf-section?
  (fn (b) (and (st-instance? b) (= (get b :class) "CtSection"))))

(define
  block-tree-transform
  (fn
    (blocks pred f)
    (map
      (fn
        (b)
        (let
          ((nb (if (pred b) (f b) b)))
          (if
            (xf-section? nb)
            (let
              ((ch (st-iv-get nb "children")))
              (if
                (list? ch)
                (st-iv-set! nb "children" (block-tree-transform ch pred f))
                nb))
            nb)))
      blocks)))

(define
  content/map-blocks
  (fn
    (doc pred f)
    (doc-with-blocks doc (block-tree-transform (doc-blocks doc) pred f))))

(define
  content/map-type
  (fn
    (doc type f)
    (content/map-blocks doc (fn (b) (= (blk-type b) type)) f)))

;; convenience: set a field on every block of a type.
(define
  content/set-field-on
  (fn
    (doc type field value)
    (content/map-type doc type (fn (b) (blk-set b field value)))))
