Improvements to the hiccup info.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
b0e57579c3
commit
e006f31ae5
|
@ -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./
|
||||
|
|
|
@ -1,71 +1,126 @@
|
|||
#+TITLE: Intro to Hiccup
|
||||
|
||||
|
||||
* Hiccup
|
||||
https://github.com/weavejester/hiccup
|
||||
* Introduction
|
||||
|
||||
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.
|
||||
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
|
||||
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"]
|
||||
#+END_SRC
|
||||
|
||||
*** Styles classes and ID's
|
||||
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"]
|
||||
#+END_SRC
|
||||
|
||||
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"]
|
||||
#+END_SRC
|
||||
|
||||
** Compossible components
|
||||
The main advantage comes from the ability to compose the parts together, so we can break this into function's
|
||||
** Example of manipulating hiccup with clojure functions
|
||||
|
||||
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.
|
||||
|
||||
|
||||
#+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.
|
||||
You can use clojure core language to manipulate these vectors.
|
||||
|
||||
place parts inside another containing element
|
||||
#+BEGIN_SRC clojure
|
||||
#+BEGIN_SRC clojure :results output :tangle src/core.cljs
|
||||
(into [:div.container]
|
||||
[[:span "span 1"]
|
||||
[:span "span 2"]])
|
||||
#+END_SRC
|
||||
|
||||
You could also use merge
|
||||
#+BEGIN_SRC clojure
|
||||
(merge [:span "span 1"] [:span "span 2"] [:span "span 3"])
|
||||
You could also use merge, in this example the spans are merged inside the div vector.
|
||||
#+BEGIN_SRC clojure :results output :tangle src/core.cljs
|
||||
(merge [:div] [:span "span 1"] [:span "span 2"] [:span "span 3"])
|
||||
#+END_SRC
|
||||
|
||||
We can take advantage of lazyness if we like
|
||||
#+BEGIN_SRC clojure
|
||||
(take 2 (map navbar-link
|
||||
[{:key "link1" :href "link1" :title "title here"}
|
||||
{:key "link2" :href "link2" :title nil}
|
||||
{:key "link3" :href "link3" :text "link text"}
|
||||
{:key "link4" :href "link4"}]))
|
||||
#+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])
|
||||
|
||||
[:div (into [:nav.f6.fw6.ttu.tracked] (vec (take 2 (mapv navbar-link
|
||||
[{: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
|
||||
|
||||
|
||||
|
||||
#+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
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,43 @@
|
|||
#+TITLE: HoneySQL
|
||||
#+TITLE: HoneySQL examples
|
||||
|
||||
* HoneySQL
|
||||
https://github.com/seancorfield/honeysql
|
||||
docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
|
||||
|
||||
* 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 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.
|
||||
|
||||
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/from :users)
|
||||
(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.
|
||||
|
||||
#+BEGIN_SRC clojure :results verbatim
|
||||
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
|
||||
(first
|
||||
(sql/format
|
||||
(sqlh/from
|
||||
|
@ -29,6 +55,7 @@ The equivalent code with out a threading macros looks like this.
|
|||
{:pretty true}))
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** 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.
|
||||
|
||||
|
@ -79,7 +106,7 @@ Now is a good time to explain aliasing, basically the values to select become wr
|
|||
** 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.
|
||||
#+BEGIN_SRC clojure :results verbatim
|
||||
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
|
||||
(-> (sqlh/select :first_name :last_name :email)
|
||||
(sqlh/from :users)
|
||||
(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.
|
||||
|
||||
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/from :users)
|
||||
(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
|
||||
|
||||
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]
|
||||
(-> (sqlh/select :*)
|
||||
(sqlh/from [:company])
|
||||
|
@ -117,14 +144,14 @@ We can use similar technique to switch between matching a single and multiple va
|
|||
(first))])
|
||||
#+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.
|
||||
|
||||
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.
|
||||
|
||||
#+BEGIN_SRC clojure :results verbatim
|
||||
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
|
||||
(def base-sql
|
||||
(-> (sqlh/select :first_name :last_name :email)
|
||||
(sqlh/from :users)))
|
||||
|
@ -154,10 +181,10 @@ we can use =if= =when= =when-let= =cond->= among other functions to help build t
|
|||
(first))])
|
||||
#+END_SRC
|
||||
|
||||
|
||||
** Joining tables
|
||||
|
||||
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
|
||||
(-> (sqlh/select :first_name :last_name :email)
|
||||
(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.
|
||||
|
||||
#+BEGIN_SRC clojure :results verbatim
|
||||
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
|
||||
(def base-group-sql
|
||||
(-> base-sql
|
||||
(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
|
||||
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
|
||||
(-> (sqlh/select :users.* :address.* :products.*)
|
||||
(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.
|
||||
|
||||
Say we want to get people added in the last 14 days this is a bit more tricky
|
||||
#+BEGIN_SRC clojure :results verbatim
|
||||
(def base-last-14-days-sql
|
||||
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
|
||||
[(def base-last-14-days-sql
|
||||
(-> base-sql
|
||||
(sqlh/where [:>
|
||||
[:raw "created"]
|
||||
[:raw "CURRENT_DATE - INTERVAL '14' DAY"]])))
|
||||
[:raw "CURRENT_DATE - INTERVAL '14' DAY"]])))]
|
||||
|
||||
|
||||
(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
|
||||
|
||||
#+BEGIN_SRC clojurescript :tangle ./src/core.cljs
|
||||
#+BEGIN_SRC clojure :results verbatim :tangle src/core.clj
|
||||
(defn conditional-where [id]
|
||||
(-> (sqlh/select :*)
|
||||
(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}))
|
||||
#+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
|
||||
|
|
|
@ -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
|
||||
#+TITLE: Getting started
|
||||
|
||||
#+END_SRC
|
||||
|
||||
* Install the npm requirements.
|
||||
|
||||
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
|
||||
|
||||
|
||||
#+BEGIN_SRC json :tangle src/clojure_demo/core.cljs
|
||||
#+BEGIN_SRC clojure :tangle src/clojure_demo/core.cljs
|
||||
|
||||
(defn current-page []
|
||||
[:div
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
'from (sci/copy-var sqlh/from sqlh-ns)
|
||||
'limit (sci/copy-var sqlh/limit 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)
|
||||
'where (sci/copy-var sqlh/where sqlh-ns)}
|
||||
'rf {'router (sci/copy-var rf/router rf-ns)}
|
||||
|
@ -85,7 +90,6 @@
|
|||
[]
|
||||
transactions))
|
||||
|
||||
|
||||
(defn code-editor
|
||||
[{:keys [exports class results]} content]
|
||||
(let [language class
|
||||
|
@ -104,8 +108,7 @@
|
|||
(first selected-text)
|
||||
(.-doc (.-state view-update)))]
|
||||
(reset! evaled-result (sci/eval-string* sci-ctx
|
||||
(.toString eval-code)
|
||||
))
|
||||
(.toString eval-code)))
|
||||
(prn "updated delayed"))) 1000)))))
|
||||
start-state
|
||||
(.create EditorState
|
||||
|
@ -126,7 +129,7 @@
|
|||
:parent @editor})))))
|
||||
:component-will-unmount (fn [_] (.destroy @view))
|
||||
:reagent-render (fn []
|
||||
(if exports
|
||||
(if exports
|
||||
nil ;[:<>]
|
||||
[:div.mb2
|
||||
[: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"}
|
||||
: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."
|
||||
: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
|
||||
{:dsl-demo
|
||||
{:file "documents/dsl-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"}
|
||||
{:hiccup-dsl-demo
|
||||
{:file "documents/hiccup-dsl-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"}
|
||||
:datalog-demo
|
||||
{:file "documents/datalog-demo.org" :git-link "https://github.com/atomjuice/dsl-demo"}
|
||||
:honey-sql-demo
|
||||
|
@ -243,7 +265,7 @@
|
|||
(into [:nav.f6.fw6.ttu.tracked] (mapv navbar-link links))])
|
||||
|
||||
(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
|
||||
{:target "_blank" :href "https://matrix.to/#/@oly:matrix.org"}
|
||||
"Contact me"]])
|
||||
|
@ -277,27 +299,43 @@
|
|||
:link (rfe/href ::demo {:page "reagent-demo"})
|
||||
:img-src "https://raw.githubusercontent.com/reagent-project/reagent/master/logo/logo-text.png"}]}]])
|
||||
|
||||
(defn dsl-page []
|
||||
(defn grouped-page [group]
|
||||
[:<>
|
||||
[articles
|
||||
{:title "Clojure Demos"
|
||||
:body (-> site-data :dslpage :intro)
|
||||
:body (-> site-data :pages group :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"}]}]])
|
||||
(mapv (fn fmt-map [demo]
|
||||
{:title (:title demo)
|
||||
:link (rfe/href ::demo {:page (:page demo)})
|
||||
:img-src (:icon-image demo)})
|
||||
(-> site-data :pages group :demos))}]])
|
||||
|
||||
(defn dialects-page [route]
|
||||
[:<>
|
||||
[grouped-page (keyword (name (:name (:data route))))]])
|
||||
|
||||
(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 org-code (partial contains? (into #{} (map keyword [:SRC]))))
|
||||
|
||||
|
||||
(defn build-file-tar [code-blocks]
|
||||
(tarts (clj->js (mapv (fn [block] {:name (str (:tangle (second block)))
|
||||
:content (str (last block))})
|
||||
|
@ -361,24 +399,24 @@
|
|||
[:main.mt4
|
||||
[:section.mw7.center.avenir
|
||||
[:h1 "Clojure library examples to aid learning"]
|
||||
[:p "Selection of clojure demos, rendered in reagent which itself is an example of using reagent."]
|
||||
[my-component "Clickable component" 1]
|
||||
[my-component "Clickable component" 2]
|
||||
[:p "Image circle componenet"]
|
||||
[circle {:img "http://placekitten.com/g/300/300" :alt "test"}]
|
||||
[:p "Product card component"]
|
||||
[:div.flex.flex-column.flex-row-ns
|
||||
[product-card
|
||||
{:title "Cat 01"
|
||||
:amount "£54.59"
|
||||
:description "Cat description here"
|
||||
:link "http://placekitten.com/g/600/300"}]
|
||||
[product-card
|
||||
{:title "Cat 02"
|
||||
:amount "£10.59"
|
||||
:description "Cat description here"
|
||||
:link "http://placekitten.com/g/600/300"}]]
|
||||
[:p "Article component"]
|
||||
[:p ""]
|
||||
;; [my-component "Clickable component" 1]
|
||||
;; [my-component "Clickable component" 2]
|
||||
;; [:p "Image circle componenet"]
|
||||
;; [circle {:img "http://placekitten.com/g/300/300" :alt "test"}]
|
||||
;; [:p "Product card component"]
|
||||
#_[:div.flex.flex-column.flex-row-ns
|
||||
[product-card
|
||||
{:title "Cat 01"
|
||||
:amount "£54.59"
|
||||
:description "Cat description here"
|
||||
:link "http://placekitten.com/g/600/300"}]
|
||||
[product-card
|
||||
{:title "Cat 02"
|
||||
:amount "£10.59"
|
||||
:description "Cat description here"
|
||||
:link "http://placekitten.com/g/600/300"}]]
|
||||
#_[:p "Article component"]
|
||||
[article {:title "Example Article component"
|
||||
:description (-> site-data :lorem)
|
||||
: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
|
||||
(defn current-page []
|
||||
[:div
|
||||
[navbar [{:href (rfe/href ::frontpage) :title "title here" :text "home" :key "homepage"}
|
||||
{: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"}]]
|
||||
#_(str (concat
|
||||
(mapv (fn build-nav [[key page]] {:href (rfe/href key) :text (:title page)}) (-> site-data :pages))
|
||||
[{:href (rfe/href ::frontpage) :title "title here" :text "home" :key "homepage"}
|
||||
{: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
|
||||
(when-let [view (-> @site-state :current-route :data :view)] [view (-> @site-state :current-route)])]
|
||||
[footer]])
|
||||
|
|
Loading…
Reference in New Issue