hasmin
CSS Minifier
https://github.com/contivero/hasmin#readme
Version on this page: | 1.0.1@rev:2 |
LTS Haskell 11.22: | 1.0.2 |
Stackage Nightly 2018-03-12: | 1.0.1@rev:3 |
Latest on Hackage: | 1.0.3@rev:1 |
hasmin-1.0.1@sha256:b3b484d0511e0bce57618e4b5d6bd66a91ea0d4f07564a5c0e6492b0e1445b41,6813
Module documentation for 1.0.1
- Hasmin
- Hasmin.Class
- Hasmin.Config
- Hasmin.Parser
- Hasmin.Types
- Hasmin.Types.BgSize
- Hasmin.Types.Color
- Hasmin.Types.Declaration
- Hasmin.Types.Dimension
- Hasmin.Types.FilterFunction
- Hasmin.Types.Numeric
- Hasmin.Types.Position
- Hasmin.Types.RepeatStyle
- Hasmin.Types.String
- Hasmin.Types.Stylesheet
- Hasmin.Types.TimingFunction
- Hasmin.Types.TransformFunction
- Hasmin.Types.Value
- Hasmin.Utils
Hasmin - A Haskell CSS Minifier
Aside from the usual techniques (e.g. whitespace removal, color minification, etc.), the idea was to explore new possibilities, by implementing things other minifiers weren’t doing, or they were, but not taking full advantage of.
Also, the minifier implements some techniques that do nothing for minified sizes, but attempt to improve post-compression sizes (at least when using DEFLATE, i.e. gzip).
For a list of techniques, see the wiki. To use it as a library, see below.
Building & Installing
Stack
The easiest and prefered way is using stack. Clone the repo, then:
$ cd path/to/hasmin/repo
$ stack build
After that, you can install it with stack install
(installs by default to ~/.local/bin
).
If you’d rather just try it out, use stack exec hasmin
(keep in mind it has
a slight additional delay at the beginning when run this way).
Cabal
Alternatively, you can use cabal:
$ cd path/to/hasmin/repo
$ cabal update # Make sure to have the latest package list
$ cabal sandbox init # Initialise a sandbox
$ cabal install --only-dependencies # Install dependencies into the sandbox
$ cabal build # Build hasmin inside the sandbox
Minifier Usage
Hasmin expects a path to the CSS file, and outputs the minified result to
stdout. Say you have a sheet.css
and want to minify it, and save it as
sheet.min.css
. Then, run:
$ hasmin sheet.css > sheet.min.css
Every technique is enabled by default, except for:
- Escaped character conversions (e.g. converting
\2714
into✔
, enabled with--convert-escaped-characters
). - Dimension minifications (e.g. converting
12px
to9pt
, enabled with--dimension-min
, or just-d
). - Lexicographical sorting of declarations (enabled with
--sort-declarations
).
The first two are disabled mainly because they are—on average, not always—detrimental for DEFLATE compression. As for declaration sorting, whether it benefits or hurts compression rates is very stylesheet-dependent, and the current implementation is quite naive, hence unsafe.
When something needs to be disabled, use the appropriate flag. Not every technique can be toggled, but if there is any one in particular that you need to and can’t, open an issue about it.
Note: there is a problem in Windows when using the
--convert-escaped-characters
flag to enable the conversion of escaped
characters. A workaround is changing the code page, which can be done by running
chcp 65001
in the terminal (whether cmd, or cygwin).
Library
The preferable way to use Hasmin as a library is to import Hasmin
; a usage
example can be seen in the module’s documentation.
That is currently the only module that is sure to abide by
PVP. Most other exposed modules are so because tests
need it, and thus definitions there may be changed anytime. In case something
internal is needed though, feel free to open an issue about it.
Zopfli Integration
Hasmin uses bindings to Google’s Zopfli library, allowing the possibility to compress the result.
Since the output is a gzip file, it can be used for the web. It tipically produces files 3~8% smaller than zlib, at the cost of being around 80 times slower, so it is only a good idea if you don’t need compression on the fly.
Zopfli is released under the Apache License, Version 2.0.
Changes
Changelog
This project adheres to PVP.
1.0.1
Added
-
Removing
all
andall and
in media query lists, sinceall
is assumed when not present. In other words, the following rules are equivalent:@media all {/*..*/} @media {/*..*/}
and so are these:
@media all and (min-width: 500px) {/*..*/} @media (min-width: 500px) {/*..*/}
Note that this applies to media query lists in at-import rules too.
-
Replacing the
url()
notation for a <string> when used in the@import
rule. -
Four pseudoelement minifications:
:nth-of-type(1)
–>:first-of-type
.:nth-last-of-type(1)
–>:last-of-type
.:nth-child(1)
–>:first-child
.:nth-last-child(1)
–>:last-child
.
-
[class~=x]
to.x
minification.
Improved
- <position> parser, making hasmin around four times faster on stylesheets with many <position> values.
Fixed
-
Length’s Eq instance, which would equate lengths with the same numerical value when one had an absolute unit, and the other relative, e.g. 1in and 1em.
-
Escaped character conversion: converting characters would crash the program when:
- The escaped character had more than 6 hexadecimal digits (6 is the specs
maximum); E.g.
\aaaaaaa
. - The escaped character’s numerical representation was out of the unicode range.
This is no longer the case.
- The escaped character had more than 6 hexadecimal digits (6 is the specs
maximum); E.g.
1.0
Added
-
border-color-*
,border-width-*
andborder-style-*
longhands are now replaced by their shorthand, when the four corresponding longhands are present in a rule. -
Style rules merging: merges pairs of rules that either have all the same selectors, or all the same declarations. For it to be safe, it only does so whenever two conditions don’t meet:
- There is a rule in between with the same specificity
- This rule has a declaration that “clashes” (interferes) with one of the declarations of the rules to be merged.
By default it is enabled, but it can be disabled with
--no-rule-merging
(or using aConfig
withMergeRulesOn
).
Changed
- Replaced
--no-property-sorting
for--sort-properties
. Now Hasmin doesn’t sort properties by default; sorting declarations became opt-in rather than opt-out. This is because:- Whether lexicographical sorting of properties aids compression varies a lot from stylesheet to stylesheet, for some files it helps, for others it hurts.
- The current implementation doesn’t take into account all the possible interactions between properties, making it unsafe.
Fixed
- Fixed non-exhaustive pattern bug introduced in 0.3.3
- Fixed parser choking with rules that contained a semicolon but no
declarations, e.g.
div { ; }
.
0.3.3 [YANKED]
This version introduced a non-exhaustive pattern bug. Don’t use it.
Added
Added a simple merging of adjacent media queries (@media
rules), e.g.:
@media all and (min-width: 24rem) {
a { font-size: 1.2rem; }
}
@media all and (min-width: 24rem) {
b { padding-left: .25rem; padding-right: .25rem; }
}
Gets merged into into:
@media all and (min-width: 24rem) {
a { font-size: 1.2rem; }
b { padding-left: .25rem; padding-right: .25rem; }
}
0.3.2.4
- Relaxed doctest upper bound once more, see stackage issue 2663.
0.3.2.3
- Relaxed doctest upper bound.
0.3.2.2
- Relaxed criterion upper bound.
0.3.2.1
- Relaxed optparse-applicative upper bound.
0.3.2
- Fixed some dimensions minifying incorrectly.
- Fixed some Eq instances.
- <An+B> values data type modified to disallow invalid values. This makes the data type safer, also simplifying the Quickcheck Arbitrary instance.
- Improved test coverage.
0.3.1.3
- Added support for
@supports
rules, and a slight minification for them: it removes adjacent negations, i.e.: @supports not (not …) gets turn into @supports …. - Fixed a small bug with
:lang()
where spaces before the right parenthesis weren’t being removed. - Improved test coverage.
0.3.0.1
Initial release