;; Extension — block query + table of contents + prose search.

(st-bootstrap-classes!)
(content/bootstrap!)
(content-bootstrap-text!)
(content-bootstrap-section!)
(content-bootstrap-table!)
(content-bootstrap-callout!)

(define
  d
  (doc-append
    (doc-append
      (doc-append
        (doc-append (doc-empty "d") (mk-heading "h1" 1 "Intro"))
        (mk-text "p1" "para"))
      (mk-image "img" "/a.png" "alt"))
    (mk-section
      "s"
      (list
        (mk-heading "h2" 2 "Sub")
        (mk-text "p2" "more")
        (mk-image "img2" "/b.png" "b")))))

;; ── select-type (tree-wide) ──
(content-test
  "select headings ids"
  (map (fn (b) (blk-id b)) (content/select-type d "heading"))
  (list "h1" "h2"))
(content-test
  "select images ids"
  (map (fn (b) (blk-id b)) (content/select-type d "image"))
  (list "img" "img2"))
(content-test
  "select text ids"
  (map (fn (b) (blk-id b)) (content/select-type d "text"))
  (list "p1" "p2"))
(content-test
  "select section ids"
  (map (fn (b) (blk-id b)) (content/select-type d "section"))
  (list "s"))

;; ── count-type ──
(content-test "count headings" (content/count-type d "heading") 2)
(content-test "count images" (content/count-type d "image") 2)
(content-test "count dividers" (content/count-type d "divider") 0)

;; ── select with custom predicate ──
(content-test
  "select-ids custom"
  (content/select-ids d (fn (b) (= (blk-type b) "image")))
  (list "img" "img2"))
(content-test
  "select custom field"
  (map
    (fn (b) (blk-id b))
    (content/select
      d
      (fn
        (b)
        (if
          (= (blk-type b) "heading")
          (= (blk-get b "level") 2)
          false))))
  (list "h2"))

;; ── headings / TOC ──
(content-test
  "headings TOC"
  (content/headings d)
  (list {:id "h1" :text "Intro" :level 1} {:id "h2" :text "Sub" :level 2}))
(content-test
  "empty doc no headings"
  (content/headings (doc-empty "e"))
  (list))

;; ── deeply nested ──
(define
  deep
  (doc-append
    (doc-empty "d")
    (mk-section
      "o"
      (list (mk-section "i" (list (mk-heading "deep" 3 "Deep")))))))
(content-test
  "deep heading found"
  (map (fn (b) (blk-id b)) (content/select-type deep "heading"))
  (list "deep"))
(content-test
  "deep toc level"
  (get (first (content/headings deep)) :level)
  3)

;; ── prose search (content/search-text) ──
;; "cat" appears in text, image alt, a list item, a table cell, and a callout
;; — every text-bearing field — so search must find all five via asText.
(define
  sd
  (doc-append
    (doc-append
      (doc-append
        (doc-append
          (doc-append
            (doc-empty "sd")
            (mk-heading "sh" 1 "Welcome aboard"))
          (mk-text "st" "the cat sat"))
        (mk-image "si" "/x.png" "a cat photo"))
      (mk-list "sl" false (list "first cat" "second dog")))
    (mk-section
      "sec"
      (list
        (mk-table "stb" (list "Animal") (list (list "cat") (list "fish")))
        (mk-callout "sc" "note" "beware of cat")))))

(content-test
  "search across every text-bearing field"
  (content/search-text-ids sd "cat")
  (list "st" "si" "sl" "stb" "sc"))
(content-test "search count" (len (content/search-text sd "cat")) 5)
(content-test
  "search heading text"
  (content/search-text-ids sd "Welcome")
  (list "sh"))
(content-test
  "search list item only"
  (content/search-text-ids sd "dog")
  (list "sl"))
(content-test "search no match" (content/search-text-ids sd "zzz") (list))
;; section containers are excluded — a term living only inside a section's
;; children returns the child, never the section wrapper.
(content-test
  "search excludes section wrapper"
  (content/search-text-ids sd "fish")
  (list "stb"))
(content-test
  "search returns block objects"
  (blk-id (first (content/search-text sd "Welcome")))
  "sh")
