tristanstraub / garden-mower

Clojure based CSS preprocessor to emulate @apply from PostCSS and output noprompt/garden config

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Garden-mower is a simple clojure based CSS preprocessor that emulates @apply from PostCSS, as used by tailwindcss. It merges specific selector attributes from a css document, and outputs data that can be digested by https://github.com/noprompt/garden.

Dependency

Add garden-mower to your dependencies. With tools.deps:

{:deps {com.tristanstraub/garden-mower {:git/url "https://github.com/tristanstraub/garden-mower"
                                        :sha "c8af31358ae1da496c18d3c9d2a35d049611d5f8"}}}

Examples

Motivation

I want to use tailwindcss, but I want to keep my tooling within clojure. I need to be able to create custom class selectors which combine the attributes of specified tailwindcss classes.

I want to run the following, where the keyword arguments passed to garden-mower.core/attributes designate tailwindcss css classes:

(garden.core/css
 [[:.card-container (garden-mower.core/attributes css :.flex :.mx-auto :.flex-col :.sm:flex-row)]
  [:.card-outer (garden-mower.core/attributes css :.max-w-sm :.w-full :.sm:max-w-full :.lg:flex :.mb-1 :.mx-auto :.sm:mx-1)]])

to produce roughly the following CSS:

.card-container {
  display: flex;
  margin-left: auto;
  margin-right: auto;
  flex-direction: column;
}

@media (min-width: 640px) {
  .card-container {
    flex-direction: row;
  }
}

.card-outer {
  max-width: 24rem;
  width: 100%;
}

@media (min-width: 640px) {
  .card-outer {
    max-width: 100%;
  }
}

@media (min-width: 1024px) {
  .card-outer {
    display: flex;
  }
}

.card-outer {
  margin-bottom: 0.25rem;
  margin-left: auto;
  margin-right: auto;
}

@media (min-width: 640px) {
  .card-outer {
    margin-left: 0.25rem;
    margin-right: 0.25rem;
  }
}

Usage

garden-mower.core/attributes walks a css document and extracts the attributes that match the selector(s), and converts them into a form that can be digested by https://github.com/noprompt/garden.

Currently, the fetched selectors must be simple single elements, but the result of garden-mower.core/attributes can be embedded within any selector block being delivered to garden.core/css (in my experience!).

Because garden supports nested media queries (so good!), media queries of the selectors are preserved. The following example demonstrates this:

(def css "
  @media (min-width: 640px) {
    .blue   { color: rgba(0,0,255,1); }
  }
  .bg-red { background-color: rgba(255,0,0,1); }")

(garden.core/css [[:.btn (garden-mower.core/attributes css :.blue :.bg-red)]
                  [:.btn-red (garden-mower.core/attributes css :.bg-red)]])

which produces:

@media (min-width: 640px) {
  .btn {
    color: rgba(0, 0, 255, 1);
  }
}

.btn {
  background-color: rgba(255, 0, 0, 1);
}

.btn-red {
  background-color: rgba(255, 0, 0, 1);
}

Selectors that are not valid keywords

Some selectors in tailwind contain forward slashes. Since keyword literals in clojure cannot contain backslashes, use a string instead:

(garden.core/css [[:.btn (garden-mower.core/attributes css ".xl:w-1/5")]])

Caveat

The CSS output is not optimised and sometimes has too much whitespace. There is room for improvement.

What now?

Try using https://github.com/tristanstraub/docker-tailwindcss to generate custom tailwindcss css files, which can be fed into garden-mower.

Modify resources/public/index.html to include the newly created css files:

  • tailwind-base.css
  • tailwind-component.css

and remove:

  • tailwind.min.css

Use tailwind-utilities.css with garden-mower to generate your CSS, but don’t include it in index.html.

Hacking

The tests can be run with:

clj -A:test

License

https://opensource.org/licenses/MIT

About

Clojure based CSS preprocessor to emulate @apply from PostCSS and output noprompt/garden config

License:MIT License


Languages

Language:Clojure 96.4%Language:Dockerfile 1.4%Language:Shell 1.3%Language:CSS 0.9%