Copy link to clipboard.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Oly 2023-08-10 14:35:50 +01:00
parent 47402cb1e2
commit d72019d6bb
6 changed files with 158 additions and 76 deletions

View File

@ -0,0 +1,8 @@
#+TITLE: About
#+DESCRIPTION: Examples mostly oriented around web development
* Introduction
This site has various example's guides and snippets showing how to use Clojure and ClojureScript, they are mainly based on my journey learning coming from JavaScript and python having no previous experience with java or the JVM.
Some of the struggles have been around Terminology & inter-op with the host languages along side re orientating my brain to think more functionally.

View File

@ -21,6 +21,13 @@
<meta property="og:site_name" content="SITE NAME" /> <meta property="og:site_name" content="SITE NAME" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<link <link
rel="stylesheet" rel="stylesheet"
type="text/css" type="text/css"

View File

@ -0,0 +1,25 @@
(ns clojure-demo.components
(:require
[clojure-demo.state :refer [site-state]]
[clojure-demo.helpers :refer [copy->clipboard slugify]]))
(defn notification []
(if (-> @site-state :notification)
[:div.fixed.p-5.top-20.right-0.border-2.border-sky-400.bg-white.opacity-100.transition-opacity.delay-150.duration-200
(-> @site-state :notification)]
[:<>]))
(defn header-on-click-copy-link [v]
{:on-click (fn [] (copy->clipboard (slugify v)))})
(defn header-lvl1 [v _]
[:h1.text-2xl.fw6.lh-title.mt-0.mb-2 {:id (slugify v)}
[:a {:name (slugify v)} [:i.fa-solid.fa-link (header-on-click-copy-link v)] v]])
(defn header-lvl2 [v _]
[:h2.text-xl.fw6.lh-title.mt-0.mb-2 {:id (slugify v)}
[:a {:name (slugify v)} [:i.fa-solid.fa-link (header-on-click-copy-link v)] v]])
(defn header-lvl3 [v _]
[:h3.text-base.fw6.lh-title.mt-0.mb-2 {:id (slugify v)}
[:a {:name (slugify v)} [:i.fa-solid.fa-link (header-on-click-copy-link v)] v]])

View File

@ -8,16 +8,17 @@
["@nextjournal/lang-clojure" :refer [clojure]] ["@nextjournal/lang-clojure" :refer [clojure]]
["react-dom/client" :refer [createRoot]] ["react-dom/client" :refer [createRoot]]
["tarts" :as tarts] ["tarts" :as tarts]
[tick.core :as t]
[cljs.core.async :as async]
[cljs.core.async.interop :as async-in]
[shadow.cljs.modern :refer [js-await]]
[ajax.core :refer [GET raw-response-format]] [ajax.core :refer [GET raw-response-format]]
[cl-eorg.html :as h :refer [body headers org->replacements]] [cl-eorg.html :as h :refer [body headers org->replacements]]
[cl-eorg.parser :as o :refer [parse]] [cl-eorg.parser :as o :refer [parse]]
[cl-eorg.themes.tachyon :refer [tachyon-theme]] [cl-eorg.themes.tachyon :refer [tachyon-theme]]
[clojure.string :as str] [clojure-demo.components
:refer [header-lvl1 header-lvl2 header-lvl3 notification]]
[clojure-demo.helpers :refer [slugify]]
[clojure-demo.state :refer [site-state]]
[clojure-demo.tailwind-theme :refer [tailwind-theme]]
[clojure.data.xml :as xml] [clojure.data.xml :as xml]
[clojure.string :as str]
[honey.sql :as sql] [honey.sql :as sql]
[honey.sql.helpers :as sqlh] [honey.sql.helpers :as sqlh]
[reagent.core :as reagent] [reagent.core :as reagent]
@ -25,12 +26,12 @@
[reitit.frontend :as rf] [reitit.frontend :as rf]
[reitit.frontend.easy :as rfe] [reitit.frontend.easy :as rfe]
[reitit.frontend.history :refer [ignore-anchor-click?]] [reitit.frontend.history :refer [ignore-anchor-click?]]
[sci.configs.funcool.promesa :as sci-promesa]
[sci.configs.reagent.reagent :as sci-reagent] [sci.configs.reagent.reagent :as sci-reagent]
[sci.configs.tonsky.datascript :as sci-datascript] [sci.configs.tonsky.datascript :as sci-datascript]
[sci.configs.funcool.promesa :as sci-promesa]
[sci.core :as sci] [sci.core :as sci]
[clojure-demo.tailwind-theme :refer [tailwind-theme]] [spec-tools.data-spec :as ds]
[spec-tools.data-spec :as ds])) [tick.core :as t]))
(def languages (def languages
{"clojure" {:mode "clojure"} {"clojure" {:mode "clojure"}
@ -41,7 +42,8 @@
(def yaml-mode (LanguageSupport. (.define StreamLanguage yaml))) (def yaml-mode (LanguageSupport. (.define StreamLanguage yaml)))
(defn ^:sci/macro my-js-await [_ _ [name thenable] & body] (defn ^:sci/macro my-js-await
[_ _ [name thenable] & body]
(let [last-expr (last body) (let [last-expr (last body)
[body catch] [body catch]
(if (and (seq? last-expr) (= 'catch (first last-expr))) (if (and (seq? last-expr) (= 'catch (first last-expr)))
@ -54,8 +56,7 @@
[`(.then (fn [~name] ~@body))]) [`(.then (fn [~name] ~@body))])
~@(when catch ~@(when catch
(let [[name & body] catch] (let [[name & body] catch]
[`(.catch (fn [~name] ~@body))] [`(.catch (fn [~name] ~@body))])))))
)))))
;; https://github.com/babashka/sci.configs ;; https://github.com/babashka/sci.configs
(def rf-ns (sci/create-ns 'reitit.frontend nil)) (def rf-ns (sci/create-ns 'reitit.frontend nil))
@ -112,14 +113,6 @@
;(def sci-ctx (sci/empty-environment)) ;(def sci-ctx (sci/empty-environment))
(sci/alter-var-root sci/print-fn (constantly *print-fn*)) (sci/alter-var-root sci/print-fn (constantly *print-fn*))
(defn slugify [s]
(when s
(str
(-> s
(str/lower-case)
(str/replace #"[^\w]+" "-")
(str/replace #"^-\\|-\\-$" "")))))
(defn fetch-selected-text (defn fetch-selected-text
"Get the users selected text" "Get the users selected text"
[updated-view transactions] [updated-view transactions]
@ -189,7 +182,7 @@
:parent @editor}))))) :parent @editor})))))
:component-will-unmount (fn [_] (.destroy @view)) :component-will-unmount (fn [_] (.destroy @view))
:reagent-render (fn [] :reagent-render (fn []
(if (= exports "none") (if (= exports "none")
nil nil
[:div.mb-8 [:div.mb-8
[:div.ba.ma-0.f5.b--black-05.pa2.overflow-auto.editor {:ref #(reset! editor %)}] [:div.ba.ma-0.f5.b--black-05.pa2.overflow-auto.editor {:ref #(reset! editor %)}]
@ -208,9 +201,9 @@
(def theme-tachyon (def theme-tachyon
(merge tachyon-theme (merge tachyon-theme
{:SRC code-editor {:SRC code-editor
:HEADER1 (fn [v _] [:h1 {:id (slugify v)} [:a {:name (slugify v)} v]]) :HEADER1 header-lvl1 #_(fn [v _] [:h1 {:id (slugify v)} [:a {:name (slugify v)} v]])
:HEADER2 (fn [v _] [:h2 {:id (slugify v)} [:a {:name (slugify v)} v]]) :HEADER2 header-lvl2 #_(fn [v _] [:h2 {:id (slugify v)} [:a {:name (slugify v)} v]])
:HEADER3 (fn [v _] [:h2 {:id (slugify v)} [:a {:name (slugify v)} v]]) :HEADER3 header-lvl3 #_(fn [v _] [:h2 {:id (slugify v)} [:a {:name (slugify v)} v]])
:LINE :p.f5.f5-ns.lh-copy.mt0 :LINE :p.f5.f5-ns.lh-copy.mt0
:BULLETS :ul.mt0 :BULLETS :ul.mt0
:LINK :a #_link-handler})) :LINK :a #_link-handler}))
@ -218,42 +211,42 @@
(def theme (def theme
(merge tailwind-theme (merge tailwind-theme
{:SRC code-editor {:SRC code-editor
:HEADER1 (fn [v _] [:h1.text-2xl.fw6.lh-title.mt-0.mb-2 {:id (slugify v)} [:a {:name (slugify v)} v]]) :HEADER1 header-lvl1 #_(fn [v _] [:h1.text-2xl.fw6.lh-title.mt-0.mb-2 {:id (slugify v)} [:a {:name (slugify v)} v]])
:HEADER2 (fn [v _] [:h2.text-xl.fw6.lh-title.mt-0.mb-2 {:id (slugify v)} [:a {:name (slugify v)} v]]) :HEADER2 header-lvl2 #_(fn [v _] [:h2.text-xl.fw6.lh-title.mt-0.mb-2 {:id (slugify v)} [:a {:name (slugify v)} v]])
:HEADER3 (fn [v _] [:h2.text-base.lh-title.mt-0.mb-2 {:id (slugify v)} [:a {:name (slugify v)} v]]) :HEADER3 header-lvl3 #_(fn [v _] [:h2.text-base.lh-title.mt-0.mb-2 {:id (slugify v)} [:a {:name (slugify v)} v]])
:LINE :p.f5.f5-ns.lh-copy.mt0 :LINE :p.f5.f5-ns.lh-copy.mt0
:BULLETS :ul.mt0 :BULLETS :ul.mt0
:LINK :a #_link-handler})) :LINK :a #_link-handler}))
#_(def theme-toc-tachyon #_(def theme-toc-tachyon
(merge tachyon-theme (merge tachyon-theme
{:HEADER1 (fn [v _] [:li [:a {:href (str "#" (slugify v))} {:HEADER1 (fn [v _] [:li [:a {:href (str "#" (slugify v))}
[:span.f4.fw6.f3-ns.lh-title.mt0.mb2 v]]]) [:span.f4.fw6.f3-ns.lh-title.mt0.mb2 v]]])
:HEADER2 (fn [v _] [:li.ml2 [:a {:href (str "#" (slugify v))} :HEADER2 (fn [v _] [:li.ml2 [:a {:href (str "#" (slugify v))}
[:span.f4.fw6.f4-ns.lh-title.mt0.mb2 v]]]) [:span.f4.fw6.f4-ns.lh-title.mt0.mb2 v]]])
:HEADER3 (fn [v _] [:li.ml4 [:a {:href (str "#" (slugify v))} :HEADER3 (fn [v _] [:li.ml4 [:a {:href (str "#" (slugify v))}
[:span.f5.fw6.f5-ns.lh-title.mt0.mb2 v]]]) [:span.f5.fw6.f5-ns.lh-title.mt0.mb2 v]]])
:HEADER4 (fn [v _] [:li.ml6 [:a {:href (str "#" (slugify v))} :HEADER4 (fn [v _] [:li.ml6 [:a {:href (str "#" (slugify v))}
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]]) [:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])
:HEADER5 (fn [v _] [:li.ml8 [:a {:href (str "#" (slugify v))} :HEADER5 (fn [v _] [:li.ml8 [:a {:href (str "#" (slugify v))}
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]]) [:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])
:HEADER6 (fn [v _] [:li.ml10 [:a {:href (str "#" (slugify v))} :HEADER6 (fn [v _] [:li.ml10 [:a {:href (str "#" (slugify v))}
[:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])})) [:span.f6.fw6.f5-ns.lh-title.mt0.mb2 v]]])}))
(def theme-toc (def theme-toc
(merge tailwind-theme (merge tailwind-theme
{:HEADER1 (fn [v _] [:li.list-decimal [:a.text-blue-800 {:class "hover:text-blue-500" :href (str "#" (slugify v))} {:HEADER1 (fn [v _] [:li.list-decimal [:a.text-blue-800 {:class "hover:text-blue-500" :href (str "#" (slugify v))}
[:span.text-xl.fw6.lh-title.mt0.mb2 v]]]) [:span.text-xl.fw6.lh-title.mt0.mb2 v]]])
:HEADER2 (fn [v _] [:li.list-decimal.ml-4 [:a.text-blue-800 {:href (str "#" (slugify v))} :HEADER2 (fn [v _] [:li.list-decimal.ml-4 [:a.text-blue-800 {:href (str "#" (slugify v))}
[:span.text-lg.fw6.lh-title.mt0.mb2 v]]]) [:span.text-lg.fw6.lh-title.mt0.mb2 v]]])
:HEADER3 (fn [v _] [:li.list-decimal.ml-8 [:a.text-blue-800 {:class "hover:text-blue-500" :href (str "#" (slugify v))} :HEADER3 (fn [v _] [:li.list-decimal.ml-8 [:a.text-blue-800 {:class "hover:text-blue-500" :href (str "#" (slugify v))}
[:span.text-base.fw6.lh-title.mt0.mb2 v]]]) [:span.text-base.fw6.lh-title.mt0.mb2 v]]])
:HEADER4 (fn [v _] [:li.list-decimal.ml-12 [:a.text-blue-800 {:href (str "#" (slugify v))} :HEADER4 (fn [v _] [:li.list-decimal.ml-12 [:a.text-blue-800 {:href (str "#" (slugify v))}
[:span.text-sm.fw6.lh-title.mt0.mb2 v]]]) [:span.text-sm.fw6.lh-title.mt0.mb2 v]]])
:HEADER5 (fn [v _] [:li.list-decimal.ml-26 [:a.text-blue-800 {:href (str "#" (slugify v))} :HEADER5 (fn [v _] [:li.list-decimal.ml-26 [:a.text-blue-800 {:href (str "#" (slugify v))}
[:span.text-xs.fw6.f5-ns.lh-title.mt0.mb2 v]]]) [:span.text-xs.fw6.f5-ns.lh-title.mt0.mb2 v]]])
:HEADER6 (fn [v _] [:li.list-decimal.ml-30 [:a.hover:decoration-blue-400 {:href (str "#" (slugify v))} :HEADER6 (fn [v _] [:li.list-decimal.ml-30 [:a.hover:decoration-blue-400 {:href (str "#" (slugify v))}
[:span.text-xs.fw6.f5-ns.lh-title.mt0.mb2 v]]])})) [:span.text-xs.fw6.f5-ns.lh-title.mt0.mb2 v]]])}))
;; put constant data here ;; put constant data here
(def site-data (def site-data
@ -318,8 +311,7 @@
:icon-image "https://avatars.githubusercontent.com/u/2181346?s=200&v=4"}]} :icon-image "https://avatars.githubusercontent.com/u/2181346?s=200&v=4"}]}
:terminology {:title "Terminology" :terminology {:title "Terminology"
:intro "" :intro ""
:key ::terminology} :key ::terminology}}
}
:demos :demos
{:hiccup-dsl-demo {:hiccup-dsl-demo
{:file "documents/hiccup-dsl-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} {:file "documents/hiccup-dsl-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"}
@ -340,9 +332,6 @@
:containers :containers
{:file "documents/containers.org" :git-link "https://github.com/atomjuice/containers"}}}) {:file "documents/containers.org" :git-link "https://github.com/atomjuice/containers"}}})
;; Store site state
(defonce site-state (reagent/atom {}))
;; form one component to render an article ;; form one component to render an article
(defn article [{:keys [title description tagline]}] (defn article [{:keys [title description tagline]}]
[:article.prose {:data-name "article-full-bleed-background"} [:article.prose {:data-name "article-full-bleed-background"}
@ -420,7 +409,6 @@
:code (filter (fn filter-code [tag] (org-code (first tag))) dsl) :code (filter (fn filter-code [tag] (org-code (first tag))) dsl)
:body (filter (fn filter-body [tag] (body (first tag))) dsl)}) :body (filter (fn filter-body [tag] (body (first tag))) dsl)})
(defn home-page [] (defn home-page []
[:<> [:<>
[articles [articles
@ -438,19 +426,39 @@
(defn grouped-page [route] (defn grouped-page [route]
(let [group (keyword (name (:name (:data route))))] (let [group (keyword (name (:name (:data route))))]
[:<> (swap! site-state dissoc :notification)
[articles (fn [route]
{:title (-> site-data :pages group :title) [:<>
:body (-> site-data :pages group :intro) [articles
:articles {:title (-> site-data :pages group :title)
(mapv (fn fmt-map [demo] :body (-> site-data :pages group :intro)
{:title (:title demo) :articles
:description (:description demo) (mapv (fn fmt-map [demo]
:link (rfe/href ::page {:page (:page demo)}) {:title (:title demo)
:img-src (:icon-image demo)}) :description (:description demo)
(-> site-data :pages group :demos))}]])) :link (rfe/href ::page {:page (:page demo)})
:img-src (:icon-image demo)})
(-> site-data :pages group :demos))}]])))
(defn default-page [route] (defn default-page [route]
(let [demo-key (keyword (-> route :parameters :path :page))
content (reagent/atom {})]
(GET (str "/" (-> site-data :demos demo-key :file))
{:response-format (raw-response-format)
:handler (fn [response]
(->> response
parse
org->split2
(reset! content)))})
(fn [route]
(if @content
[:main
[:h1.mt-8.mb-8.text-4xl (:content (last (first (:header @content))))]
[:div
(into [:div] (org->replacements theme (:body @content)))]]
[:<>]))))
(defn default-page-header [route]
(let [demo-key (keyword (-> route :parameters :path :page)) (let [demo-key (keyword (-> route :parameters :path :page))
content (reagent/atom {})] content (reagent/atom {})]
(GET (str "/" (-> site-data :demos demo-key :file)) (GET (str "/" (-> site-data :demos demo-key :file))
@ -483,11 +491,10 @@
(into [:div] (org->replacements theme (:body @content)))]] (into [:div] (org->replacements theme (:body @content)))]]
[:<>])))) [:<>]))))
;; form one render about page component ;; form one render about page component
(defn about-page [] (defn about-page []
[:div [default-page {:parameters {:path {:page "about"}}}]
#_[:div
[:section.mw7.center.avenir [:section.mw7.center.avenir
[:h1 "Clojure library examples to aid learning"] [:h1 "Clojure library examples to aid learning"]
[:p ""] [:p ""]
@ -504,9 +511,9 @@
["/page/:page" ["/page/:page"
{:name ::page {:name ::page
:view default-page :view default-page-header
:parameters {:path {:page string?} :parameters {:path {:page string?}
:query {(ds/opt :foo) keyword?}}}] :query {(ds/opt :foo) keyword?}}}]
["/terminology/" ["/terminology/"
{:name ::terminology {:name ::terminology
@ -530,21 +537,15 @@
["/about/" ["/about/"
{:name ::about {:name ::about
:view about-page}] :view about-page}]])
#_["/demo/:page"
{:name ::demo
:view demo-page
:parameters {:path {:page string?}
:query {(ds/opt :foo) keyword?}}}]])
;; top level component contains nav and adds in the select page into a containing element ;; top level component contains nav and adds in the select page into a containing element
;; we are adding in a style sheet but this will often be done in index.html ;; we are adding in a style sheet but this will often be done in index.html
(defn current-page [] (defn current-page []
[:div [:div
[notification]
[navbar (concat [navbar (concat
[{:href (rfe/href ::frontpage) :title "title here" :text "home" :key "homepage"}] [{:href (rfe/href ::frontpage) :title "title here" :text "home" :key "homepage"}]
(mapv (fn build-nav [[key page]] {:href (rfe/href (:key page)) :text (:title page)}) (-> site-data :pages)) (mapv (fn build-nav [[key page]] {:href (rfe/href (:key page)) :text (:title page)}) (-> site-data :pages))
[;;{:href (rfe/href ::dsl) :text "DSL's" :key "dsl"} [;;{:href (rfe/href ::dsl) :text "DSL's" :key "dsl"}
{:title "Domain Specific Languages" :href (rfe/href ::about) :text "About" :key "about"} {:title "Domain Specific Languages" :href (rfe/href ::about) :text "About" :key "about"}

View File

@ -0,0 +1,36 @@
(ns clojure-demo.helpers
(:require
[cljs.core.async :refer [go]]
[cljs.core.async.interop :refer [<p!]]
[clojure.string :as str]
[clojure-demo.state :refer [site-state]]))
(defn slugify [s]
(when s
(str
(-> s
(str/lower-case)
(str/replace #"[^\w]+" "-")
(str/replace #"^-\\|-\\-$" "")))))
(defn build-page-path [title]
(str "http://127.0.0.1:8080/" #_"https://clojure-demos.digitaloctave.com/" "page/"
(when (-> @site-state :current-route :parameters :path :page)
(-> @site-state :current-route :parameters :path :page))
"#" title)
)
(defn copy->clipboard
"Simple wrapper which copies text to the clipboard and resolves the promise"
[text]
(go (<p! (.writeText (.-clipboard js/navigator) (build-page-path text)))
(swap! site-state assoc :notification "Copied to clipboard")
(prn "copied")))
(comment
(.-writeText (.-clipboard js/navigator) "test")
(copy->clipboard "test2"))

View File

@ -0,0 +1,5 @@
(ns clojure-demo.state
(:require [reagent.core :as reagent]))
;; Store site state
(defonce site-state (reagent/atom {}))