Skip to content

A component that watches-and-recompiles your Garden stylesheets.

License

Notifications You must be signed in to change notification settings

lambdaisland/garden-watcher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Garden reloader component

Watch your Garden stylesheets for changes, and compiles them to CSS.

Quickstart

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.

Use with garden-watcher.main

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

Use as a library

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)

Use as a Component

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.

Use of metadata

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

One-off Compiling to CSS

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

CLJC support

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.

License

Copyright © 2016-2019 Arne Brasseur

Distributed under the Mozilla Public License 2.0 (https://www.mozilla.org/en-US/MPL/2.0/)

About

A component that watches-and-recompiles your Garden stylesheets.

Resources

License

Stars

Watchers

Forks

Packages

No packages published