Watch your Garden stylesheets for changes, and compiles them to CSS.
Add lambdaisland/garden-watcher
as a dependency in deps.edn
(Clojure CLI),
project.clj
(Leiningen) or build.boot
(Boot).
;; deps.edn
{lambdaisland/garden-watcher {:mvn/version "1.0.45"}}
;; project.clj/build.boot
[lambdaisland/garden-watcher "1.0.45"]
Create vars containing Garden-style declarations, and add a ^:garden
metadata
to the var.
(ns sesame.styles)
(def ^:garden main
(list
[:h1 {:color "blue"}]
[:h2 {:color "green"}]
[:h3 {:color "red"}]))
Now you start garden-watcher, passing it your namespace name, and it will
recompile the stylesheet and create a main.css
file whenever the namespace
changes. You can start garden-watcher in several ways. For more metadata options
(e.g. to control the output file) and a convenience macro (defstyles
), see
below.
There's a main namespace that's convenient if you want to simply run the watcher as its own process. You pass one or more namespace names as arguments.
;; leiningen
lein run -m garden-watcher.main name.of.your.namespace
;; clojure CLI
clj -m garden-watcher.main name.of.your.namespace
There are start/stop functions so you can hook this up however you like. Useful for use with Integrant, Mount, etc.
(require '[garden-watcher.core :as gw])
(def watcher (gw/start-garden-watcher! '[name.of.namespace name.of.other.namespace]))
(gw/stop-garden-watcher! watcher)
If you're using com.stuartsierra.component
then you can use the built-in
component directly.
Use garden-watcher.core/new-garden-watcher
to create the component, passing it
a vector of namespace names. Once started this will watch and compile each var
with a :garden
metadata key in the given namespaces to a CSS file.
Also, hawk options map can be passed as a second argument.
(ns user
(:require [com.stuartsierra.component :as component]
[figwheel-sidecar.config :as fw-conf]
[figwheel-sidecar.system :as fw-sys]
[garden-watcher.core :refer [new-garden-watcher]])) ;; <------
(defn dev-system []
(component/system-map
:figwheel-system (fw-sys/figwheel-system (fw-conf/fetch-config))
:css-watcher (fw-sys/css-watcher {:watch-paths ["resources/public/css"]})
:garden-watcher (new-garden-watcher '[sesame.styles]))) ;; <------
The above will generate resources/public/css/main.css
, and recreate it
whenever styles.clj
is saved. By combining it with Figwheel's CSS reloader you
get instant reloading in the browser.
Garden provides a macro, garden.def/defstylesheet
, that allows you to pass
compiler options to garde.core/css
. By adding :output-to
this allows writing
stylesheets that "automatically" create the corresponding CSS files. When using
garden-watcher you should not use defstylesheet
.
With defstylesheet
the compile-to-CSS happens as a side effect of loading the
namespace, which makes it impossible to load the namespace without generating
the CSS file, or generating the CSS without reloading the namespace. Therefore
garden-watcher
chose a different approach.
Instead create regular vars, adn tag them with a :garden
metadata key. You can
use a map to add compiler options, including :output-to
.
(def
^{:garden {:output-to "resources/public/styles.css"
:vendors ["webkit"]}}
my-stylesheet
(list
[:h1 {:color "blue"}]))
If you don't specify an output file, it defaults to resources/public/css/{{var-name}}.css
;; This creates resources/public/css/anja.css
(def ^:garden anja
(list
[:h1 {:color "blue"}]))
Note that Garden provides garden.def/defstyles
macro that allows you to get
rid of the (list ,,,)
(that's all that macro does), so this code is equivalent:
(require '[garden.def :refer [defstyles]])
(defstyles ^:garden anja
[:h1 {:color "blue"}])
Or you can use garden-watcher.def/defstyles
, which does the exact same thing,
but automatically adds the :garden
metadata, so this code is equivalent again:
(require '[garden-watcher.def :refer [defstyles]]) ;; <-- different namespace
(defstyles anja
[:h1 {:color "blue"}])
To generate CSS files from these vars, use
garden-watcher.core/compile-garden-namespaces
:
(compile-garden-namespaces '[sesame.styles])
garden-watcher also includes a "main" entry point to make it easy to invoke this as a build step.
lein run -m garden-watcher.main sesame.styles
E.g. say you're building an uberjar containing compiled ClojureScript and CSS.
(defproject sesame "0.1.0"
,,,
:uberjar-name "sesame.jar"
:profiles {,,,
:uberjar
{:prep-tasks ["compile"
["cljsbuild" "once" "min"]
["run" "-m" "garden-watcher.main" "sesame.styles"]]
:omit-source true
:aot :all}})
In order to share code with Clojurescript, cljc
files are fully supported.
However, note that priority is given to regular clj
files when both kind
exist for a given namespace.
Copyright © 2016-2019 Arne Brasseur
Distributed under the Mozilla Public License 2.0 (https://www.mozilla.org/en-US/MPL/2.0/)