Improvements to the hiccup info.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Oly 2023-06-29 08:29:57 +01:00
parent b0e57579c3
commit e006f31ae5
5 changed files with 259 additions and 99 deletions

View File

@ -1 +1,3 @@
clj -m figwheel.main --build dev --repl clj -m figwheel.main --build dev --repl
https://www.clojuriststogether.org/news/call-for-new-proposals.-june-survey-results./

View File

@ -1,71 +1,126 @@
#+TITLE: Intro to Hiccup #+TITLE: Intro to Hiccup
* Hiccup * Introduction
https://github.com/weavejester/hiccup
hiccup is a html DSL, used extensively in the clojure's eco-system, there are others as well but hiccup is the most widely used. hiccup is a html DSL, used extensively in the clojure's eco-system, there are others as well but hiccup is the most widely used.
In hiccup everything is a list, this means you can easily compose html using standard language constructs. In hiccup everything is a list, this means you can easily compose html using standard language constructs.
To render the hiccup to html elements we call the (html) function from the hiccup library for server side with reagent or client side code this will likely be a different function like (render). To render the hiccup to html elements we call the (html) function from the hiccup library for server side with reagent or client side code this will likely be a different function like (render).
There are a few variant's the main ones being https://github.com/weavejester/hiccup and https://github.com/lambdaisland/hiccup , the lambdaisland one is particular helpful if you want to share html between the frontend and backend as its closer to reagents builtin hiccup.
** Simple examples ** Simple examples
If using reagent you don't need to pass into h/html but this is server side reagent also has some helpers to work with react nicer. If using reagent you don't need to pass into h/html but this is server side reagent also has some helpers to work with react nicer.
#+BEGIN_SRC clojure #+BEGIN_SRC clojure :tangle ./src/core.cljs
[:span "bar"] [:span "bar"]
#+END_SRC #+END_SRC
*** Styles classes and ID's
Attributes are added as a map of values styles are also a map Attributes are added as a map of values styles are also a map
#+BEGIN_SRC clojure #+BEGIN_SRC clojure :tangle src/core.cljs
[:span {:class "class1 class2" :title "my title" :style {:color "red"}} "bar"] [:span {:class "class1 class2" :title "my title" :style {:color "red"}} "bar"]
#+END_SRC #+END_SRC
You can use shorthand to add id's and classes You can use shorthand to add id's and classes
#+BEGIN_SRC clojure #+BEGIN_SRC clojure :results output :tangle src/core.cljs
[:span#id.class1.class2 "bar"] [:span#id.class1.class2 "bar"]
#+END_SRC #+END_SRC
** Compossible components ** Example of manipulating hiccup with clojure functions
The main advantage comes from the ability to compose the parts together, so we can break this into function's
In this example its only a hash map, the data is separated out from the html, in reagent you can use atom for live updating. You can use clojure core language to manipulate these vectors.
#+BEGIN_SRC clojure
(defn navbar-link [{:keys [href title text] :or {text nil title nil}}]
[:a.link.dim.white.dib.mr3 {:href href :title title} text])
(defn navbar [links]
[:header.bg-black-90.fixed.w-100.ph3.pv3.pv4-ns.ph4-m.ph5-l
(into [:nav.f6.fw6.ttu.tracked]
(map navbar-link links))])
(navbar [{:href "link1" :title "title here"}
{:href "link2" :title nil}
{:href "link3" :text "link text"}
{:href "link4"}])
#+END_SRC
You can use clojure core language to manipulate these lists.
place parts inside another containing element place parts inside another containing element
#+BEGIN_SRC clojure #+BEGIN_SRC clojure :results output :tangle src/core.cljs
(into [:div.container] (into [:div.container]
[[:span "span 1"] [[:span "span 1"]
[:span "span 2"]]) [:span "span 2"]])
#+END_SRC #+END_SRC
You could also use merge You could also use merge, in this example the spans are merged inside the div vector.
#+BEGIN_SRC clojure #+BEGIN_SRC clojure :results output :tangle src/core.cljs
(merge [:span "span 1"] [:span "span 2"] [:span "span 3"]) (merge [:div] [:span "span 1"] [:span "span 2"] [:span "span 3"])
#+END_SRC #+END_SRC
We can take advantage of lazyness if we like We can take advantage of lazyness if we like
#+BEGIN_SRC clojure #+BEGIN_SRC clojure :results output :tangle src/core.cljs
(take 2 (map navbar-link (defn navbar-link [{:keys [href title text] :or {text href title nil} :as link}]
[{:key "link1" :href "link1" :title "title here"} [:a.link.dim.white.dib.mr3 {:key href :href href :title title} text])
{:key "link2" :href "link2" :title nil}
{:key "link3" :href "link3" :text "link text"} [:div (into [:nav.f6.fw6.ttu.tracked] (vec (take 2 (mapv navbar-link
{:key "link4" :href "link4"}])) [{:key "link1" :href "link1" :title "title here"}
{:key "link2" :href "link2" :title nil}
{:key "link3" :href "link3" :text "link text"}
{:key "link4" :href "link4"}]))))]
#+END_SRC
** Compossible components
The main advantage comes from the ability to compose the parts together, so we can break our html apart and recombine using all the function at our disposal.
In this example our navigation is defined as a hash map, the data is separated out from the html, we can then pass the data to our component to render it.
In this example we have a link component and a nav component the link component take the values as key, value pairs and uses de structuring while also setting default if values are not set.
#+BEGIN_SRC clojure :results output :tangle src/core.cljs
(defn navbar-link [{:keys [href title text] :or {text href title nil} :as link}]
[:a.link.dim.white.dib.mr3 {:key href :href href :title title} text])
(defn navbar [links]
[:header.bg-black-90.w-100.ph3.pv3.pv4-ns.ph4-m.ph5-l
(into [:nav.f6.fw6.ttu.tracked]
(mapv navbar-link links))])
[navbar [{:href "link1" :title "title here"}
{:href "link2" :title nil}
{:href "link3" :text "link text"}
{:href "link4"}]]
#+END_SRC #+END_SRC
#+BEGIN_SRC clojure :results output :tangle src/core.cljs
(defn playing-card
[{:keys [title image stats]}]
[:article.fl.br2.ba.dark-gray.b--black-10.ma2.w-100.h-200.w-50-m.w-25-l.mw5
[:div.pa2.ph3-ns.pb3-ns
[:div.dt.w-100.mt1
[:div [:h1.f5.f4-ns.mv0 title]]
[:img.db.w-100.h-100.br2.br--top {:src image}]
#_[:div.dtc.tr [:h2.f5.mv0 "amount"]]]
(into [:ul.ma2.pa2] (mapv (fn build-stats [ [stat value]] [:li [:div stat [:div.fr (str value)]]]) stats))
[:p.f6.lh-copy.measure.mt2.mid-gray ""]]])
[:div
[playing-card
{:title "Bee"
:image "https://loremflickr.com/300/300/bee"
:stats {:strength ""
:lifespan "1" ;; 6 weeks
:danger ""
:mobility "9"}}]
[playing-card
{:title "Spider"
:image "https://loremflickr.com/300/300/spider"
:stats {:strength ""
:lifespan "3" ;; 1 year
:danger ""
:mobility ""}}]
[playing-card
{:title "Ant"
:image "https://loremflickr.com/300/300/ant"
:stats {:strength ""
:lifespan "8" ;; 7 years
:danger ""
:mobility ""}}]
[playing-card
{:title "Ant"
:image ""
:stats {:strength ""
:lifespan ""
:danger ""
:mobility ""}}]]
#+END_SRC

View File

@ -1,17 +1,43 @@
#+TITLE: HoneySQL #+TITLE: HoneySQL examples
* HoneySQL docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
https://github.com/seancorfield/honeysql
* Introduction
HoneySQL is a Domain Specific Language (DSL) for building SQL queries. HoneySQL provides a number of helper functions to make it easier to build queries, so you don't need to build the data structure manually. HoneySQL is a Domain Specific Language (DSL) for building SQL queries. HoneySQL provides a number of helper functions to make it easier to build queries, so you don't need to build the data structure manually.
HoneySQL does not care about connecting to your database. It only builds the queries. All examples send the result to =format= and =first= so that the resulting query is displayed inside the browser. HoneySQL does not care about connecting to your database. It only builds queries. All examples send the result to =format= and =first= so that the resulting query is displayed inside the browser.
#+BEGIN_SRC edn :results silent :exports none :tangle deps.edn
{:paths ["src" "resources"]
:deps
{org.clojure/clojure {:mvn/version "1.10.0"}
com.github.seancorfield/honeysql {:mvn/version "2.4.1045"}
}
:aliases {:run {:main-opts ["-m" "clojure-demo.core"]}}
}
#+END_SRC
#+BEGIN_SRC text :results silent :exports none :tangle readme.org
#+TITLE: Getting started
#+END_SRC
#+BEGIN_SRC clojure :tangle :exports none :tangle src/core.clj
(ns clojure-demo.core
(:require
["react-dom/client" :refer [createRoot]]
[reagent.core :as reagent]))
#+END_SRC
* Basic Query's
One nice way to write HoneySQL queries is to use the =->= threading macro. The =->= threading macro takes two arguments: the first argument is the result of the previous call, and the second argument is the function to call with that result. This allows you to chain together multiple calls to build complex queries. One nice way to write HoneySQL queries is to use the =->= threading macro. The =->= threading macro takes two arguments: the first argument is the result of the previous call, and the second argument is the function to call with that result. This allows you to chain together multiple calls to build complex queries.
Here is an example of how to use the =->= macro to build a simple SQL query: Here is an example of how to use the =->= macro to build a simple SQL query:
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(-> (sqlh/select :first_name :last_name :email) (-> (sqlh/select :first_name :last_name :email)
(sqlh/from :users) (sqlh/from :users)
(sql/format {:pretty true}) (sql/format {:pretty true})
@ -20,7 +46,7 @@ Here is an example of how to use the =->= macro to build a simple SQL query:
The equivalent code with out a threading macros looks like this. The equivalent code with out a threading macros looks like this.
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(first (first
(sql/format (sql/format
(sqlh/from (sqlh/from
@ -29,6 +55,7 @@ The equivalent code with out a threading macros looks like this.
{:pretty true})) {:pretty true}))
#+END_SRC #+END_SRC
** Basic SQL select queries ** Basic SQL select queries
Using HoneySQL you can incrementally build up our queries, they do not need to be complete to get an answer this allow us to define partial SQL and compose it together. Using HoneySQL you can incrementally build up our queries, they do not need to be complete to get an answer this allow us to define partial SQL and compose it together.
@ -79,7 +106,7 @@ Now is a good time to explain aliasing, basically the values to select become wr
** Basic SQL filtering ** Basic SQL filtering
Filtering is just as simple and support the usual operators like = < > we pass them in as keywords so =:== =:<>= =:<= =:.= would be the equivalents. Filtering is just as simple and support the usual operators like = < > we pass them in as keywords so =:== =:<>= =:<= =:.= would be the equivalents.
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(-> (sqlh/select :first_name :last_name :email) (-> (sqlh/select :first_name :last_name :email)
(sqlh/from :users) (sqlh/from :users)
(sqlh/where [:= :first_name "spot"] (sqlh/where [:= :first_name "spot"]
@ -91,7 +118,7 @@ Filtering is just as simple and support the usual operators like = < > we pass t
Often we want to conditionally filter, this is nice and simple with the knowledge that the =where= function will short circuit given a nil value this means we can use =when= and =if= functions inside our sql generations. Often we want to conditionally filter, this is nice and simple with the knowledge that the =where= function will short circuit given a nil value this means we can use =when= and =if= functions inside our sql generations.
So below the SQL where will not be appended because true is not false so the when returns nil removing the where in the generated query. So below the SQL where will not be appended because true is not false so the when returns nil removing the where in the generated query.
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(-> (sqlh/select :first_name :last_name :email) (-> (sqlh/select :first_name :last_name :email)
(sqlh/from :users) (sqlh/from :users)
(sqlh/where (when (true? false) [:= :first_name "spot"])) (sqlh/where (when (true? false) [:= :first_name "spot"]))
@ -100,7 +127,7 @@ So below the SQL where will not be appended because true is not false so the whe
#+END_SRC #+END_SRC
We can use similar technique to switch between matching a single and multiple values. We can use similar technique to switch between matching a single and multiple values.
#+BEGIN_SRC clojurescript :results verbatim :tangle ./src/core.cljs #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(defn conditional-where [id] (defn conditional-where [id]
(-> (sqlh/select :*) (-> (sqlh/select :*)
(sqlh/from [:company]) (sqlh/from [:company])
@ -117,14 +144,14 @@ We can use similar technique to switch between matching a single and multiple va
(first))]) (first))])
#+END_SRC #+END_SRC
** Composing SQL queries and performing joins ** Composing SQL queries
For all the standard fn's like select and where there are equivalent merge fn's the merge versions append in place of replacing. For all the standard fn's like select and where there are equivalent merge fn's the merge versions append in place of replacing.
A good strategy is to build basic queries extending them when needed, so create a base select then create a function which build on the query adding in the conditions, this allow you to run the base queries in the REPL or the extended version making it easier to find query related issues by testing parts in isolation. A good strategy is to build basic queries extending them when needed, so create a base select then create a function which build on the query adding in the conditions, this allow you to run the base queries in the REPL or the extended version making it easier to find query related issues by testing parts in isolation.
we can use =if= =when= =when-let= =cond->= among other functions to help build these, in the example below you can see the where part of the query is modified based on what values are provided in the map. we can use =if= =when= =when-let= =cond->= among other functions to help build these, in the example below you can see the where part of the query is modified based on what values are provided in the map.
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(def base-sql (def base-sql
(-> (sqlh/select :first_name :last_name :email) (-> (sqlh/select :first_name :last_name :email)
(sqlh/from :users))) (sqlh/from :users)))
@ -154,10 +181,10 @@ we can use =if= =when= =when-let= =cond->= among other functions to help build t
(first))]) (first))])
#+END_SRC #+END_SRC
** Joining tables
We can also do joins to other table's We can also do joins to other table's
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(def base-sql (def base-sql
(-> (sqlh/select :first_name :last_name :email) (-> (sqlh/select :first_name :last_name :email)
(sqlh/from :users))) (sqlh/from :users)))
@ -171,7 +198,7 @@ We can also do joins to other table's
or group by's and sql functions like =count= =max= =min= these can be used by appending :%name to the selected column. or group by's and sql functions like =count= =max= =min= these can be used by appending :%name to the selected column.
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(def base-group-sql (def base-group-sql
(-> base-sql (-> base-sql
(sqlh/select :first_name [:%count.first_name :count_name]) (sqlh/select :first_name [:%count.first_name :count_name])
@ -182,7 +209,7 @@ or group by's and sql functions like =count= =max= =min= these can be used by ap
** Larger query ** Larger query
This is how I like to compose queries, and shows a larger query being generated. This is how I like to compose queries, and shows a larger query being generated.
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(def big-base-sql (def big-base-sql
(-> (sqlh/select :users.* :address.* :products.*) (-> (sqlh/select :users.* :address.* :products.*)
(sqlh/from :users) (sqlh/from :users)
@ -224,12 +251,12 @@ Don't forget its just data, if you don't use sql/format it just returns a data s
When all else fails you have a few options, check to see if there is a honeysql db specific library or break out =sql/raw= or extending honey sql. When all else fails you have a few options, check to see if there is a honeysql db specific library or break out =sql/raw= or extending honey sql.
Say we want to get people added in the last 14 days this is a bit more tricky Say we want to get people added in the last 14 days this is a bit more tricky
#+BEGIN_SRC clojure :results verbatim #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(def base-last-14-days-sql [(def base-last-14-days-sql
(-> base-sql (-> base-sql
(sqlh/where [:> (sqlh/where [:>
[:raw "created"] [:raw "created"]
[:raw "CURRENT_DATE - INTERVAL '14' DAY"]]))) [:raw "CURRENT_DATE - INTERVAL '14' DAY"]])))]
(first (sql/format base-last-14-days-sql)) (first (sql/format base-last-14-days-sql))
@ -240,7 +267,7 @@ Say we want to get people added in the last 14 days this is a bit more tricky
*** Switch between singular or multiple values in condition *** Switch between singular or multiple values in condition
#+BEGIN_SRC clojurescript :tangle ./src/core.cljs #+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(defn conditional-where [id] (defn conditional-where [id]
(-> (sqlh/select :*) (-> (sqlh/select :*)
(sqlh/from [:company]) (sqlh/from [:company])
@ -250,3 +277,29 @@ Say we want to get people added in the last 14 days this is a bit more tricky
;(clojure.string/join "" (sql/format (conditional-where [1 2 3]) {:pretty true})) ;(clojure.string/join "" (sql/format (conditional-where [1 2 3]) {:pretty true}))
#+END_SRC #+END_SRC
* Insert or update data on conflict
In this example we will insert some data but on a conflict we will update the row instead,
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(defn upsert-daily-sales-sql [values]
(-> (sqlh/insert-into :address)
(sqlh/values values)
(sqlh/on-conflict :first_name :last_name :email)
(sqlh/do-update-set :line1 :line2 :city :country :postcode)))
#+END_SRC
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
(defn -main []
(first (sql/format (conditional-where [1 2 3]) {:pretty true}))
)
#+END_SRC
* Further reading
https://github.com/seancorfield/honeysql

View File

@ -60,6 +60,8 @@ Reagent is a popular react wrapper in the clojurescript it greatly simplify buil
#+BEGIN_SRC text :results silent :exports none :tangle readme.org #+BEGIN_SRC text :results silent :exports none :tangle readme.org
#+TITLE: Getting started #+TITLE: Getting started
#+END_SRC
* Install the npm requirements. * Install the npm requirements.
npx install npx install
@ -220,7 +222,7 @@ If we wish to capture a node we can use =:ref= and store the result in an atom,
#+END_SRC #+END_SRC
#+BEGIN_SRC json :tangle src/clojure_demo/core.cljs #+BEGIN_SRC clojure :tangle src/clojure_demo/core.cljs
(defn current-page [] (defn current-page []
[:div [:div

View File

@ -53,6 +53,11 @@
'from (sci/copy-var sqlh/from sqlh-ns) 'from (sci/copy-var sqlh/from sqlh-ns)
'limit (sci/copy-var sqlh/limit sqlh-ns) 'limit (sci/copy-var sqlh/limit sqlh-ns)
'join (sci/copy-var sqlh/join sqlh-ns) 'join (sci/copy-var sqlh/join sqlh-ns)
'values (sci/copy-var sqlh/values sqlh-ns)
'on-conflict (sci/copy-var sqlh/on-conflict sqlh-ns)
'do-update-set (sci/copy-var sqlh/do-update-set sqlh-ns)
'insert-into (sci/copy-var sqlh/insert-into sqlh-ns)
'order-by (sci/copy-var sqlh/order-by sqlh-ns)
'group-by (sci/copy-var sqlh/group-by sqlh-ns) 'group-by (sci/copy-var sqlh/group-by sqlh-ns)
'where (sci/copy-var sqlh/where sqlh-ns)} 'where (sci/copy-var sqlh/where sqlh-ns)}
'rf {'router (sci/copy-var rf/router rf-ns)} 'rf {'router (sci/copy-var rf/router rf-ns)}
@ -85,7 +90,6 @@
[] []
transactions)) transactions))
(defn code-editor (defn code-editor
[{:keys [exports class results]} content] [{:keys [exports class results]} content]
(let [language class (let [language class
@ -104,8 +108,7 @@
(first selected-text) (first selected-text)
(.-doc (.-state view-update)))] (.-doc (.-state view-update)))]
(reset! evaled-result (sci/eval-string* sci-ctx (reset! evaled-result (sci/eval-string* sci-ctx
(.toString eval-code) (.toString eval-code)))
))
(prn "updated delayed"))) 1000))))) (prn "updated delayed"))) 1000)))))
start-state start-state
(.create EditorState (.create EditorState
@ -126,7 +129,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 (if exports
nil ;[:<>] nil ;[:<>]
[:div.mb2 [:div.mb2
[:div.ba.ma0.f5.b--black-05.pa2.overflow-auto.editor {:ref #(reset! editor %)}] [:div.ba.ma0.f5.b--black-05.pa2.overflow-auto.editor {:ref #(reset! editor %)}]
@ -171,9 +174,28 @@
{:homepage {:intro "Clojure tutorials examples and exploration"} {:homepage {:intro "Clojure tutorials examples and exploration"}
:dslpage {:intro "A domain-specific language (DSL) is a language designed to be used for a specific task or domain, clojure has a rich set of DSL some popular DSL's are listed on this page with example's on usage. "} :dslpage {:intro "A domain-specific language (DSL) is a language designed to be used for a specific task or domain, clojure has a rich set of DSL some popular DSL's are listed on this page with example's on usage. "}
:lorem "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum." :lorem "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
:pages {:dialects {:title "Dialects"
:key ::dialects}
:devops {:title "devops"
:key ::devops}
:dsl {:title "DSL's"
:key ::dsl
:intro "A domain-specific language (DSL) is a language designed to be used for a specific task or domain, clojure has a rich set of DSL some popular DSL's are listed on this page with example's on usage. "
:demos [{:title "Hiccup HTML Demo"
:page "hiccup-dsl-demo"
; :link (rfe/href ::demo {:page "hiccup-dsl-demo"})
:icon-image "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"}
{:title "Honey SQL Demo"
:page "honey-sql-demo"
; :link (rfe/href ::demo {:page "honey-dsl-demo"})
:icon-image "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"}
{:title "Datalog Demo"
:page "datalog-demo"
; :link (rfe/href ::demo {:page "datalog-demo"})
:icon-image "https://raw.githubusercontent.com/tonsky/datascript/master/extras/logo.svg"}]}}
:demos :demos
{:dsl-demo {:hiccup-dsl-demo
{:file "documents/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"}
:datalog-demo :datalog-demo
{:file "documents/datalog-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"} {:file "documents/datalog-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"}
:honey-sql-demo :honey-sql-demo
@ -243,7 +265,7 @@
(into [:nav.f6.fw6.ttu.tracked] (mapv navbar-link links))]) (into [:nav.f6.fw6.ttu.tracked] (mapv navbar-link links))])
(defn footer [] (defn footer []
[:footer.pv4.ph3.ph5-m.ph6-l.mid-gray.w-full [:footer.bg-near-black.white-80.pv4.ph3.ph5-m.ph6-l.mid-gray.w-full
[:a.f6.dib.ph2.link.mid-gray.dim [:a.f6.dib.ph2.link.mid-gray.dim
{:target "_blank" :href "https://matrix.to/#/@oly:matrix.org"} {:target "_blank" :href "https://matrix.to/#/@oly:matrix.org"}
"Contact me"]]) "Contact me"]])
@ -277,27 +299,43 @@
:link (rfe/href ::demo {:page "reagent-demo"}) :link (rfe/href ::demo {:page "reagent-demo"})
:img-src "https://raw.githubusercontent.com/reagent-project/reagent/master/logo/logo-text.png"}]}]]) :img-src "https://raw.githubusercontent.com/reagent-project/reagent/master/logo/logo-text.png"}]}]])
(defn dsl-page [] (defn grouped-page [group]
[:<> [:<>
[articles [articles
{:title "Clojure Demos" {:title "Clojure Demos"
:body (-> site-data :dslpage :intro) :body (-> site-data :pages group :intro)
:articles :articles
[{:title "Hiccup HTML Demo" (mapv (fn fmt-map [demo]
:link (rfe/href ::demo {:page "hiccup-dsl-demo"}) {:title (:title demo)
:img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"} :link (rfe/href ::demo {:page (:page demo)})
{:title "Honey SQL Demo" :img-src (:icon-image demo)})
:description "Querying a database using the HoneySQL DSL" (-> site-data :pages group :demos))}]])
:link (rfe/href ::demo {:page "honey-sql-demo"})
:img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"} (defn dialects-page [route]
{:title "Datalog Demo" [:<>
:link (rfe/href ::demo {:page "datalog-demo"}) [grouped-page (keyword (name (:name (:data route))))]])
:img-src "https://raw.githubusercontent.com/tonsky/datascript/master/extras/logo.svg"}]}]])
(defn dsl-page [route]
[:<>
[grouped-page (keyword (name (:name (:data route))))]
#_[articles
{:title "Clojure Demos"
:body (-> site-data :pages :intro)
:articles
[{:title "Hiccup HTML Demo"
:link (rfe/href ::demo {:page "hiccup-dsl-demo"})
:img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"}
{:title "Honey SQL Demo"
:description "Querying a database using the HoneySQL DSL"
:link (rfe/href ::demo {:page "honey-sql-demo"})
:img-src "https://miro.medium.com/max/1400/1*CEYFj5R57UFyCXts2nsBqA.png"}
{:title "Datalog Demo"
:link (rfe/href ::demo {:page "datalog-demo"})
:img-src "https://raw.githubusercontent.com/tonsky/datascript/master/extras/logo.svg"}]}]])
(def toc (partial contains? (into #{} (map keyword [:HEADER1 :HEADER2 :HEADER3 :HEADER4 :HEADER5 :HEADER6])))) (def toc (partial contains? (into #{} (map keyword [:HEADER1 :HEADER2 :HEADER3 :HEADER4 :HEADER5 :HEADER6]))))
(def org-code (partial contains? (into #{} (map keyword [:SRC])))) (def org-code (partial contains? (into #{} (map keyword [:SRC]))))
(defn build-file-tar [code-blocks] (defn build-file-tar [code-blocks]
(tarts (clj->js (mapv (fn [block] {:name (str (:tangle (second block))) (tarts (clj->js (mapv (fn [block] {:name (str (:tangle (second block)))
:content (str (last block))}) :content (str (last block))})
@ -361,24 +399,24 @@
[:main.mt4 [:main.mt4
[:section.mw7.center.avenir [:section.mw7.center.avenir
[:h1 "Clojure library examples to aid learning"] [:h1 "Clojure library examples to aid learning"]
[:p "Selection of clojure demos, rendered in reagent which itself is an example of using reagent."] [:p ""]
[my-component "Clickable component" 1] ;; [my-component "Clickable component" 1]
[my-component "Clickable component" 2] ;; [my-component "Clickable component" 2]
[:p "Image circle componenet"] ;; [:p "Image circle componenet"]
[circle {:img "http://placekitten.com/g/300/300" :alt "test"}] ;; [circle {:img "http://placekitten.com/g/300/300" :alt "test"}]
[:p "Product card component"] ;; [:p "Product card component"]
[:div.flex.flex-column.flex-row-ns #_[:div.flex.flex-column.flex-row-ns
[product-card [product-card
{:title "Cat 01" {:title "Cat 01"
:amount "£54.59" :amount "£54.59"
:description "Cat description here" :description "Cat description here"
:link "http://placekitten.com/g/600/300"}] :link "http://placekitten.com/g/600/300"}]
[product-card [product-card
{:title "Cat 02" {:title "Cat 02"
:amount "£10.59" :amount "£10.59"
:description "Cat description here" :description "Cat description here"
:link "http://placekitten.com/g/600/300"}]] :link "http://placekitten.com/g/600/300"}]]
[:p "Article component"] #_[:p "Article component"]
[article {:title "Example Article component" [article {:title "Example Article component"
:description (-> site-data :lorem) :description (-> site-data :lorem)
:tagline "https://tachyons.io/components/"}]]]) :tagline "https://tachyons.io/components/"}]]])
@ -425,10 +463,20 @@
;; 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
[navbar [{:href (rfe/href ::frontpage) :title "title here" :text "home" :key "homepage"} #_(str (concat
{:href (rfe/href ::dsl) :text "DSL's" :key "dsl"} (mapv (fn build-nav [[key page]] {:href (rfe/href key) :text (:title page)}) (-> site-data :pages))
{:title "Domain Specific Languages" :href (rfe/href ::about) :text "About" :key "about"} [{:href (rfe/href ::frontpage) :title "title here" :text "home" :key "homepage"}
#_{:href (rfe/href ::i-do-not-exist) :text "missing"}]] {:href (rfe/href ::dsl) :text "DSL's" :key "dsl"}
{:title "Domain Specific Languages" :href (rfe/href ::about) :text "About" :key "about"}
#_{:href (rfe/href ::i-do-not-exist) :text "missing"}])
)
[navbar (concat
[{: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))
[{:href (rfe/href ::dsl) :text "DSL's" :key "dsl"}
{:title "Domain Specific Languages" :href (rfe/href ::about) :text "About" :key "about"}
#_{:href (rfe/href ::i-do-not-exist) :text "missing"}])]
[:main.ma4 [:main.ma4
(when-let [view (-> @site-state :current-route :data :view)] [view (-> @site-state :current-route)])] (when-let [view (-> @site-state :current-route :data :view)] [view (-> @site-state :current-route)])]
[footer]]) [footer]])