Coder Social home page Coder Social logo

sass4clj's Introduction

Sass4clj

Clojars Project Build Status AppVeyor

Clojure wrapper for jsass JNA wrapper for Libsass. This repository also contains Boot and Leiningen tasks.

For parallel Less library check less4clj

ATTENTION: libsass (the C library) and the JNA wrapper library jsass are deprecated. Consider using Dart Sass if you do not need to read SCSS files from the Java classpath. You can integrate Dart Sass process with Shadow CLJS.

Both sass4clj still works and will receive bug fixes, but the difference between libsass and dart-sass will continue growing.

Some ideas if you need to read files from the classpath or jar files:

  • It might be possible to extend dart-sass through Importer API
  • Extract files from the jar files in a script before calling dart-sass compile (for example, using clj and unzip)

Features

  • Jsass features
    • Requires Java 1.8
    • Linux & Windows builds are automatically tested
    • (Doesn't work on Alpine based Docker images)
  • Load imports directly from Java classpath (e.g. Webjars)
    • Add dependency [org.webjars.bower/bootstrap "4.0.0-alpha"] to use Bootstrap
  • Assumes that files starting with _ are partial files and should not be compiled into CSS files.
  • Non feature: compilation warnings are reported by libsass/jsass directly to stdout, and aren't accessible from sass4clj API.

Boot Clojars Project

  • Provides the sass task (deraen.boot-sass/sass)
  • Select main files using inputs option
  • or, for each .sass or .scss file not starting with _ in the fileset creates equivalent .css file.
  • Check boot sass --help for task options.

Leiningen Clojars Project

  • Provides the sass4clj task
  • Select main files using inputs option
  • or, for each .sass or .scss file not starting with _ in source-dirs creates equivalent .css file.
  • Check lein help sass4clj for options.

Clj

Test in the repository:

clj -m sass4clj.main --source-paths test-resources

Check clj -m sass4clj.main --help for options.

Import load order

Loading order for @import "{name}"; on file at {path}

  1. Local file at {path}/{name}.sass or {path}/{name}.scss
  2. Local files on other source-paths, {source-path}/{name}.ext
  3. Classpath resource (io/resource "{name}.ext")
  4. Classpath resource (io/resource "{path}/{name}.ext")
  5. Webjar asset
    • Resource META-INF/resources/webjars/{package}/{version}/{path} can be referred using {package}/{path}
    • For example @import "bootstrap/scss/bootstrap.scss"; will import META-INF/resources/webjars/bootstrap/4.0.0-alpha/scss/bootstrap.scss

FAQ

Shadow-cljs integration

If you want to combine CLJS compilation with Shadow CLJS and Sass compilation, you can create your function which starts both watches and run this using shadow-cljs clj-run task.

(ns app.shadow
  (:require [shadow.cljs.devtools.api :as shadow]
            [sass4clj.api :as sass]
            [clojure.edn :as edn]))

(defn watch
  {:shadow/requires-server true}
  [& _args]
  ;; Sass compilation probably starts faster.
  ;; Both watches keep running until ctrl-c.
  (sass/start (-> (edn/read-string (slurp "sass4clj.edn"))
                  (assoc :target-path "target/dev/public/css")))
  (shadow/watch :app))

The configuration file, sass4clj.edn, is also supported by sass4clj.main namespace. You could use that to compile CSS for your production build instead of the leiningen plugin.

And start the watch with (or with whatever tool you are using):

lein run -m shadow.cljs.devtools.cli clj-run app.shadow/watch

You need to ensure that the classpath used by shadow-cljs contains deraen/sass4clj and any packages where you are importing sass files from.

Log configuration

If you don't have any slf4j implementations, you will see a warning:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

To disable this, add a no operation logger to your project. As this is only required on the build phase, you can use :scope "test" so that the dependency is not transitive and is not included in Uberjar. Alternatively, you can add this dependency to your Leiningen dev profile.

[org.slf4j/slf4j-nop "1.7.13" :scope "test"]

License

Copyright © 2014-2021 Juho Teperi

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

sass4clj's People

Contributors

bdollard avatar danielcompton avatar deraen avatar eerohele avatar pinqvin avatar puredanger avatar tessellator avatar viesti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

sass4clj's Issues

Use Jsass 5

There are some API changes and just fixing the renamed calls didn't seem to be enough.

Boot sass task does not respect target env

I have the following task.
It compiles fine, but keeps outputting files to target.
I want it to compile into compiled_css instead.

Main reason, is I would like to run SASS compilation on its own.

(set-env!
  :source-paths #{"src/cljs" "test/clj"}
  :resource-paths #{"src/clj" "src/cljc" "resources"}
  :dependencies '[
                  [adzerk/boot-cljs "1.7.228-1" :scope "test"]
                  [adzerk/boot-cljs-repl "0.3.0" :scope "test"]
                  [adzerk/boot-reload "0.4.5" :scope "test"]
                  [pandeiro/boot-http "0.7.1-SNAPSHOT" :scope "test"]
                  [crisptrutski/boot-cljs-test "0.2.2-SNAPSHOT" :scope "test"]
                  [org.clojure/clojure "1.7.0"]
                  [org.clojure/clojurescript "1.7.228"]
                  [adzerk/boot-test "1.1.1" :scope "test"]
                  [com.cemerick/piggieback "0.2.1" :scope "test"]
                  [weasel "0.7.0" :scope "test"]
                  [org.clojure/tools.nrepl "0.2.12" :scope "test"]
                  [org.clojure/core.async "0.2.374"
                   :exclusions [org.clojure/tools.reader]]
                  [sablono "0.4.0"]
                  [devcards "0.2.1-5"]
                  [deraen/boot-sass "0.2.1"]
                  [org.omcljs/om "1.0.0-alpha32" :exclusions [org.clojure/clojure]]])

(require
  '[adzerk.boot-cljs :refer [cljs]]
  '[adzerk.boot-cljs-repl :refer [cljs-repl start-repl repl-env]]
  '[adzerk.boot-reload :refer [reload]]
  '[adzerk.boot-test :refer [test]]
  '[deraen.boot-sass :refer [sass]]
  '[pandeiro.boot-http :refer [serve]])

(task-options!
  pom {:project     'torca
       :version     "0.1.0-SNAPSHOT"
       :description "TORCA CLJS Front-End"
       :license     {"The MIT License (MIT)" "http://opensource.org/licenses/mit-license.php"}}
  aot {:namespace #{'backend.main}}
  jar {:main 'backend.main}
  cljs {:source-map true})

(deftask dev
         "Start the dev env..."
         [s speak bool "Notify when build is done"
          p port PORT int "Port for web server"]
         (comp
           (watch)
           (reload :on-jsload 'torca.core/reload)
           (cljs-repl)
           (cljs :compiler-options {:devcards true})
           (serve :port port, :dir "target")
           (target)
           (if speak (boot.task.built-in/speak) identity)))

(deftask styles []
         "Compile Styles"
         (set-env! :source-paths #{"sass"}
                   :target "compiled_css")
        (comp (watch)
              (speak)
              (sass)
              (target)))
(deftask run-tests []
         (test))

(deftask autotest []
         (comp
           (watch)
           (run-tests)))

(deftask package
         "Build the package"
         []
         (comp
           (cljs :compiler-options {:devcards false :optimizations :advanced})
           (target)))

Problem with M1 chip Mac

Hey!

I've been migrating to the new Mac on M1 chip and I am getting this error:
Screenshot 2022-02-15 at 15 38 28

Maybe someone has already stumbled upon something similar?

Thanks!

Problem with relative imports

Tried this:

  1. Download contents of https://github.com/twbs/bootstrap-sass/tree/master/assets/stylesheets.
  2. Copy to /css/ in a boot based project using https://github.com/Deraen/boot-sass.
  3. Add "import '@boostrap';" to app.scss.
  4. Run "boot sass".

Results in this output:

Compiling {sass}... 77 changed files.
Error: file to import not found or unreadable: bootstrap/variables
       Current dir: 
        on line 8 of bootstrap
>> @import "bootstrap/variables";
   --------^

Moving the bootstrap directory up one level to the root of the resource path gets me this:

Compiling {sass}... 77 changed files.
Error: file to import not found or unreadable: mixins/hide-text
       Current dir: 
        on line 5 of mixins
>> @import "mixins/hide-text";
   --------^

So it gets passed the variables, but isn't able to locate the mixins sub-directory. It seems like it expects all imports to be relative to the root of the resource path.

It tries to compile anything it can lay its hands on

If I for example have sass files that import mixins from a library in npm and I pull node_modules into fileset:

e.g:

(deftask add-node-modules []
  (with-pre-wrap fileset
(let [nm (clojure.java.io/file "node_modules")]
  (when-not (and (.exists nm) (.isDirectory nm))
    (dosh "npm" "install"))
  (-> fileset
    (add-resource (clojure.java.io/file ".") :include #{#"^node_modules/"})
    commit!))))

thanks @anmonteiro

boot-sass tries to compile things in node_modules. Definitely not something desired

Automatic run

Is there a way to automatically run this task when compiling the uberjar? I tried both hooks and prep-tasks and I couldn't get it to work.

Specifying dependencies in POM for Boot plugin

The Boot plugin dynamically adds the sass4clj dependency at runtime, when the plugin is called.

(update-in [:dependencies] into deps)

This is a problem in CI, because my dependencies have already been downloaded before I run my SASS build. Is it possible to add the sass4clj dependency to the POM for the Boot and Leiningen plugins? I know version handling stuff like this can be tricky, so I wanted to check if my idea made sense.

:dependencies [])

Attach to existing JVM?

Hi there,

first of all thank you for sass4clj - it's a pleasure to see it working!

One downside vs. my previous setup (ruby-sass) is the RAM penalty of having a JVM around just for this (500mb in my machine).

I already have JVMs for Clojure(Script) processes, would it be possible to hack one's project.clj so whenever I run lein figwheel, the sass4clj library does its thing too?

I realise that this might be more of a generic leiningen question, but still I feel this would be a very commonly derisable thing, worth documenting.

Thoughts?

Cheers - Victor

In `api/build`, return status or throw when errors are encountered.

Hi, thanks for maintaining this -- it's been very helpful to provide a smooth development experience!

I was wondering if you would considering returning a status report when errors are encountered. I'm calling sass4clj.api/build, and it swallows any exceptions thrown during the compilation. I'd like to plug in my own error reporting.

I'm working around this by using with-out-str and parsing the resulting text but surely that's a hack :)

I'm happy to submit a PR for this.

Option to select input files

Related #17

Currently sass4clj compiles any non-partial files (i.e. not starting with _) in source-paths. It could be useful to select input files using option in some cases, like if the source-path contains some Sass libraries which include non-partial files.

Things to consider:

  • API & CLI option:
    • (build {:inputs ["foo.scss" "bar.scss"]})
    • clj -Asass -i foo.scss -i bar.scss
    • List of paths relative to source-paths? or relative to current directory?
  • Boot option
    • No source-paths, source-paths is the fileset.
    • Input paths has to be relative to fileset.
  • Lein option
  • Implement the same option for https://github.com/Deraen/less4clj/

Feature request: support for shadow-cljs

I was trying to find an easy solution for SASS-like syntax with ClojureScript for shadow-cljs but have not found it yet, but I think this could be fire if you could make your lib work with shadow-cljs. Thanks for the contribution though!

SLF4J whining

Running boot sass target -d target shows some WTF warning. The compilation still works though.

Compiling {sass}... 1 changed files.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Writing target dir(s)...

With boot -vv:

Adding stylesheets/style.scss...
Adding funfin/core.cljs...
Adding main.cljs.edn...
Adding index.html...
Released java.util.concurrent.Semaphore@1757cd72[Permits = 1]...
Compiling {sass}... 1 changed files.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
found META-INF/resources/webjars/bootstrap/4.0.0-alpha.2/scss/bootstrap.scss at webjars
Found jar:file:/Users/be9/.m2/repository/org/webjars/bootstrap/4.0.0-alpha.2/bootstrap-4.0.0-alpha.2.jar!/META-INF/resources/webjars/bootstrap/4.0.0-alpha.2/scss/bootstrap.scss from resources

Inlining CSS doesn't work

I'm using @import "magnific-popup/dist/magnific-popup"; and I'm expecting the .css to be loaded.

This works as I expect:

(sass4clj.core/find-webjars
  {:asset-map (sass4clj.webjars/asset-map)}
  "magnific-popup/dist/magnific-popup.css")

So I'm not sure why the @import form doesn't work. But I'd expect this code to generate that string from my import.


Oh I should mention, I'm using boot-sass

This may be a boot-sass bug, this works:

(sass4clj.core/sass-compile
  "@import \"magnific-popup/dist/magnific-popup\""
  {})

as does this:

(sass4clj.core/sass-compile-to-file
  (clojure.java.io/file "src/scss/public/main.scss")
  (clojure.java.io/file "/tmp/output.css")
  {})

File watching (sass4clj auto) only works for top-level stylesheets?

Hi there,

our SCSS structure is the following:

image

Where sass/themes/dark.scss and sass/themes/lite.scss are the "top-level" stylesheets, everything else being dependencies of them.

This is reflected in our project.clj:

:source-paths ["sass/themes"]

This setup compiles correctly.

The problem is, if I edit any stylesheet that is not a top-level one, sass4clj auto will not detect the changes. I'd have to touch them manually (or with some script) for a recompile to be triggered.

Is this a bug in the auto implementation? Or maybe is our scss structure improvable?

Cheers - Victor

sass file globbing?

I'd love to be able to use this, it looks like it would be great to be able to watch and sass with boot instead of having a ruby setup running in parallel in the project just for stylesheets.

The only thing holding me back is not being able to glob :(

https://github.com/chriseppstein/sass-globbing

Maybe I misunderstand, but there's already a custom @import setup in this project, so it wouldn't be crazy hard to add globbing?

Source-maps

Jsass or libsass does some magic so just setting main.css.map as sourceMapFile causes bad values for sourceMappingUrl.

/*# sourceMappingURL=../../2m7mhu/css/main.css.map */
/*# sourceMappingURL=../../../../../../../../../../Source/saapas/main.css.map */

Troubleshooting source maps?

Not sure if this is an issue in sass4clj or some other configuration, but I'm having trouble figuring why the source maps don't work.

  • I can verify that the generated CSS file contains as the last line /*# sourceMappingURL=main.css.map */
  • I can verify that the browser requests the file (I see it in my Pedestal logs)
  • I can verify that the source map file is accessible via the web server (I can download it via the browser)
  • I can verify that the source map is valid JSON
  • The browser seems to be able to pick up bits of SCSS that come from Bootstrap SCSS, but not a lot, not seemingly correct, and none of my actual code. In the devtools I just see the main.css file as the reference file. I tried with Chrome, Firefox, Safari on macOS, all same results.

Any pointers on how to troubleshoot this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.