Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: jump to heading #13

Merged
merged 1 commit into from
May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clojure/resources/firn/_firn_starter/static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,7 @@ img {

.firn-headline-timestamp {}
.firn-headline-cookie {}

/* Other "Components" */
.firn-footnote-ref {}
.firn-footnote-def {}
53 changes: 38 additions & 15 deletions clojure/src/firn/markup.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(ns firn.markup
"Namespace responsible for converted org-edn into html."
(:require [clojure.string :as s]
[firn.util :as u]))
[firn.util :as u]
[firn.org :as org]))

(declare to-html)

Expand Down Expand Up @@ -32,6 +33,25 @@
[:span.firn-img-caption desc]]
[:img {:src path}]))

(defn- clean-anchor
"converts `::*My Heading` => #my-heading"
[anchor]
(str "#" (-> anchor
(s/replace #"::\*" "")
(s/replace #" " "-")
(s/lower-case))))

(defn internal-link-handler
"Takes an org link and converts it into an html path."
[org-link]
(let [regex #"(file:)(.*)\.(org)(\:\:\*.+)?"
res (re-matches regex org-link)
anchor-link (last res)
anchor-link (when anchor-link (-> res last clean-anchor))]
(if anchor-link
(str "./" (nth res 2) anchor-link)
(str "./" (nth res 2)))))

(defn link->html
"Parses links from the org-tree.
Checks if a link is an HTTP link or File link."
Expand All @@ -43,12 +63,11 @@
img-http-regex #"(http:\/\/|https:\/\/)(.*)\.(jpg|JPG|gif|GIF|png)"
img-rel-regex #"(\.(.*))\.(jpg|JPG|gif|GIF|png)"
img-make-url #(->> (re-matches img-file-regex link-href)
(take-last 2)
(s/join "."))
(take-last 2)
(s/join "."))
;; file regexs / ctor fns
org-file-regex #"(file:)(.*)\.(org)"
http-link-regex #"https?:\/\/(?![^\" ]*(?:jpg|png|gif))[^\" ]+"
file-path #(str "./" (nth % 2))]
org-file-regex #"(file:)(.*)\.(org)(\:\:\*.+)?"
http-link-regex #"https?:\/\/(?![^\" ]*(?:jpg|png|gif))[^\" ]+"]

(cond
;; Images ---
Expand All @@ -66,7 +85,7 @@

;; org files
(re-matches org-file-regex link-href)
[:a.firn_internal {:href (file-path (re-matches org-file-regex link-href))} link-val]
[:a.firn_internal {:href (internal-link-handler link-href)} link-val]

(re-matches http-link-regex link-href)
[:a.firn_external {:href link-href :target "_blank"} link-val]
Expand All @@ -85,15 +104,19 @@
keywrd (v :keyword)
priority (v :priority)
value (v :value)
parent {:type "headline" :level level :children [v]}
heading-priority (u/str->keywrd "span.firn-headline-priority.firn-headline-priority__" priority)
heading-keyword (u/str->keywrd "span.firn-headline-keyword.firn-headline-keyword__" keywrd)
heading-anchor (-> parent org/get-headline-helper clean-anchor)
;; _ (prn "heading anchor is " heading-anchor)
heading-id+class #(u/str->keywrd "h" % heading-anchor ".firn-headline.firn-headline-" %)
h-level (case level
1 :h1.firn-headline.firn-headline-1
2 :h2.firn-headline.firn-headline-2
3 :h3.firn-headline.firn-headline-3
4 :h4.firn-headline.firn-headline-4
5 :h5.firn-headline.firn-headline-5
:h6.firn-headline-6)
1 (heading-id+class 1)
2 (heading-id+class 2)
3 (heading-id+class 3)
4 (heading-id+class 4)
5 (heading-id+class 5)
(heading-id+class 6))
make-child #(into [%] (map title->html children))]
(case typ
"headline" (make-child :div)
Expand All @@ -114,15 +137,15 @@

(defn- footnote-ref
[v]
[:a.firn_footnote-ref
[:a.firn-footnote-ref
{:id (str "fn-" (v :label))
:href (str "#" (v :label))}
[:sup (v :label)]])

(defn- footnote-def
[v]
(let [make-child #(into [%] (map to-html (v :children)))]
[:span.firn_footnote-def
[:span.firn-footnote-def
[:span {:id (v :label)
:style "padding-right: 8px"} (v :label)]
(make-child :span)
Expand Down
23 changes: 10 additions & 13 deletions clojure/src/firn/org.clj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
(prn "Orgize failed to parse file." stripped res)
(res :out)))))

(defn- get-headline-helper
(defn get-headline-helper
"Sanitizes a heading of links and just returns text.
Necessary because org leafs of :type `link` have a `:desc` and not a `:value`

Expand All @@ -48,15 +48,16 @@
(case (:type child)
"text" (get-trimmed-val child :value)
"link" (get-trimmed-val child :desc)
"code" (get-trimmed-val child :value)
"")))))))

(defn get-headline
"Fetches a headline from an org-mode tree."
[tree name]
(->> (tree-seq map? :children tree)
(filter #(and (= "headline" (:type %))
(= name (get-headline-helper %))))
(first)))
(filter #(and (= "headline" (:type %))
(= name (get-headline-helper %))))
(first)))

(defn get-headline-content
"Same as get-headline, but removes the first child :title)."
Expand Down Expand Up @@ -100,7 +101,6 @@
:log-sum log-sum
:hour-sum (u/timestr->hour-float log-sum)}))))


(defn logbook-year-stats
"Takes a logbook and pushes it's data into a year calendar.
Returns a map that looks like:
Expand Down Expand Up @@ -133,21 +133,18 @@
:as opts}]
[:div
(for [[year year-of-logs] (logbook-year-stats logbook)
:let [
max-log (apply max-key :hour-sum year-of-logs) ;; Don't need this yet.
:let [max-log (apply max-key :hour-sum year-of-logs) ;; Don't need this yet.
;; This should be measured against the height and whatever the max-log is.
g-multiplier (/ height 8) ;; 8 - max hours we expect someone to log in a day
fmt-points #(str %1 "," (* g-multiplier (%2 :hour-sum)))
points (s/join " " (->> year-of-logs (map-indexed fmt-points)))]]


[:div
[:h5.firn-headline.firn-headline-5 year]
[:svg {:viewbox (format "0 0 %s %s" width height),
[:svg {:viewbox (format "0 0 %s %s" width height)
:class "chart"}
[:g {:transform (format "translate(0, %s) scale(1, -1)", (- height (* stroke-width 1.25)))}
[:polyline {:fill "none",
:stroke stroke,
:stroke-width "1",
[:polyline {:fill "none"
:stroke stroke
:stroke-width "1"
:points points}]]]])]))

7 changes: 7 additions & 0 deletions clojure/test/firn/markup_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@
(t/testing "internal-link"
(t/is (= (sut/link->html (sample-links :file-link))
[:a.firn_internal {:href "./file2"} "File 2"]))))

(t/deftest internal-link-handler
(t/testing "Expected results."
(let [res1 (sut/internal-link-handler "file:foo.org")
res2 (sut/internal-link-handler "file:foo.org::*my headline link")]
(t/is (= res1 "./foo"))
(t/is (= res2 "./foo#my-headline-link")))))
22 changes: 22 additions & 0 deletions clojure/test/firn/org_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,28 @@
(t/testing "It returns the expected value."
(t/is (= (-> res :children first :type) "section")))))

(t/deftest get-headline-helper
(t/testing "expected output"
(let [sample-data
{:type "headline",
:level 1,
:children
[{:type "title", :level 1, :tags ["ATTACH"], :raw "Image Tests", :children [{:type "text", :value "Image Tests"}]}]}

sample-data-with-multiple-children
{:type "headline",
:level 1,
:children
[{:type "title", :level 1, :raw "Headlines <2020-03-27 Fri>", :properties {:foo "bar"},
:children [{:type "text", :value "Headlines "} {:type "timestamp", :timestamp_type "active", :start {:year 2020, :month 3, :day 27, :dayname "Fri"}}]}]}

res1 (sut/get-headline-helper sample-data)
res2 (sut/get-headline-helper sample-data-with-multiple-children)]

(t/is (= res1 "Image Tests"))
(t/is (= res2 "Headlines")))))


(t/deftest parsed-org-date->unix-time
(t/testing "returns the expected value."
(t/is (= 1585683360000
Expand Down