diff --git a/doerg/package.nix b/doerg/package.nix index be8ffee..d2a1715 100644 --- a/doerg/package.nix +++ b/doerg/package.nix @@ -16,7 +16,7 @@ let }); plex = ibm-plex-web.override { - families = [ "math" "serif" "sans-kr" ]; + families = [ "math" "serif" "sans" "sans-kr" ]; }; in mkCljBin' { name = "net.deertopia/doerg"; diff --git a/doerg/src/net/deertopia/doerg/html.clj b/doerg/src/net/deertopia/doerg/html.clj index 01658fa..76cf513 100644 --- a/doerg/src/net/deertopia/doerg/html.clj +++ b/doerg/src/net/deertopia/doerg/html.clj @@ -37,7 +37,7 @@ (fs/file (format "css/ibm-plex-%s-default.min.css" family)) slurp)] (external-stylesheet - (format "ibm-plex-web/css/ibm-plex-%s-default.min.css" family)))) + (format "ibm-plex-web/css/ibm-plex-%s-all.min.css" family)))) (def deerstar (external-stylesheet "deerstar.css") diff --git a/doerg/src/net/deertopia/doerg/render.clj b/doerg/src/net/deertopia/doerg/render.clj index 51c6610..b49e673 100644 --- a/doerg/src/net/deertopia/doerg/render.clj +++ b/doerg/src/net/deertopia/doerg/render.clj @@ -2,8 +2,10 @@ (:require [net.deertopia.doerg.element :as element] [clojure.stacktrace] [clojure.tools.logging :as l] + [clojure.core.match :refer [match]] [clojure.tools.logging.readable :as lr] [net.deertopia.doerg.html :as doerg-html] + [clojure.pprint] [clojure.zip :as z])) ;;; Top-level API @@ -33,7 +35,8 @@ (def ^:dynamic ^:private *document-info*) -(declare ^:private gather-footnotes renderer-error) +(declare ^:private + gather-footnotes render-renderer-error) (defn org-element-recursive "Recursively render an Org-mode element to Hiccup." @@ -42,10 +45,14 @@ (-> loc (element/cata (fn [node] - (try (org-element node) + (prn node) + (try (let [x (org-element node)] + (println "⇒" (pr-str x)) + (newline) + x) (catch Throwable e (lr/error e "Error in renderer" {:node node}) - (renderer-error e))))) + (render-renderer-error e))))) z/node))) (defn org-document @@ -68,6 +75,9 @@ (defmethod org-element "keyword" [e] (org-keyword e)) +(defmethod org-element "link" [e] + (org-link e)) + (defn- gather-footnotes [loc] @@ -75,21 +85,45 @@ -(defn- render-pprint [x] +(defn- render-pprint + "Render the argument inline as `clojure.pprint/pprint` output." + [x & {:keys [text] + :or {text "debug!"}}] [:details - {:summary (:type x)} + [:summary {:style {:font-family "IBM Plex Sans"}} + (if (:type x) + (list text " (" [:code (:type x)] ")") + text)] [:samp {:style {:overflow "scroll" :display "block" :white-space "pre"}} - ()]]) + (with-out-str + (clojure.pprint/pprint x))]]) + +(defn- level->tag + "Convert a number 1–5 to a hiccup :h1, :h2, :h3, … tag." + [level] + (cond (<= 1 level 5) (keyword (str \h (+ level 1))) + :else :h5)) + +(defn- descriptive-list-item-components + "If `e` is an Org-mode descriptive list item, return a map {:dt x + :dd y} with the corresponding dt and dd tags. Otherwise, return + nil." + [e] + (match (:children e) + ([[:dt & dts] & dds] :seq) {:dt (apply vector :dt dts) + :dd (apply vector :dd dds)} + _ nil)) -(defn- renderer-error +(defn- render-renderer-error "Render a `Throwable` to display within the document." [e] [:details - [:summary "Renderer error!"] + [:summary {:style {:font-family "IBM Plex Sans"}} + "Renderer error!"] [:samp {:style {:overflow "scroll" :display "block" :white-space "pre"}} @@ -100,4 +134,72 @@ [{:keys [children]}] children) -(defmethod org-keyword "TITLE" [e]) +(defmethod org-element "paragraph" [{:keys [children]}] + [:p children]) + +(defmethod org-element "text" [{:keys [value]}] + value) + +(defmethod org-element "bold" [{:keys [children]}] + [:b children]) + +(defmethod org-element "section" [{:keys [children]}] + [:section + (or (seq children) + [:div.empty-section-message "This section is empty…"])]) + +(defmethod org-element "headline" [{:keys [children level]}] + [(level->tag level) children]) + +(defmethod org-element "footnote-reference" + [{:keys [label children]}] + ;; FIXME: This will break if there are multiple references to a + ;; single footnote, since `label` is assumed to be unique. + (list [:label.margin-toggle.sidenote-number {:for label}] + [:input.margin-toggle {:type "checkbox" + :id label}] + [:span.sidenote + "«todo: footnote here lol»"])) + +(defmethod org-element "plain-list" [{:keys [list-type children]}] + (let [tag (case list-type + "descriptive" :dl + "unordered" :ul + "ordered" :ol)] + [tag children])) + +(defmethod org-element "list-item" [{:keys [children] :as e}] + (if-some [{:keys [dt dd]} (descriptive-list-item-components e)] + (list dt dd) + [:li children])) + +(defmethod org-element "list-item-tag" [{:keys [children]}] + [:dt children]) + +(defmethod org-element "property-drawer" [{:keys [children]}] + [:table.property-drawer {:hidden true} + [:tbody children]]) + +(defmethod org-element "node-property" [{:keys [key value]}] + [:tr [:th key] [:td value]]) + +(defmethod org-element "citation" [{:keys [prefix suffix children]}] + [:div prefix children suffix]) + +(defmethod org-keyword "TITLE" [{:keys [value]}] + [:h1 value]) + +(defmethod org-element :default [x] + (render-pprint x :text "unimplemented!")) + +#_#_ +(defmethod org-keyword :default [x] + (render-pprint x :text "unimplemented!")) + +(defmethod org-special-block :default [x] + (render-pprint x :text "unimplemented!")) + +(defmethod org-link :default [{:keys [raw-link children]}] + [:span {:class "org-link external"} + [:a {:href raw-link} + (or (seq children) raw-link)]])