;; Extension — relative block reorder + tree reparent. (st-bootstrap-classes!) (content/bootstrap!) (content-bootstrap-section!) (define d (doc-append (doc-append (doc-append (doc-empty "d") (mk-text "a" "A")) (mk-text "b" "B")) (mk-text "c" "C"))) ;; ── move-before ── (content-test "move-before" (doc-ids (content/move-before d "c" "a")) (list "c" "a" "b")) (content-test "move-before mid" (doc-ids (content/move-before d "c" "b")) (list "a" "c" "b")) (content-test "move-before immutable" (doc-ids d) (list "a" "b" "c")) ;; ── move-after ── (content-test "move-after" (doc-ids (content/move-after d "a" "b")) (list "b" "a" "c")) (content-test "move-after last" (doc-ids (content/move-after d "a" "c")) (list "b" "c" "a")) ;; ── move-to-front / back ── (content-test "move-to-front" (doc-ids (content/move-to-front d "c")) (list "c" "a" "b")) (content-test "move-to-back" (doc-ids (content/move-to-back d "a")) (list "b" "c" "a")) (content-test "front already first" (doc-ids (content/move-to-front d "a")) (list "a" "b" "c")) ;; ── no-ops ── (content-test "missing id no-op" (doc-ids (content/move-before d "zzz" "a")) (list "a" "b" "c")) (content-test "missing target no-op" (doc-ids (content/move-before d "a" "zzz")) (list "a" "b" "c")) ;; ── render after move ── (content-test "render after move" (asHTML (content/move-after d "a" "c")) "

B

C

A

") ;; ── reparent: move a top-level block INTO a section ── (define nd (doc-append (doc-append (doc-empty "d") (mk-text "p" "P")) (mk-section "s" (list (mk-text "x" "X"))))) (content-test "move-into: block leaves top level" (doc-ids (content/move-into nd "p" "s" 1)) (list "s")) (content-test "move-into: block lands in section at index" (doc-tree-ids (content/move-into nd "p" "s" 1)) (list "s" "x" "p")) (content-test "move-into at front of section" (doc-tree-ids (content/move-into nd "p" "s" 0)) (list "s" "p" "x")) (content-test "move-into immutable" (doc-tree-ids nd) (list "p" "s" "x")) ;; ── reparent: move a NESTED block to a different section ── (define two (doc-append (doc-append (doc-empty "d") (mk-section "s1" (list (mk-text "n" "N")))) (mk-section "s2" (list (mk-text "y" "Y"))))) (content-test "move-into across sections" (doc-tree-ids (content/move-into two "n" "s2" 1)) (list "s1" "s2" "y" "n")) ;; ── promote: nested block out to top level (appended last) ── (content-test "promote nested to top level" (doc-tree-ids (content/promote two "n")) (list "s1" "s2" "y" "n")) (content-test "promote leaves section empty shell" (doc-ids (content/promote two "n")) (list "s1" "s2" "n")) (content-test "promote a whole section keeps its subtree" (doc-tree-ids (content/promote (doc-append (doc-empty "d") (mk-section "o" (list (mk-section "i" (list (mk-text "z" "Z")))))) "i")) (list "o" "i" "z")) ;; ── cycle guard: cannot move a section into its own descendant ── (define nest (doc-append (doc-empty "d") (mk-section "outer" (list (mk-section "inner" (list (mk-text "t" "T"))))))) (content-test "move section into its own child is a no-op" (doc-tree-ids (content/move-into nest "outer" "inner" 0)) (list "outer" "inner" "t")) (content-test "move block into itself is a no-op" (doc-tree-ids (content/move-into nest "inner" "inner" 0)) (list "outer" "inner" "t")) ;; ── reparent no-ops on missing ids ── (content-test "move-into missing block no-op" (doc-tree-ids (content/move-into nd "zzz" "s" 0)) (list "p" "s" "x")) (content-test "move-into missing section no-op" (doc-tree-ids (content/move-into nd "p" "zzz" 0)) (list "p" "s" "x")) (content-test "promote missing no-op" (doc-tree-ids (content/promote nd "zzz")) (list "p" "s" "x"))