Created
June 1, 2024 03:39
-
-
Save danodic/530021d72f9335d3f2391900ec43aad7 to your computer and use it in GitHub Desktop.
Transform a list of html headings and return a TOC tree
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; I had to create a Table of Contents component for my personal site, and in | |
;; order to do that I had to scan all headings in the document (using .querySelectorAll) | |
;; and transform them into a list of maps that I could use to nest them properly. | |
;; The idea is to get a plain vector of nodes created using `make-node` and return | |
;; a tree in which nodes are nested according to their level. | |
(defn make-node | |
"Creates the representation of an HTML heading. You can search for all headings | |
in your document and convert them to this structure." | |
[tag-name tag-level value] | |
{:tag (keyword tag-name) | |
:level tag-level | |
:value value}) | |
(defn parse-nodes | |
"Given a vector of nodes created with `make-node`, transforms the vector into a | |
tree composed of nested vectors." | |
[elements current-level] | |
(loop [elements-left elements | |
parsed-elements []] | |
(if-not (empty? elements-left) | |
(let [next-element (first elements-left) | |
element-level (:level next-element)] | |
(cond | |
(> element-level current-level) (let [[r-parsed r-left] (parse-nodes elements-left (inc current-level))] | |
(recur r-left (conj parsed-elements r-parsed))) | |
(< element-level current-level) [parsed-elements elements-left] | |
:else (recur (drop 1 elements-left) (conj parsed-elements next-element)))) | |
[parsed-elements elements-left]))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment