;; Hardening — non-core block types (callout/table/media/section) survive the ;; flat and tree CvRDT materialise paths (regression for the ct-class-for-type ;; fix: these route through crdt-element->block -> mk-block). (st-bootstrap-classes!) (content-bootstrap-blocks!) (content-bootstrap-doc!) (content-bootstrap-render!) (content-bootstrap-section!) (content-bootstrap-callout!) (content-bootstrap-table!) (content-bootstrap-media!) ;; ── flat CRDT: callout / table / media leaves ── (define s (crdt-apply-all (crdt-empty) (list (crdt-op-insert "co" "callout" (crdt-pos 1 0) (list (list "kind" "note") (list "text" "hi")) 1 0) (crdt-op-insert "tb" "table" (crdt-pos 2 0) (list (list "headers" (list "A")) (list "rows" (list (list "1")))) 1 0) (crdt-op-insert "vid" "media" (crdt-pos 3 0) (list (list "kind" "video") (list "src" "/v.mp4")) 1 0)))) (content-test "flat crdt callout render" (asHTML (crdt-materialize "d" s)) "
A
1
") (content-test "flat crdt order" (crdt-order s) (list "co" "tb" "vid")) ;; ── flat CRDT: callout field via LWW update ── (define s2 (crdt-update s "co" "text" "edited" 5 1)) (content-test "flat crdt callout update" (str (blk-send (doc-find (crdt-materialize "d" s2) "co") "text")) "edited") ;; ── tree CRDT: callout/table inside a section ── (define t (crdt-tree-apply-all (crdt-empty) (list (crdt-tree-op-insert "sec" "section" (crdt-pos 1 0) "" (list) 1 0) (crdt-tree-op-insert "co" "callout" (crdt-pos 1 0) "sec" (list (list "kind" "tip") (list "text" "T")) 1 0) (crdt-tree-op-insert "tb" "table" (crdt-pos 2 0) "sec" (list (list "headers" (list "H")) (list "rows" (list))) 1 0)))) (content-test "tree crdt nested blocks" (doc-tree-ids (crdt-tree-materialize "d" t)) (list "sec" "co" "tb")) (content-test "tree crdt nested render" (asHTML (crdt-tree-materialize "d" t)) "
H
") ;; ── tree CRDT: concurrent callout inserts into a section converge ── (define base (crdt-tree-insert (crdt-empty) "sec" "section" (crdt-pos 1 0) "" (list) 1 0)) (define rA (crdt-tree-insert base "x" "callout" (crdt-pos 5 1) "sec" (list (list "kind" "note") (list "text" "A")) 2 1)) (define rB (crdt-tree-insert base "y" "media" (crdt-pos 5 2) "sec" (list (list "kind" "audio") (list "src" "/a.mp3")) 2 2)) (content-test "tree crdt mixed converge" (= (get (crdt-tree-merge rA rB) :elements) (get (crdt-tree-merge rB rA) :elements)) true) (content-test "tree crdt mixed ids" (doc-tree-ids (crdt-tree-materialize "d" (crdt-tree-merge rA rB))) (list "sec" "x" "y"))