Add blog project to static files
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Oliver 2024-10-25 20:03:22 +01:00
parent c584866355
commit 18d23e0c06
19 changed files with 804 additions and 37 deletions

View File

@ -15,7 +15,7 @@ steps:
path: /drone/cache/ path: /drone/cache/
commands: commands:
- ls -la /drone/cache/.m2 - 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 - name: build-clojure
pull: always pull: always
@ -25,13 +25,40 @@ steps:
path: /drone/cache/ path: /drone/cache/
commands: commands:
- ls -la /drone/cache/.m2 - 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 pull: True
image: appleboy/drone-scp image: appleboy/drone-scp
depends_on: depends_on:
- build-clojure - build-static-blog
settings: settings:
host: blog.digitaloctave.com host: blog.digitaloctave.com
port: 22 port: 22
@ -39,30 +66,28 @@ steps:
from_secret: ssh_user from_secret: ssh_user
key: key:
from_secret: ssh_key from_secret: ssh_key
target: /var/www/portfolio/${DRONE_COMMIT_SHA:0:10}/ target: /var/www/new-blog/
source: /drone/src/development/resources/public/* source: /drone/src/resources/public/*
strip_components: 5 strip_components: 4
- name: promote-deployed-site # - name: promote-deployed-site
pull: True # pull: True
image: appleboy/drone-ssh # image: appleboy/drone-ssh
depends_on: # depends_on:
- deploy-site # - deploy-site
settings: # settings:
host: blog.digitaloctave.com # host: blog.digitaloctave.com
port: 22 # port: 22
username: # username:
from_secret: SSH_USER # from_secret: SSH_USER
key: # key:
from_secret: SSH_KEY # from_secret: SSH_KEY
port: 22 # port: 22
command_timeout: 5m # command_timeout: 5m
script: # script:
- cd /var/www/portfolio/ # - cd /var/www/portfolio/
- rm /var/www/portfolio/promoted # - rm /var/www/portfolio/promoted
- ln -s /var/www/portfolio/${DRONE_COMMIT_SHA:0:10} /var/www/portfolio/promoted # - ln -s /var/www/portfolio/${DRONE_COMMIT_SHA:0:10} /var/www/portfolio/promoted
depends_on:
- deploy-site
volumes: volumes:
- name: cache - name: cache

4
.gitignore vendored
View File

@ -34,3 +34,7 @@ projects/**/pom.xml
# Calva VS Code Extension # Calva VS Code Extension
.calva/output-window/output.calva-repl .calva/output-window/output.calva-repl
/.shadow-cljs/
/.lsp/
/node_modules/
/.clj-kondo/*

25
bases/do-blog/deps.edn Normal file
View File

@ -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 {}}}}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html class="tachyon ma0 pa0 h-100">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" />
<link rel="stylesheet" href="https://unpkg.com/tachyons@4.12.0/css/tachyons.min.css" />
<style type="text/css" media="screen">
#loading {
-webkit-animation: rotation 2s infinite linear;
}
@-webkit-keyframes rotation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(359deg);
}
}
</style>
</head>
<body class="ma0 pa0 h-100">
<div id="app" class="ma0 pa0 h-100">
<section id="startup" class="h-100">
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div class="h-100 w-100 flex justify-around items-center v-mid">
<div class="v-mid tc">
<p class="f2 button is-warning is-loading">Initiating Blog</p>
<i id="loading" class="f-6 fas fa-circle-notch"></i>
<p>Application is loading, if nothing happens ensure javascript is enabled.</p>
</div>
</div>
</section>
</div>
<script src="/cljs-out/main.js" type="text/javascript"></script>
</body>
</html>

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html class="tachyon ma0 pa0 h-100">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" />
<link rel="stylesheet" href="https://unpkg.com/tachyons@4.12.0/css/tachyons.min.css" />
<style type="text/css" media="screen">
#loading {
-webkit-animation: rotation 2s infinite linear;
}
@-webkit-keyframes rotation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(359deg);
}
}
</style>
</head>
<body class="ma0 pa0 h-100">
<div id="app" class="ma0 pa0 h-100">
<section id="startup" class="h-100">
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div class="h-100 w-100 flex justify-around items-center v-mid">
<div class="v-mid tc">
<p class="f2 button is-warning is-loading">Initiating Blog</p>
<i id="loading" class="f-6 fas fa-circle-notch"></i>
<p>Application is loading, if nothing happens ensure javascript is enabled.</p>
</div>
</div>
</section>
</div>
<script src="/js/base.js" type="text/javascript"></script>
<script src="/js/app.js" type="text/javascript"></script>
</body>
</html>

View File

@ -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 (<! @comm))
(swap! state assoc :search {:terms nil :results []})
(org-dsl-render @document)))
(prn (str "render from path nothing found ") path)))
(def router
(rf/router
[["/"
{:name :homepage
:init 'switch-to-latest
:view #'home-page}]
["/archive/{*tag}"
{:name :archive
:view #'archive-page}]
["/tags/{*path}"
{:name :tags
:view 'post
:parameters {:path string?}}]
["/about"
{:name :about
:view #'about-page}]
["/book/{*path}"
{:name :book
:view 'book
:parameters {:path string?}}]
["/posts/{*path}"
{:name :posts
:view #'article-page
:state render-doc-from-path
:parameters {:path string?}}]]))
(defn switch-to-latest
[path-params]
(-> (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))

View File

@ -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"]))

View File

@ -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)}]])))

View File

@ -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)]])))

View File

@ -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])

View File

@ -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))

View File

@ -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))

View File

@ -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})])]])))

View File

@ -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
})

View File

@ -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"} :deps {cjohansen/dumdom {:mvn/version "2023.11.06"}
org.clojure/clojurescript {:mvn/version "1.11.60"}
no.cjohansen/portfolio {:mvn/version "2023.07.15"}} 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"} :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"} org.clojure/tools.deps.alpha {:mvn/version "0.12.1003"}
cljs-ajax/cljs-ajax {:mvn/version "0.8.1"} cljs-ajax/cljs-ajax {:mvn/version "0.8.1"}
;; dev libraries ;; dev libraries
thheller/shadow-cljs {:mvn/version "2.25.2"} thheller/shadow-cljs {:mvn/version "2.25.2"}
refactor-nrepl/refactor-nrepl {:mvn/version "3.9.0"} ;;refactor-nrepl/refactor-nrepl {:mvn/version "3.9.0"}
cider/cider-nrepl {:mvn/version "0.43.1"} ;;cider/cider-nrepl {:mvn/version "0.43.1"}
no.cjohansen/portfolio {:mvn/version "2023.07.15"} no.cjohansen/portfolio {:mvn/version "2023.07.15"}
djblue/portal {:mvn/version "0.48.0"}}} 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 :shadow-cljs-run
{:extra-deps {thheller/shadow-cljs {:mvn/version "2.25.2"} {: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"}} cider/piggieback {:mvn/version "0.5.3"}}
:extra-paths ["dev"] :extra-paths ["dev" "bases/do-blog/src"]
:main-opts ["-m" "shadow.cljs.devtools.cli"]} :main-opts ["-m" "shadow.cljs.devtools.cli"]}
:test {:extra-paths []} :test {:extra-paths []}

View File

@ -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 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

View File

@ -1,14 +1,15 @@
{:deps {:aliases [:dev]} {:deps {:aliases [:blog]}
:dev-http {8080 ["development/resources/public/" "classpath:public"]} :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]}
: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-ui/src"
;; "../../components/web-api/src" ;; "../../components/web-api/src"
;; "../../components/polyculture/src" ;; "../../components/polyculture/src"
;; "../../components/svg-generation/src" ;; "../../components/svg-generation/src"
;; "../../components/local-store/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 "." ;:asset-path "."
:target :browser :target :browser
:compiler-options {:infer-externs :auto :output-feature-set :es6} :compiler-options {:infer-externs :auto :output-feature-set :es6}
@ -18,6 +19,15 @@
:portfolio {:init-fn design/launch :portfolio {:init-fn design/launch
:depends-on #{:base}} :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!} :devtools {:after-load app.main/reload!}
} }
}} }}