diff --git a/.drone.yml b/.drone.yml
index 0a152a2..538ea6e 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -15,7 +15,7 @@ steps:
path: /drone/cache/
commands:
- ls -la /drone/cache/.m2
- - clojure -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -P -M:shadow-cljs-run
+ - clj -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -P -M:shadow-cljs-run
- name: build-clojure
pull: always
@@ -25,13 +25,40 @@ steps:
path: /drone/cache/
commands:
- ls -la /drone/cache/.m2
- - clj -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -Mshadow-cljs-run release app --debug
+ - clj -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -Mshadow-cljs-run release app --debug
- - name: deploy-site
+ # - name: deploy-site
+ # pull: True
+ # image: appleboy/drone-scp
+ # depends_on:
+ # - build-clojure
+ # settings:
+ # host: blog.digitaloctave.com
+ # port: 22
+ # username:
+ # from_secret: ssh_user
+ # key:
+ # from_secret: ssh_key
+ # target: /var/www/portfolio/${DRONE_COMMIT_SHA:0:10}/
+ # source: /drone/src/development/resources/public/*
+ # strip_components: 5
+
+ - name: build-static-blog
+ pull: always
+ image: clojure:tools-deps
+ volumes:
+ - name: cache
+ path: /drone/cache/
+ commands:
+ - ls -la /drone/cache/.m2
+ - clj -M:blog:shadow-cljs-run release blog
+ #- clj -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -Mshadow-cljs-run release app --debug
+
+ - name: deploy-static-blog
pull: True
image: appleboy/drone-scp
depends_on:
- - build-clojure
+ - build-static-blog
settings:
host: blog.digitaloctave.com
port: 22
@@ -39,30 +66,28 @@ steps:
from_secret: ssh_user
key:
from_secret: ssh_key
- target: /var/www/portfolio/${DRONE_COMMIT_SHA:0:10}/
- source: /drone/src/development/resources/public/*
- strip_components: 5
+ target: /var/www/new-blog/
+ source: /drone/src/resources/public/*
+ strip_components: 4
- - name: promote-deployed-site
- pull: True
- image: appleboy/drone-ssh
- depends_on:
- - deploy-site
- settings:
- host: blog.digitaloctave.com
- port: 22
- username:
- from_secret: SSH_USER
- key:
- from_secret: SSH_KEY
- port: 22
- command_timeout: 5m
- script:
- - cd /var/www/portfolio/
- - rm /var/www/portfolio/promoted
- - ln -s /var/www/portfolio/${DRONE_COMMIT_SHA:0:10} /var/www/portfolio/promoted
- depends_on:
- - deploy-site
+ # - name: promote-deployed-site
+ # pull: True
+ # image: appleboy/drone-ssh
+ # depends_on:
+ # - deploy-site
+ # settings:
+ # host: blog.digitaloctave.com
+ # port: 22
+ # username:
+ # from_secret: SSH_USER
+ # key:
+ # from_secret: SSH_KEY
+ # port: 22
+ # command_timeout: 5m
+ # script:
+ # - cd /var/www/portfolio/
+ # - rm /var/www/portfolio/promoted
+ # - ln -s /var/www/portfolio/${DRONE_COMMIT_SHA:0:10} /var/www/portfolio/promoted
volumes:
- name: cache
diff --git a/.gitignore b/.gitignore
index 6979b1a..5a78479 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,7 @@ projects/**/pom.xml
# Calva VS Code Extension
.calva/output-window/output.calva-repl
+/.shadow-cljs/
+/.lsp/
+/node_modules/
+/.clj-kondo/*
diff --git a/bases/do-blog/deps.edn b/bases/do-blog/deps.edn
new file mode 100644
index 0000000..aa4cb27
--- /dev/null
+++ b/bases/do-blog/deps.edn
@@ -0,0 +1,25 @@
+{:paths ["src" "resources"]
+ :deps {
+ org.clojure/core.async {:mvn/version "1.6.673"}
+ org.clojure/clojurescript {:mvn/version "1.11.60"}
+
+ reagent/reagent {:mvn/version "1.1.1"}
+ tick/tick {:mvn/version "0.5.0"}
+ metosin/reitit {:mvn/version "0.5.18"}
+
+ cljs-ajax/cljs-ajax {:mvn/version "0.8.4"}
+
+ datascript/datascript {:mvn/version "1.4.0"}
+ olymk2/tachyon-reagent {:git/url "https://gitlab.com/olymk2/tachyon-reagent.git"
+ :sha "e422af7b41266f7bc90ab78a24fb93f32be61385"}
+ olymk2/cl-eorg {:git/url "https://gitlab.com/olymk2/cl-org.git"
+ :sha "13e57f11da75516844922fe28bfd6aa7692b7c34"}
+
+ }
+ :aliases {:dev {:extra-deps {thheller/shadow-cljs {:mvn/version "2.25.2"}
+ cider/cider-nrepl {:mvn/version "0.50.2"}
+ refactor-nrepl/refactor-nrepl {:mvn/version "3.10.0"}
+ cider/piggieback {:mvn/version "0.5.3"}}}
+
+ :test {:extra-paths ["test"]
+ :extra-deps {}}}}
diff --git a/bases/do-blog/resources/do-blog/.keep b/bases/do-blog/resources/do-blog/.keep
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/bases/do-blog/resources/do-blog/.keep
@@ -0,0 +1 @@
+
diff --git a/development/resources/public/cljs-out/.keep b/bases/do-blog/resources/documents/readme.org
similarity index 100%
rename from development/resources/public/cljs-out/.keep
rename to bases/do-blog/resources/documents/readme.org
diff --git a/bases/do-blog/resources/public/404.html b/bases/do-blog/resources/public/404.html
new file mode 100644
index 0000000..3c70fd6
--- /dev/null
+++ b/bases/do-blog/resources/public/404.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Initiating Blog
+
+
Application is loading, if nothing happens ensure javascript is enabled.
+
+
+
+
+
+
+
+
diff --git a/bases/do-blog/resources/public/index.html b/bases/do-blog/resources/public/index.html
new file mode 100644
index 0000000..a21738a
--- /dev/null
+++ b/bases/do-blog/resources/public/index.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Initiating Blog
+
+
Application is loading, if nothing happens ensure javascript is enabled.
+
+
+
+
+
+
+
+
+
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/core.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/core.cljs
new file mode 100644
index 0000000..25ae5f5
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/core.cljs
@@ -0,0 +1,340 @@
+(ns com.oly.static-sites.do-blog.core
+ (:require [ajax.core :refer [GET text-response-format]]
+ [com.oly.static-sites.do-blog.theme :refer [tachyon-theme]]
+ [cl-eorg.html :refer [org->to-hiccup]]
+ [cl-eorg.parser :as parser]
+ [cljs.reader :as reader]
+ [datascript.core :as d]
+ [clojure.string :as str]
+ [reagent.core :as r]
+ [reagent.dom :as dom]
+ [reitit.frontend :as rf]
+ [reitit.frontend.easy :as rfe]
+ [tachyons.cards :refer [profile-card]]
+ [clojure.core.async :refer [! chan go]]
+ [tick.core :as t]
+ [tick.timezone]
+ [tick.locale-en-us]
+ ;; [cljsjs.js-joda-timezone]
+ ;; [henryw374.js-joda-locale_en-us]
+ [com.oly.static-sites.do-blog.pages.helpers.database
+ :refer [state document conn schema latest-article search-articles]]
+ [com.oly.static-sites.do-blog.pages.home :refer [home-page]]
+ [com.oly.static-sites.do-blog.pages.article :refer [article-page]]
+ [com.oly.static-sites.do-blog.pages.archive :refer [archive-page]]
+ [com.oly.static-sites.do-blog.pages.about :refer [about-page]])
+ (:require-macros [cl-eorg.macros :refer [org-doc->move-process inline-filelist-map]]))
+
+
+;(set! js/JSJoda (.use js/JSJoda js/JSJodaLocale))
+
+(inline-filelist-map "bases/do-blog/resources/documents/")
+
+(org-doc->move-process
+ "bases/do-blog/resources/documents/"
+ "bases/do-blog/resources/public/documents/")
+
+(d/listen!
+ conn
+ (fn [tx-report]
+ ;; Only update if data was modified
+ (when (:tx-data tx-report)
+ (swap! state update :new-data inc))))
+
+(defn convert-date [text]
+ (when text
+ (let [parts (-> text
+ clojure.string/trim
+ (clojure.string/split #" "))]
+ (-> (t/date (first parts))))))
+
+
+(defn href
+ "Build up path to document"
+ [doc]
+ (str (rfe/href :posts {:path ""}) (:relative-path doc)))
+
+(defn fetch-document-cb [doc callback]
+ (GET (str "/documents/" doc)
+ {:response-format (text-response-format)
+ :handler callback}))
+
+(defn org-dsl-render
+ "Render and store parsed documents"
+ [doc]
+ (swap! state assoc-in [:document :body] (parser/parse doc))
+ (swap! state assoc-in [:document :hiccup] (into [:div] (vec (rest (org->to-hiccup tachyon-theme (-> @state :document :body))))))
+ (swap! state assoc-in [:document :details] (parser/filter-root-nodes [] (-> @state :document :body))))
+
+(defn render-doc-from-path [path]
+ (if path
+ (let [comm (r/atom (chan))]
+ (fetch-document-cb path #(go (>! @comm %)))
+ (go (reset! document ( (latest-article)
+ (render-doc-from-path)))
+
+(defn select-initial-page
+ [path-params]
+ (if path-params
+ (render-doc-from-path path-params)
+ (-> (latest-article)
+ (render-doc-from-path))))
+
+(defn ui-search [search]
+ [:div
+ [:input.w-100.center.input-reset.ba.b--black-20.pa2.mb2
+ {:type "text"
+ :placeholder "Search"
+ :on-change (fn [evt]
+ (swap! state assoc :search {:terms (-> evt .-target .-value)}))}]])
+
+(defn ui-sidebar [{:keys [sidebar body]}]
+ (let [search (r/atom "")]
+ (fn [{:keys [sidebar body]}]
+ [:div.h-100.flex.items-stretch
+ [:div.dn.db-l.pa3.bg-blue {:style {:flex-basis "20rem" :flex-grow "1"}} sidebar]
+ [:div.ma3.pa3 {:style {:flex-basis "0" :flex-grow "999"}}
+ [ui-search search]
+ body]])))
+
+#_(defn ui-tags [meta]
+ [:div (map-indexed
+ (fn [idx tag]
+ [:span.mr2 {:key idx}
+ [pill-grow
+ {:href (rfe/href :archive {:tag tag})
+ :text tag}]])
+ (-> meta :filetags extract-tags))])
+
+#_(defn title-text-image [{:keys [title content] :as optional} tags]
+ [:article.lh-copy.f4.mt-0
+ [:h1.f2 title]
+ (when tags
+ [ui-tags tags])
+ (when (:img-src optional)
+ [:img.w-100.f5.measure {:src (:img-src optional) :alt (:img-alt optional)}])
+ content])
+
+(defn layout [content]
+ (let [org-index (r/cursor state [:index])]
+ (fn [content]
+ [:<>
+ [:link {:rel "stylesheet" :href "https://unpkg.com/tachyons@4.12.0/css/tachyons.min.css"}]
+ [:link {:rel "stylesheet" :href "https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/fontawesome.min.css"}]
+ [:style
+ ".font{font-family: \"Roboto Slab\",serif !important;}"
+ ".r90{transition: all 3s; transform-style: preserve-3d; transform-origin: top left; transform: rotate3d(0,1,0,180deg); backface-visibility: visible;}
+
+
+ .r180-back{transition: all 3s; transform-style: preserve-3d; transform-origin: top left; transform: rotate3d(0,1,0,180deg); backface-visibility: visible;}
+ .r180-front{transition: all 3s; transform-style: preserve-3d; transform-origin: top left; transform: rotate3d(0,1,0,180deg); backface-visibility: hidden;}
+ .r0{transition: all 3s; transform-style: preserve-3d; transform-origin: top left; transform: rotate3d(0,1,0,0deg); backface-visibility: visible;}"]
+ [:div.font.h-100
+ [ui-sidebar
+ {:body content
+ :sidebar [:div
+ [profile-card {:name "Oly" :tagline "Earthling, Software Engineer" :img-src "/images/default/me.png"}]
+ [:ul.list.pl0.measure.center
+ [:li.lh-copy.pv3.b--black-30.ba.bt-0.bl-0.br-0
+ [:a.black.f3.link.hover-green
+ {:href (rfe/href :homepage)} "Home"]]
+ [:li.lh-copy.pv3.b--black-30.ba.bt-0.bl-0.br-0
+ [:a.black.f3.link.hover-green
+ {:href (rfe/href :archive {:tag ""})} "Past articles"]]
+ [:li.lh-copy.pv3.b--black-30.ba.bt-0.bl-0.br-0
+ [:a.black.f3.link.hover-green
+ {:href (rfe/href :about)} "About"]]
+ #_[:li.lh-copy.pv3.b--black-30.ba.bt-0.bl-0.br-0
+ [:a.black.f3.link.hover-green
+ {:href (rfe/href :book {:path ""})} "Book test"]]]]}]]])))
+
+(defn book-page [front back current-page page degrees callback]
+ [:div.outline.w-50.v-mid.absolute.center.bg-blue.r0
+ {:onMouseUp #(when (<= current-page page) (callback inc))
+ :style {:left "50%" :height "105px"
+ :backface-visibility "hidden"
+ :transform (str "rotate3D(0,1,0,"
+ degrees
+ #_(if (<= (+ 1 current-page) page)
+ 0
+ 180)
+ "deg")}}
+
+ [:div.w-100.h-100.absolute.bg-green
+ {:onMouseUp #(when (> current-page page) (callback dec))
+ :style {:backface-visibility "hidden"
+ :transform
+ (str "rotate3D(0,1,0,"
+ 180
+ "deg")}}
+ (+ 1 page)
+ "-" degrees "-"
+ back]
+ page "-" degrees "-" front])
+
+(defn rotate-test
+ []
+ (let [current-page (r/atom 1)
+ flick (fn [dir] (prn dir)
+ (swap! current-page dir))
+ pages (vec (search-articles {}))
+ p (r/track! (fn []
+ (prn @current-page)
+ (prn (- @current-page 1))
+ (prn (+ 4 @current-page))
+ (subvec pages 0 4 #_#_(- @current-page 1) (+ 4 @current-page))))]
+ (fn []
+ [:div
+ (str (count pages))
+ (str (nth @p 1))
+ (str @current-page)
+ [:div.flex.relative.center
+ [:<>
+ [book-page
+ (:title (nth @p 2))
+ (:title (nth @p 3))
+ @current-page 3
+ (if (<= (* 180 (- @current-page 2)) 0) 0 (* 180 (- @current-page 2)))
+ flick]
+ [book-page
+ (:title (first @p))
+ (:title (second @p))
+ @current-page 1
+ (* 180 (- 1 @current-page))
+ flick]]]
+
+ @current-page])))
+
+;(partition 4 [1 2 3 4 5 6 7 8 9 10])
+;(mod 360 180)
+(defn book-pages
+ [& pages]
+ (let [current-page (r/atom 0)
+ flick (fn [idx dir] (swap! current-page dir))]
+ (fn [pages]
+ [:div.flex.relative.center @current-page
+ (doall
+ (->> pages
+ (map-indexed (fn [idx page] [(+ 1 idx) page]))
+ (reverse)
+ ;(partition 4)
+ ;(first)
+ (map (fn [[idx page]]
+ [:<> {:key idx}
+ [:div.outline.w-50.v-mid.absolute.center.bg-blue
+ {:onMouseUp #(flick idx inc)
+ :class (when (>= @current-page idx) "r0")
+ :style {:left "50%" :height "1050px"
+ :transform (if (< idx @current-page)
+ ;(str "rotate3D(0,1,0,360deg)")
+ (str "rotate3D(0,1,0," (* @current-page 180) "deg)")
+ (str "rotate3D(0,1,0," (* @current-page 180) "deg)")
+ ;(str "rotate3D(0,1,0," (* (- 1 idx) 180) "deg)")
+ )
+ :z-index (if (> idx @current-page) "1" "0")}}
+ [:div (when (= idx (+ 1 @current-page)) {:style {:transform "rotateY(180deg)"}}) "back page"
+ idx
+ page]]]))))])))
+
+(defn book [{:keys [path-params] :as route}]
+ (let [document (r/cursor state [:document :hiccup])]
+ (fn [{:keys [path-params] :as route}]
+ [:<>
+ [rotate-test]
+ #_[book-pages
+
+ (mapv (fn [article] [:div.p1 (str article)
+
+ [title-text-image {:title article
+ :content (into [:div]
+ (vec
+ (rest
+ @doc)))}
+ (:details @document)]]) (search-articles {}))]])))
+
+(defn ^:dev/after-load reagent-render [hiccup]
+ (dom/render hiccup (js/document.getElementById "app")))
+
+
+(defn render-page []
+ (let [current-page (r/cursor state [:current-route])]
+ ;; load in the latest document
+ (fn []
+ (when (-> @current-page :data :init)
+ ((-> @current-page :data :init) nil)
+ ((-> @current-page :data :init) (-> @current-page :parameters :path :path)))
+ (when (-> @current-page :data :state)
+ ((-> @current-page :data :state) (-> @current-page :parameters :path :path)))
+ [layout [(-> @current-page :data :view) (-> @current-page)]]
+ #_(case (-> @current-page :data :name)
+ :homepage [layout [page-homepage @current-page]]
+ :archive [layout [archive @current-page]]
+ :posts [layout [post @current-page]]
+ :book [layout [book @current-page]]
+ :about [layout [about-page @current-page]]
+ [layout [:div "default"]]))))
+
+(defn ^:after-load init []
+ (rfe/start!
+ router
+ (fn [m]
+ (swap! state assoc :current-route m)
+ ;;(switch-to-latest (-> @state :current-route :parameters :path :path))
+ )
+ {:use-fragment false})
+
+ (GET "/documents/org-meta-index.edn"
+ {:handler (fn [response]
+ (->> (reader/read-string response)
+ ;; filter out missing dates
+ (filter (fn [doc] (some? (:date doc))))
+ (mapv #(assoc % :tags (into [] (:filetags %))))
+ (mapv #(assoc % :date (convert-date (:date %))))
+ (swap! state assoc :index))
+ (d/reset-conn! conn (d/empty-db schema))
+ (d/transact! conn (:index @state))
+ (select-initial-page (-> @state :current-route :parameters :path :path)))})
+ (reagent-render [render-page]))
+
+;;(defonce start (init))
+
+;;(comment )
+;; (-> @state :document)
+;; (latest-article)
+
+; (switch-to-latest)
+;; (org->to-hiccup tachyon-theme (-> @state :document :body))
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/about.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/about.cljs
new file mode 100644
index 0000000..dbac20c
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/about.cljs
@@ -0,0 +1,5 @@
+(ns com.oly.static-sites.do-blog.pages.about)
+
+(defn about-page [{:keys [path-params] :as route}]
+ (fn [{:keys [path-params] :as route}]
+ [:div "hi2"]))
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/archive.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/archive.cljs
new file mode 100644
index 0000000..89526fb
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/archive.cljs
@@ -0,0 +1,21 @@
+(ns com.oly.static-sites.do-blog.pages.archive
+ (:require [reagent.core :as r]
+ [reitit.frontend.easy :as rfe]
+ [tachyons.definition-lists :refer [simple]]
+ [com.oly.static-sites.do-blog.pages.helpers.utils :refer [format-date]]
+ [com.oly.static-sites.do-blog.pages.helpers.database :refer [search-articles state]]))
+
+(defn archive-page [{:keys [path-params] :as route}]
+ (let [search (r/cursor state [:search :terms])
+ org-index (r/reaction (search-articles (merge {:search @search} path-params)))]
+ (fn [{:keys [path-params] :as route}]
+ [:div {:key "search"}
+ [:h1 "Past articles"]
+ [simple
+ {:list
+ (map-indexed (fn [idx doc]
+ {:text [:div [:a.f4.lh-copy {:href (str (rfe/href :posts {:path ""}) (:relative-path doc))
+ :key idx}
+ (str (format-date (:date doc))
+ #_(convert-date (:date doc)) " " (:title doc))]]})
+ @org-index)}]])))
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/article.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/article.cljs
new file mode 100644
index 0000000..7862e21
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/article.cljs
@@ -0,0 +1,16 @@
+(ns com.oly.static-sites.do-blog.pages.article
+ (:require [reagent.core :as r]
+ [reitit.frontend.easy :as rfe]
+ [com.oly.static-sites.do-blog.pages.helpers.utils :refer [format-date]]
+ [com.oly.static-sites.do-blog.pages.helpers.database :refer [search-articles state]]
+ [com.oly.static-sites.do-blog.pages.components.core :refer [ui-tags title-text-image article-list-author-media-flipped]]))
+
+
+(defn article-page [{:keys [path-params] :as route}]
+ (let [document (r/cursor state [:document])]
+ (fn [{:keys [path-params] :as route}]
+ [:<>
+ [title-text-image
+ {:title (-> @document :details :title)
+ :content (-> @document :hiccup)}
+ (-> @document :details)]])))
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/components/core.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/components/core.cljs
new file mode 100644
index 0000000..df76b47
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/components/core.cljs
@@ -0,0 +1,41 @@
+(ns com.oly.static-sites.do-blog.pages.components.core
+ (:require [reitit.frontend.easy :as rfe]
+ [tachyons.buttons :refer [pill-grow]]
+ [com.oly.static-sites.do-blog.pages.helpers.utils :refer [extract-tags format-date]]
+ ))
+
+(defn ui-tags [meta]
+ [:div (map-indexed
+ (fn [idx tag]
+ [:span.mr2 {:key idx}
+ [pill-grow
+ {:href (rfe/href :archive {:tag tag})
+ :text tag}]])
+ (-> meta :filetags extract-tags))])
+
+(defn article-list-author-media-flipped [title articles]
+ [:section.mw7.center
+ (when title [:h2.athelas.ph3.ph0-l title])
+ (map-indexed (fn [idx {:keys [title relative-path description date author src alt thumbnail] :as article}]
+ [:article.pv4.bb.b--black-10.ph3.ph0-l
+ {:keys idx}
+ [:div.flex.flex-column.flex-row-ns
+ [:div.w-100.w-60-ns.pr3-ns.order-2.order-1-ns
+ [:a {:href (str (rfe/href :posts {:path ""}) relative-path)}
+ [:h1.f3.athelas.mt0.lh-title title]]
+ [:p.f5.f4-l.lh-copy.athelas description]]
+ (when thumbnail [:div.pl3-ns.order-1.order-2-ns.mb4.mb0-ns.w-100.w-40-ns
+ [:img.db {:src thumbnail
+ :alt alt}]])]
+ [:p.f6.lh-copy.gray.mv0 (when author (str "By " author))
+ (when date [:time.f6.db.gray (format-date date)])]])
+ articles)])
+
+(defn title-text-image [{:keys [title content] :as optional} tags]
+ [:article.lh-copy.f4.mt-0
+ [:h1.f2 title]
+ (when tags
+ [ui-tags tags])
+ (when (:img-src optional)
+ [:img.w-100.f5.measure {:src (:img-src optional) :alt (:img-alt optional)}])
+ content])
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/helpers/database.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/helpers/database.cljs
new file mode 100644
index 0000000..08f638c
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/helpers/database.cljs
@@ -0,0 +1,60 @@
+(ns com.oly.static-sites.do-blog.pages.helpers.database
+ (:require [clojure.string :as str]
+ [reagent.core :as r]
+ [datascript.core :as d]
+ [com.oly.static-sites.do-blog.pages.helpers.utils :refer [ltrim-slash]]))
+
+(defonce schema {:tags {:db/cardinality :db.cardinality/many}})
+(defonce conn (d/create-conn schema))
+(defonce document (r/atom {}))
+(defonce state
+ (r/atom {:index []
+ :search {:terms ""
+ :results []}
+ :document {:details nil :body nil}
+ :latest nil
+ :current-doc ""
+ :new-data 0
+ :current-key :org-01}))
+
+;(def not-empty? (complement empty?))
+
+(def db-search
+ '{:find [(pull ?e [*])]
+ :in [$]
+ :where
+ [[?e :title ?title]
+ [(get-else $ ?e :description :nil) ?description]
+ [?e :date ?date]
+ [(get-else $ ?e :thumbnail :nil) ?thumbnail]
+ [?e :relative-path ?path]]})
+
+(defn db-search-filter
+ "Add where clauses to the datalog query when supplied"
+ [{:keys [search tag]}]
+ (let [re-search (if (not (str/blank? search)) #_(js/RegEx (str "(?i)" search))
+ (re-pattern (str "(?i)" search)) nil)]
+ (prn re-search)
+ (cond-> db-search
+ (not (str/blank? tag))
+ (update-in [:where] #(conj % ['?e :tags tag]))
+ re-search
+ (update-in [:where] #(conj % [`(~'re-find ~re-search ~'?title)])))))
+
+(defn search-articles [search]
+ (prn (db-search-filter search))
+ (->>
+ (d/q (db-search-filter search) @conn)
+ (flatten)
+ (sort-by :date)
+ reverse
+ (map #(assoc %1 :relative-path (ltrim-slash (:relative-path %1))))))
+
+(defn latest-article
+ "Just return the first item from search articles."
+ []
+ (->> (search-articles {:search ""})
+ first
+ :relative-path))
+
+
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/helpers/utils.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/helpers/utils.cljs
new file mode 100644
index 0000000..36d68a4
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/helpers/utils.cljs
@@ -0,0 +1,19 @@
+(ns com.oly.static-sites.do-blog.pages.helpers.utils
+ (:require
+ [clojure.string :as str]
+ [tick.core :as t]
+ [tick.locale-en-us]
+ [tick.timezone]))
+
+(defonce date-format (t/formatter "yyyy-MMM-dd"))
+
+(defn format-date [text]
+ (when text
+ (t/format date-format text)))
+
+(defn ltrim-slash "Right trim a leading slash" [text] (str/replace text #"^/" ""))
+
+(defn extract-tags [text]
+ (->> (clojure.string/split text #_(:filetags %) #":")
+ (reduce (fn [m a] (conj m a)) [])
+ vec))
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/pages/home.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/home.cljs
new file mode 100644
index 0000000..5b285e5
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/pages/home.cljs
@@ -0,0 +1,21 @@
+(ns com.oly.static-sites.do-blog.pages.home
+ (:require [reagent.core :as r]
+ [reitit.frontend.easy :as rfe]
+ [com.oly.static-sites.do-blog.pages.helpers.utils :refer [format-date]]
+ [com.oly.static-sites.do-blog.pages.helpers.database :refer [search-articles state]]
+ [com.oly.static-sites.do-blog.pages.components.core :refer [ui-tags title-text-image article-list-author-media-flipped]]))
+
+(defn home-page [{:keys [path] :as route}]
+ (let [search (r/cursor state [:search :terms])
+ latest (r/cursor state [:document])]
+ (fn []
+ [:<>
+ [:div
+ (if (empty? @search)
+ [title-text-image
+ {:title (-> @latest :details :title)
+ :content (-> @latest :hiccup)}
+ (-> @latest :details)]
+ [article-list-author-media-flipped
+ "Articles"
+ (search-articles {:search @search})])]])))
diff --git a/bases/do-blog/src/com/oly/static_sites/do_blog/theme.cljs b/bases/do-blog/src/com/oly/static_sites/do_blog/theme.cljs
new file mode 100644
index 0000000..edebd28
--- /dev/null
+++ b/bases/do-blog/src/com/oly/static_sites/do_blog/theme.cljs
@@ -0,0 +1,61 @@
+(ns com.oly.static-sites.do-blog.theme)
+
+(defn link-handler [v d]
+ (if (-> v second :img)
+ (conj [:img] (-> (dissoc (clojure.set/rename-keys (second v) {:href :src}) :img)
+ (update :src #(clojure.string/replace % #"\.\./" "")) )
+ )
+ (conj [:a] (second v))))
+
+
+(def tachyon-theme
+ {:TITLE :header.f2.fw6.f2-ns.lh-title.mt0.mb2
+ ;:DESCRIPTION :p
+ :HEADER1 :h1.f3.fw6.f3-ns.lh-title.mt0.mb2
+ :HEADER2 :h2.f3.fw6.f3-ns.lh-title.mt0.mb2
+ :HEADER3 :h3
+ :HEADER4 :h4
+ :HEADER5 :h5
+ :TODO :span
+ :VERBATIM :code
+ :CODE :code
+
+ :MAIN :main
+
+ :THUMBNAIL nil
+ :DESCRIPTION :meta ;(fn [v] [:span {:name (str v)} ])
+ :CATEGORY :meta ;(fn [v] [:span {:name (str v)} ])
+ :SLUG :meta ;(fn [v] [:span {:name (str v)} ])
+ :DATE :meta ;(fn [v] [:span {:name (str v)} ])
+ :FILETAGS (fn [v] [:meta {:name "keywords" :content (str v)}])
+ :NAME :meta ;(fn [v] [:span {:name (str v)} ])
+ :HTML_DOCTYPE :meta
+
+ :TABLE :table.collapse.ba.br2.b--black-10.pv2.ph3
+ :TBODY :tbody
+ :THEAD :thead
+ :TR :tr.striped--light-gray
+ :TD :td.pv2.ph3
+
+ ;;TODO this is a src attrib probably worth handling this differently
+ ;;perhaps allow custom functions instead of a simple replace
+ :LANGUAGE :class
+ :SRC :pre.bg-near-black.silver.pa2.hljs.roboto.overflow-auto.klipse.f6
+ :RESULTS :pre.bg-near-black.silver.pa2.hljs.roboto.overflow-auto
+ :EXAMPLE :pre.bg-near-black.silver.pa2.hljs.roboto.overflow-auto
+ :COMMENT nil
+ :CAPTION :span
+ :I :i
+ :U :u
+ :B :b
+ :LINK link-handler
+ :IMG :img
+ ;; probably remove these 2
+ :A :a
+ :P :p
+ :BR :br
+ :LINE :p.f5.f4-ns.lh-copy.mt0
+ :BULLETS-ORDERED :ol
+ :BULLETS :ul
+ :BULLET :li
+ })
diff --git a/deps.edn b/deps.edn
index 4fcbc80..3648c7c 100644
--- a/deps.edn
+++ b/deps.edn
@@ -1,24 +1,50 @@
-{:paths ["development/src" "bases/portfolio/src"]
+{:paths ["development/src" "bases/portfolio/src" "bases/do-blog/src"]
:deps {cjohansen/dumdom {:mvn/version "2023.11.06"}
+ org.clojure/clojurescript {:mvn/version "1.11.60"}
+
no.cjohansen/portfolio {:mvn/version "2023.07.15"}}
- :aliases {:dev {:extra-paths ["development/src" "bases/portfolio/src" ]
+ :aliases {
+ :dev {:extra-paths ["development/src" "bases/portfolio/src" "bases/do-blog/src"]
:extra-deps {org.clojure/clojure {:mvn/version "1.10.3"}
+ org.clojure/clojurescript {:mvn/version "1.11.60"}
+
org.clojure/tools.deps.alpha {:mvn/version "0.12.1003"}
cljs-ajax/cljs-ajax {:mvn/version "0.8.1"}
;; dev libraries
thheller/shadow-cljs {:mvn/version "2.25.2"}
- refactor-nrepl/refactor-nrepl {:mvn/version "3.9.0"}
- cider/cider-nrepl {:mvn/version "0.43.1"}
+ ;;refactor-nrepl/refactor-nrepl {:mvn/version "3.9.0"}
+ ;;cider/cider-nrepl {:mvn/version "0.43.1"}
no.cjohansen/portfolio {:mvn/version "2023.07.15"}
djblue/portal {:mvn/version "0.48.0"}}}
+ :blog {:extra-paths ["development/src" "bases/do-blog/src"]
+ :extra-deps {
+ org.clojure/core.async {:mvn/version "1.6.673"}
+ org.clojure/clojurescript {:mvn/version "1.11.60"}
+
+ reagent/reagent {:mvn/version "1.1.1"}
+ tick/tick {:mvn/version "0.5.0"}
+ metosin/reitit {:mvn/version "0.5.18"}
+
+ cljs-ajax/cljs-ajax {:mvn/version "0.8.4"}
+
+ datascript/datascript {:mvn/version "1.4.0"}
+ olymk2/tachyon-reagent {:git/url "https://gitlab.com/olymk2/tachyon-reagent.git"
+ :sha "e422af7b41266f7bc90ab78a24fb93f32be61385"}
+ olymk2/cl-eorg {:git/url "https://gitlab.com/olymk2/cl-org.git"
+ :sha "528e8125afcac5d7664aac80f7fbba12dd0f5d98"}
+ }
+ }
+
+
:shadow-cljs-run
{:extra-deps {thheller/shadow-cljs {:mvn/version "2.25.2"}
- refactor-nrepl/refactor-nrepl {:mvn/version "3.9.0"}
+ cider/cider-nrepl {:mvn/version "0.50.2"}
+ refactor-nrepl/refactor-nrepl {:mvn/version "3.10.0"}
cider/piggieback {:mvn/version "0.5.3"}}
- :extra-paths ["dev"]
+ :extra-paths ["dev" "bases/do-blog/src"]
:main-opts ["-m" "shadow.cljs.devtools.cli"]}
:test {:extra-paths []}
diff --git a/readme.org b/readme.org
index 5c887e7..ac1908f 100644
--- a/readme.org
+++ b/readme.org
@@ -4,3 +4,6 @@ npx shadow-cljs server
npx tailwindcss -i ./development/resources/public/css/tailwind-styles.css -o ./development/resources/public/css/styles.css --watch
+
+
+clj -M:blog::shadow-cljs-run watch blog
diff --git a/shadow-cljs.edn b/shadow-cljs.edn
index f375761..458a14e 100644
--- a/shadow-cljs.edn
+++ b/shadow-cljs.edn
@@ -1,14 +1,15 @@
-{:deps {:aliases [:dev]}
- :dev-http {8080 ["development/resources/public/" "classpath:public"]}
+{:deps {:aliases [:blog]}
+ :dev-http {8080 ["bases/do-blog/resources/public" "classpath:public"]
+ 8081 ["development/resources/public/" "classpath:public"]}
;:nrepl {:middleware [refactor-nrepl.middleware/wrap-refactor]}
:nrepl {:middleware [refactor-nrepl.middleware/wrap-refactor]}
- :source ["devlopment/src" "bases/portfolio/src"] ;;"src"
+;; :source ["devlopment/src" "bases/portfolio/src"] ;;"src"
;; "../../components/web-ui/src"
;; "../../components/web-api/src"
;; "../../components/polyculture/src"
;; "../../components/svg-generation/src"
;; "../../components/local-store/src"]
- :builds {:app {:output-dir "development/resources/public/cljs-out"
+ :builds {:app {:output-dir "bases/portfolio/resources/public/js"
;:asset-path "."
:target :browser
:compiler-options {:infer-externs :auto :output-feature-set :es6}
@@ -18,6 +19,15 @@
:portfolio {:init-fn design/launch
:depends-on #{:base}}
}
+ :devtools {:after-load app.main/reload!}}
+ :blog {:output-dir "bases/do-blog/resources/public/js"
+ ;:asset-path "."
+ :target :browser
+ :compiler-options {:infer-externs :auto :output-feature-set :es6}
+ :modules {:base {:entries []}
+ :app {:init-fn com.oly.static-sites.do-blog.core/init
+ :depends-on #{:base}}
+ }
:devtools {:after-load app.main/reload!}
}
}}