;; content-on-sx — nested document outline.
;;
;; Builds a hierarchical heading tree from content/headings: each node is
;; {:id :text :level :children}, where a heading nests under the nearest
;; preceding heading of a lower level. The structured companion to the flat TOC,
;; for rendering nested navigation.
;;
;; Requires (loaded by harness): query.sx (content/headings).

;; consume a prefix of `hs` forming nodes whose level > minlevel; return
;; {:nodes ... :rest ...}.
(define
  ol-forest
  (fn
    (hs minlevel)
    (if
      (= (len hs) 0)
      {:rest (list) :nodes (list)}
      (let
        ((h (first hs)))
        (if
          (<= (get h :level) minlevel)
          {:rest hs :nodes (list)}
          (let
            ((sub (ol-forest (rest hs) (get h :level))))
            (let
              ((node {:id (get h :id) :text (get h :text) :children (get sub :nodes) :level (get h :level)}))
              (let
                ((more (ol-forest (get sub :rest) minlevel)))
                {:rest (get more :rest) :nodes (cons node (get more :nodes))}))))))))

(define
  content/outline
  (fn (doc) (get (ol-forest (content/headings doc) 0) :nodes)))
