scissors 0.6.7

sCiSSors Build Status Pub Package

Smarter resources for Angular apps: CSS pruning, bidirectional layouts, SVG & PNG optimization, Sass compilation, locale permutations, automatic reload.

Disclaimer: This is not an official Google product.

Features #

All of the following features are lazy (only triggered when needed) and most of them are disabled or optimized for speed with pub serve in debug mode. (note: may need pub serve --force-poll on MacOS X)

  • CSS pruning for Angular (see example/angular1, example/angular2):

    • Finds which .css rules are not used by Angular templates and removes them.
    • Supports ng-class and class with programmatic interpolated fragments (e.g. class="some-{{fragmented}}-class and-some-normal-class", ng-class="{'some-class': isSome}").
    • Disabled by default in debug mode.
  • CSS mirroring / bidirectionalization that works with Angular2's transformer:

    • Uses CSSJanus to produce a single CSS file that supports both RTL & LTR layouts!

    • Given foo { color: blue; float: left }, it generates:

      foo { color: blue; }
      :host-context([dir="ltr"]) foo { float: left }
      :host-context([dir="rtl"]) foo { float: right }

      So you just need the supporting code in your main.dart to support bidirectional layouts (see example/mirroring):

      document.body.dir = Bidi.isRtlLanguage(Intl.getCurrentLocale()) ? 'rtl' : 'ltr';
  • Sass compilation:

    • Compiles *.sass and *.scss files with sassc, the lightning-fast C++ port of Ruby Sass.
    • Rebuilds .css files whenever their .sass sources are modified.
  • Image inlining:

    • Expands inline-image calls in CSS files into data URI links, like Compass does.
    • By default in debug mode, links to images instead of inlining them.
  • PNG optimization:

    • Calls pngcrush to remove all metadata that is useless for rendering.
    • Disabled by default in debug mode.
  • SVG optimization:

    • Removes comments, doctypes, unused namespaces.
    • Disabled by default in debug mode.
  • Locale-specific permutations generation (Optional, see example/permutations):

    • Generates one .js per locale (e.g. main_en.js, main_fr.js...) with the deferred parts needed for that locale, which speeds up load time.
    • Supports deferred messages and deferred LTR/RTL template caches.
    • Optionally optimizes the resulting .js files with the Closure Compiler.
  • Automatic reload support (Optional): zero-turnaround for Dart!

  • Experimental static checker that detects unawaited futures (a common cause of sneaky bugs in async code):

Usage #

Defaults vs. debug vs. release #

sCiSSors is fine-tuned for fast build in debug mode (default for pub serve) and small code size in release mode (default for pub build).

Its behaviour can be fully customized through transformer settings in pubspec.yaml. For instance, to enable PNG optimizations in all modes, and enable SVG optimizations in debug only:

- scissors:
    optimizePng: true
        optimizeSvg: false
        optimizeSvg: true

Prerequisites #

If you checked out scissors's sources, you can run . ./script/ to get all the required dependencies, and skip the rest of this section :-)

Installing CSSJanus #

You'll need a local install of CSSJanus for CSS mirroring.

Note that this transformer uses Google's original, not its .js port (, which might work if packaged as a binary that consumes css from stdin and outputs mirrored css on stdout).

To install CSSJanus, run the following command in a console (ensure you have something like export PATH=~/bin:$PATH in your ~/.profile or ~/.bashrc):

  mkdir ~/bin
  curl > ~/bin/
  chmod +x ~/bin/

Other deps: SassC, pngcrush... #

These packages are quite standard, you can get them with brew install on MacOS X and with sudo apt-get install on Ubuntu:

  • sassc
  • pngcrush

Using the scissors transformer

The default transformer will build Sass files in a blink of an eye and will optimize CSS, PNG and SVG assets in release mode (pub build).

Please only setup sCiSSors's transformer on projects you know respect sCiSSors' conventions and limitations (see below).

Examples: see example/angular1, example/angular2).


    scissors: ^0.6.0
  - scissors

Valid settings:

  • pruneCss (boolean): false by default
  • imageInlining: default is inlineInlinedImages
    • inlineAllUrls: treats url as inline-image
    • inlineInlinedImages: simply honours inline-image
    • linkInlinedImages: replaces inline-image by url
    • disablePass: leaves inline-image untouched
  • optimizePng (boolean): by default, true in release only
  • optimizeSvg (boolean): by default, true in release only
  • sasscPath: default is sassc
  • compiledCssExtension: default is append
    • append: append the .css extension to the SASS / SCSS file name: foo.scss will be compiled to foo.scss.css.
    • replace: replace the SASS / SCSS file extension by .css: foo.scss will be compiled to foo.css.
  • pngCrushPath: default is pngcrush
  • bidiCss (boolean): default is false (note that this is true by default in the scissors/css_mirroring_transformer, see below)
  • cssJanusPath: by default, see prerequisites

Limitations #

  • Assumes if foo.html exists, foo.css is only used from there (conventions matter). This means sCiSSors should be disabled or used with caution when using Angular2 with ViewEncapsulation.None (see section below).
  • Very limited support of CSS rules (naive and hopefully pessimistic matching),
  • Bails out of pruning as soon as it doesn't recognize the (map literal) syntax of an ng-class (or if the map has non-string-literal keys),
  • Does not detect direct / handle DOM manipulations done in .dart companion files yet (html:Element.classes, etc).
  • No support for XML namespaces in CSS3 attribute selectors.
  • No CSS renaming yet (just pruning for now),
  • No Polymer.dart support yet.

Style Isolation in Angular #

Angular(1,2) provide the following strategies:

  • Shadow DOM (default in AngularDart 1.x), implemented by ShadowDomComponentFactory in AngularDart 1.x and ViewEncapsulation.Native in Angular2
  • Shadow DOM emulation with "transclusion" (default in Angular2) implemented by TranscludingComponentFactory in AngularDart 1.x and ViewEncapsulation.Emulated in Angular2
  • Unscoped / no Shadow DOM, implemented by ViewEncapsulation.None in Angular2

The first two strategies (Shadow DOM & its transcluded emulation) provide strict encapsulation of style at the component level: styles defined in a component do not leak to any of its sub-components or parent components. This is the assumption by which sCiSSors lives, so you're safe with it.

The last "unscoped" strategy means there's no file- or component-local way of deciding if a style could be used elsewhere. You should not use sCiSSors on packages / projects with that strategy.

Using scissors/css_mirroring_transformer

See BidirectionalCss for more details.

Example: see example/mirroring.


  - scissors/css_mirroring_transformer

Valid settings:

  • bidiCss (boolean): true by default (Note: this is not the same default as in the scissors transformer)
  • originalCssDirection (ltr or rtl): ltr by default, defines the direction of input css.
  • cssJanusPath: by default.

Limitations #

  • The standalone scissors/css_mirroring_transformer transformer only consumes CSS files. If you need Sass support, please use the scissors transformer with bidiCss: true.
  • Does not handle directives like @keyframes and @page.

Using scissors/permutations_transformer

Example: see example/permutations.


  - scissors/permutations_transformer

Valid settings:

  • generatePermutations: true by default
  • ltrImport and rtlImport: unset by default. If you're deferred-loading LTR/RTL-specific template caches, these settings should take the alias you're importing them under. See example/permutations for a concrete example.
  • expectedPartCounts (map of .dart.js artifact to number of expected parts): unset by default. For instance: { web/main.dart.js: 3 }.
  • stripSourceMaps: false by default. Removes the sourceMappingURL links from all generated .js files, to avoid provoking 404s in production when sourcemaps aren't served (relevant only when the $dart2js transformer has setting sourceMaps: true).
  • reoptimizePermutations: false by default. Whether to optimize permutations with the Closure Compiler.
  • closureCompilerJarPath: compiler.jar by default
  • javaPath: java by default.

Using scissors/reloader/transformer

This provides an amazing development turnaround experience, whether you're using the other sCiSSors transformers or not.

With pub serve --force-poll, as soon as you save an asset (say, foo.scss) and it finished building the dependent assets (say, foo.scss.css), the app will reload. That's typically before you even have the time to tab-switch to the browser (+ no need to Ctrl+R).

The transformer ensures the automatic reload logic is removed in release builds (pub build), without interfering with source maps.

Example: see example/permutations.

Just edit pubspec.yaml (note: it's in dev_dependencies, not dependencies):

  - scissors/reloader/transformer

And edit main.dart:

  import 'package:scissors/reloader/reloader.dart';

  main() {

Valid settings:

  • serveTimestamps (boolean): by default, true in debug only
  • removeReloader (boolean): by default, true in release only

Using scissors/src/checker/transformer to detect unawaited futures

See UnawaitedFutures for more details.

Keep in mind that this transformer is very experimental, and slow. It aims to complement Dart's new strong-mode analyzer with more static checks, some of which could eventually graduate to the analyzer itself.



  - scissors/src/checker/transformer:
    unawaitedFutures: error

Valid settings:

  • unawaitedFutures (ignore, warning or error): warning by default

Development #

For things to do, please see issues.

To setup dependencies, please run:

. scripts/

This will download some executables used by Scissors and will export the following environment vars


Please run the following command to test your changes + reformat + analyze sources:


Please never force-push to master: use git revert to revert changes.

Current development tree #


0.6.7 (2016-12-05) #

Features #

  • Added Compass polyfills support for css-filters, css-placeholder, inline-block

0.6.7 (2016-11-08) #

Features #

  • scissors-sassc runner now supports workers (combo of --persistent_worker flag, @@args_file argument and proto-based standard input / output communication protocol with Bazel).

0.6.5 (2016-09-16) #

Bugfixes #

  • Made image inlining more robust (#53).
  • Fix sass aggregate transformer (skip non-scss files)

Features #

  • New dart image inliner transformer + CLI

0.6.4 (2016-06-30) #

Bugfixes #

  • Fix skipping of image inlining for unaffected files (see issue #53)

0.6.3 (2016-06-14) #

Bugfixes #

  • Fixed bidirectionalization of @media rules.
  • Fixed race condition + some embarrassing typos in Sass settings (caused some includes to not be resolved)
  • Merged SassC & ImageInlining transformers to avoid some errors "Both {SassC on ..., ImageInlining on ...} emitted the same file."
  • Switched hidden onlyCompileOutOfDateSass option's default to false (caused pub to hang when used in combination with some other transformers)

Features #

  • Removed experimental scissors/src/checker/transformer, which feature was integrated to the Dart Linter package from version 0.1.19.
  • Switched some defaults around: pruneCss: false, imageInlining: inlineInlinedImages

0.6.2 (2016-06-02) #

Features #

  • Added experimental scissors/src/checker/transformer that detects unawaited futures. These extra static checks are slow, but prevent accidental fire-and-forget of futures within async method bodies.

0.6.1 (2016-05-26) #

Bugfixes #

  • Fixed Bidi CSS which had been wrongly simplified (issue #43)

0.6.0 (2016-03-16) #

Bugfixes #

0.5.0 (2016-03-14) #

Features #

  • Added a sourcemap-stripping transformer, usable standalone or in scissors/permutations_transformer with stripSourceMaps: true (relevant only when the $dart2js transformer has sourceMaps: true)
  • Added Compass polyfills for prefix-usage, browsers, browser-prefixes, compact (makes lots of Compass mixins to work well)

Bugfixes #

  • CSS pruning:

    • Handle Angular2 [] and [] syntaxes in CSS pruning (issues #30 & #31)
    • Skip :host rules (issue #29)
  • Bidirectional CSS:

    • Fix Css mirroring to handle multiple selectors in RuleSet
    • Transformer is now an aggregate (more solid interaction with other transformers)
  • Follow symlinks in path resolution logic.

  • scissors-sassc now automatically finds compass stylesheets

0.4.3 (2016-03-04) #

Features #

  • Introduced scissors-sassc binary that wraps sassc and adds inline-image support.

0.4.2 (2016-03-03) #

Bugfixes #

  • Fixed "Bad state: Setting sasscArgs wasn't read yet." (issue #27).

0.4.1 (2016-01-19) #

Bugfixes #

  • Simplified bidirectional CSS output (issue #23): now produces smaller code.

0.4.0 (2016-01-19) #

Features #

  • Added scissors/css_mirroring_transformer that makes CSS files to support bidirectional layouts (uses CSSJanus. Given foo { color: blue; float: left }, it generates:

      foo { color: blue }
      :host-context([dir="ltr"]) foo { float: left }
      :host-context([dir="rtl"]) foo { float: right }

    So you just need the supporting code in your main.dart to support bidirectional layouts (see example/mirroring):

      document.body.dir = Bidi.isRtlLanguage(Intl.getCurrentLocale()) ? 'rtl' : 'ltr';

    This feature is also available in the regular scissors transformer, but it must be enabled with bidiCss: true.

  • Added compiledCssExtension option to control how foo.scss is compiled: append yields foo.scss.css (default), while replace produces foo.css.

Bugfixes #

  • Fixed support for -I / --load-path arguments in sasscArgs setting (issue #21)

0.3.0 (2016-01-13) #

Features #

  • Added scissors-sassc-compass binary that provides a best-effort replacement for Compass using SassC: it processes any inline-image function detected, and falls back to using plain Compass if SassC fails to compile the input (or if it does not understand the command-line arguments).

Bugfixes #

  • scissors/permutations_transformer: generate sourcemaps for permutations (limited to source map of main fragment; shouldn't hurt much if deferred parts only contain messages and template caches)

0.2.2 (2016-01-05) #

Bugfixes #

  • Systematically resolve paths from settings (for pngcrush, sassc, etc)
  • scissors/permutations_transformer: generate permutation for defaultLocale (language in which the messages are written in the source, defaults to en_US)

0.2.1 (2015-12-14) #

Bugfixes #

  • Resolve files with the .packages file to prepare for disappearance of packages/.
  • scissors/transformer: made Sass transformer really lazy.
  • scissors/permutations_transformer: hard-fail when parts check fails (consume the .dart.js)
  • scissors/reloader/transformer: added named argument timestampBaseUrl to setupReloader.

0.2.0 (2015-11-19) #

Features #

  • Added inline_images.dart entry point for standalone inlining

Bugfixes #

  • Improved asset file resolution with package_name/path pattern.
  • Made permutations transformer lazy

0.1.9 (2015-11-15) #

Features #

  • Added new scissors/reloader/transformer + runtime lib that allow instant reload whenever assets are updated (triggered at the end of the pub build). Reloader usage is erased from release builds by default (respecting source maps).
  • Don't prune css in debug by default

Bugfixes #

  • Sass transformer respects existing .scss.css input and only rebuilds them from the .scss sources when it's out of date (timestamp-based; can be disabled with onlyCompileOutOfDateSass: false).

0.1.8 (2015-11-14) #

This version comes with a massive refactoring that splits out most features into their own transformer. Please note that there are still only 3 officially-supported transformer entry points:

  • scissors/transformer (lazy Sass compilation, CSS and image optimizations)
  • scissors/eager_transformer (eager version of the previous: builds all the assets upfront when pub serve is run)
  • scissors/permutations_transformer (lazy locale-specific permutations with optional Closure Compilation to reoptimize the outputs)

Bugfixes #

  • Permutations transformer (scissors/permutations_transformer):

    • Permutations are now built lazily (fixes pub serve + Dartium experience)
    • Disabled reoptimizePermutations by default
    • Respect javaPath when running the Closure Compiler.
    • Added expectedPartCounts check (takes a map of .dart.js script path to number of expected parts, see example/permutations)
  • Fixed path resolution regression (dotted package names)

0.1.7 (2015-11-12) #

Bugfixes #

  • Fixed image linking (imageInlining: linkInlinedImages), with a new packageRewrites setting (with fromPattern,toReplacement syntax; defaults to ^package:,packages/, which works well with pub serve).
  • Fixed usage of pngCrushPath setting.

0.1.6 (2015-11-12) #

Bugfixes #

  • Fixed support of wildcard * CSS rules.

Features #

  • Added support for LTR/RTL-specific parts in scissors/permutations_transformer (see example/permutations).

0.1.5 (2015-11-12) #

Bugfixes #

  • Fixed base64 format in inline-image

Features #

  • Added experimental SVG optimization (poor-man heuristics, enabled in release, disable with optimizeSvg: false)

  • Added experimental PNG optimization relying on pngcrush (enabled in release, disable with optimizePng: false, provide path to pngcrush with pngCrushPath: path/to/pngcrush)

  • Added imageInlining setting to control image inlining inside CSS files, accepts values:

    • inlineAllUrls: inlines inline-image and url references
    • inlineInlinedImages: inlines inline-image only (default in release mode)
    • linkInlinedImages: rewrites inline-image references into url references (default in debug mode): images are not inlined.
    • disablePass: don't touch inline-image references (may produce invalid CSS).
  • Added experimental scissors/permutations_transformer transformer that generates locale-specific .js artefacts when using defer-loaded messages (package:intl).

0.1.4 (2015-10-30) #

Bugfixes #

  • Cleaner path resolution logic (easier to override)
  • Stricter regexp in recursive sass imports consumer

0.1.3 (2015-10-28) #

Features #

  • The transformer is now lazy by default, which speeds up startup time of pub serve (use scissors/eager_transformer to force eager transform)

  • Sass compilation supports Compass's inline-image helper to inline images.

  • Rebuilds .css files when any transitive .sass import is modified:

    • Requires pub serve --force-poll
    • The default (lazy) transformer will just invalidate stale resources, while scissors/eager_transformer will eagerly rebuild them.

0.1.2 (2015-10-26) #

Features #

  • Improved sassc integration:

    • Resolving ${FOO} environment variables in sasscPath and sasscArgs settings
    • Automatically set --load-path arguments with list of root directories, with clean fork point (path_resolver.dart)
    • Output css sourcemaps

0.1.1 (2015-10-23) #

Features #

  • Preliminary support for compiling *.scss and *.sass files with sassc.

0.1.0 (2015-10-22) #

Features #

  • Basic support for .css pruning based on companion .html template or inlined templates in companion .dart file (Angular1 and Angular2)
  • Support for ng-class and interpolated name fragments inside class in templates

Use this package as an executable

1. Install it

You can install the package from the command line:

$ pub global activate scissors

2. Use it

The package has the following executables:

$ bazel-worker
$ scissors-inline-images
$ scissors-sassc

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  scissors: ^0.6.7

2. Install it

You can install packages from the command line:

with pub:

$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:scissors/scissors.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

The package version is not analyzed, because it does not support Dart 2. Until this is resolved, the package will receive a health and maintenance score of 0.

Analysis issues and suggestions

Support Dart 2 in pubspec.yaml.

The SDK constraint in pubspec.yaml doesn't allow the Dart 2.0.0 release. For information about upgrading it to be Dart 2 compatible, please see

Maintenance issues and suggestions

Make sure dartdoc successfully runs on your package's source files. (-10 points)

Dependencies were not resolved.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.8.0 <2.0.0