Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Inline CSS imports, preserving media queries
- Loading branch information
Showing
7 changed files
with
108 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
(ns optimus.optimizations.inline-css-imports | ||
(:require [clojure.string :as str] | ||
[optimus.assets.load-css :refer [update-css-references external-url?]])) | ||
|
||
(def import-re #"@import (?:url)?[('\"]{1,2}([^']+?)[)'\"]{1,2} ?([^;]*);") | ||
|
||
(defn- by-path [path assets] | ||
(first (filter #(= path (:path %)) assets))) | ||
|
||
(defn- inline-import-match [asset assets [match path media]] | ||
(if (external-url? path) | ||
(throw (Exception. "Import of external URL http://external.css in /main.css is strongly adviced against. It's a performance killer. In fact, there's no option to allow this. Use a link in your HTML instead. Open an issue if you really, really need it.")) | ||
(let [contents (:contents (by-path path assets))] | ||
(if (empty? media) | ||
contents | ||
(str "@media " media " { " contents " }"))))) | ||
|
||
(defn- is-css [#^String path] | ||
(.endsWith path ".css")) | ||
|
||
(defn- inline-css-imports-1 [asset assets] | ||
(if-not (is-css (:path asset)) | ||
asset | ||
(-> asset | ||
(assoc :contents (str/replace (:contents asset) import-re (partial inline-import-match asset assets))) | ||
(update-css-references)))) | ||
|
||
(defn inline-css-imports [assets] | ||
(map #(inline-css-imports-1 % assets) assets)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
(ns optimus.optimizations.inline-css-imports-test | ||
(:require [optimus.optimizations.inline-css-imports :refer :all] | ||
[midje.sweet :refer :all])) | ||
|
||
(fact | ||
"CSS imports are inlined from the asset list, and removed from the | ||
references." | ||
|
||
(inline-css-imports [{:path "/main.css" :contents "@import '/other.css'; #id {}" :references #{"/other.css"}} | ||
{:path "/other.css" :contents ".class {}"}]) | ||
=> [{:path "/main.css" :contents ".class {} #id {}"} | ||
{:path "/other.css" :contents ".class {}"}]) | ||
|
||
(fact | ||
"CSS imports can take many forms." | ||
|
||
(let [assets [{:path "/main.css" :contents "@import '/other.css';"} | ||
{:path "/other.css" :contents ".class {}"}] | ||
expected [{:path "/main.css" :contents ".class {}"} | ||
{:path "/other.css" :contents ".class {}"}]] | ||
|
||
(inline-css-imports (assoc-in assets [0 :contents] "@import '/other.css';")) => expected | ||
(inline-css-imports (assoc-in assets [0 :contents] "@import \"/other.css\";")) => expected | ||
(inline-css-imports (assoc-in assets [0 :contents] "@import url('/other.css');")) => expected | ||
(inline-css-imports (assoc-in assets [0 :contents] "@import url(\"/other.css\");")) => expected | ||
(inline-css-imports (assoc-in assets [0 :contents] "@import url(/other.css);")) => expected)) | ||
|
||
(fact | ||
"Media queries are conserved." | ||
|
||
(inline-css-imports [{:path "/main.css" :contents "@import '/other.css' screen and (orientation:landscape);"} | ||
{:path "/other.css" :contents ".class {}"}]) | ||
=> [{:path "/main.css" :contents "@media screen and (orientation:landscape) { .class {} }"} | ||
{:path "/other.css" :contents ".class {}"}]) | ||
|
||
(fact | ||
"External URLs for @imports are not tolerated. It's disastrous for frontend performance." | ||
|
||
(inline-css-imports [{:path "/main.css" :contents "@import 'http://external.css';"}]) | ||
=> (throws Exception "Import of external URL http://external.css in /main.css is strongly adviced against. It's a performance killer. In fact, there's no option to allow this. Use a link in your HTML instead. Open an issue if you really, really need it.")) | ||
|
||
(fact | ||
"Non-CSS assets are left to their own devices." | ||
|
||
(inline-css-imports [{:path "/main.js" :contents "@import '/other.css';"}]) | ||
=> [{:path "/main.js" :contents "@import '/other.css';"}]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters