version app + node.exe + nw.exe
This commit is contained in:
15
node_modules/jade/.npmignore
generated
vendored
Normal file
15
node_modules/jade/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
test
|
||||
support
|
||||
benchmarks
|
||||
examples
|
||||
lib-cov
|
||||
coverage
|
||||
.gitmodules
|
||||
.travis.yml
|
||||
History.md
|
||||
Makefile
|
||||
test/
|
||||
support/
|
||||
benchmarks/
|
||||
examples/
|
||||
docs/
|
||||
1
node_modules/jade/.release.json
generated
vendored
Normal file
1
node_modules/jade/.release.json
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
"2ab04e8289982bfac3548a9c6016476472dcdb4f"
|
||||
991
node_modules/jade/History.md
generated
vendored
Normal file
991
node_modules/jade/History.md
generated
vendored
Normal file
@@ -0,0 +1,991 @@
|
||||
1.11.0 / 2015-06-12
|
||||
==================
|
||||
|
||||
* Added block code support ([@alephyud](https://github.com/alephyud))
|
||||
* Improved runtime performance of mixins significantly ([Andreas Lubbe](https://github.com/alubbe))
|
||||
* Improved runtime performance of jade's string escaping ([Andreas Lubbe](https://github.com/alubbe)) and ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Better line number counting for pipeless text ([@alephyud](https://github.com/alephyud))
|
||||
|
||||
|
||||
1.10.0 / 2015-05-25
|
||||
==================
|
||||
|
||||
* Now supports jstransformers, which allows improved handling of embedded languages such as Coffee-Script, and deprecated Transformers support in filters - to be removed in 2.0.0 ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* CLI: added a flag to keep directory hierarchy when a directory is specified - this behavior will be the default in 2.0.0 ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* disabled 'compileDebug' flag by default when used with express in production mode ([Andreas Lubbe](https://github.com/alubbe))
|
||||
* Fixed a memory leak on modern versions of Chrome as well as node 0.12 and iojs ([Andreas Lubbe](https://github.com/alubbe))
|
||||
* update website ([@GarthDB](https://github.com/GarthDB))
|
||||
|
||||
1.9.2 / 2015-01-18
|
||||
==================
|
||||
|
||||
* Do not ignore some parser errors for mismatched parenthesis ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Warn for `:` that is not followed by a space ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix #1794 (a bizzare bug with a certain combination of inheritance, mixins and &attributes) ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Add `compileClientWithDependenciesTracked` ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Support comments in `case` blocks ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix blocks in nested mixins ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Lots more documentation ([@enlore](https://github.com/enlore))
|
||||
* Fix watching in CLI ([@pavel](https://github.com/pavel))
|
||||
|
||||
1.9.1 / 2015-01-17
|
||||
==================
|
||||
|
||||
* Clean up path/fs functions in CLI as we no longer support node@0.6 ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Update commander ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Document `cache` and `parser` options ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Fix bug in 1.9.0 where we read the file if cache was enabled, even if a string was provided ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Fix year in changelog ([@tomByrer](https://github.com/tomByrer))
|
||||
|
||||
1.9.0 / 2015-01-13
|
||||
==================
|
||||
|
||||
* Fix `--watch` sometimes dying when there were file-system errors ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix `--watch` by using `fs.watchFile` correctly ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Fix errors with using the CLI to compile from stdin
|
||||
* Better looking badges ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Added `--extension` to CLI([@nicocedron](https://github.com/nicocedron) and [@TimothyGu](https://github.com/TimothyGu))
|
||||
* Refactor and improve internal cache handling ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Loads more tests ([@TimothyGu](https://github.com/TimothyGu))
|
||||
|
||||
1.8.2 / 2014-12-16
|
||||
==================
|
||||
|
||||
* Use `-` as the default filename when using stdin on CLI ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Prevent some compiler errors being silenced ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove use of non-standard `string.trimLeft()` ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix bug in CLI when no name was provided for child template ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove dependency on monocle (hopefully fixing installation on 0.8) ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Add gitter chat room ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.8.1 / 2014-11-30
|
||||
==================
|
||||
|
||||
* Fix corner case when the pretty option was passed a non-string truthy value ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Warn when `lexer` is given as an option ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Update dependencies ([@TimothyGu](https://github.com/TimothyGu))
|
||||
|
||||
1.8.0 / 2014-11-28
|
||||
==================
|
||||
|
||||
* Fix empty text-only block ([@rlidwka](https://github.com/rlidwka))
|
||||
* Warn about future change to ISO 8601 style dates ([@TimothyGu](https://github.com/TimothyGu) and [@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Add warnings when data-attributes contain ampersands ([@TimothyGu](https://github.com/TimothyGu))
|
||||
* Allow custom pretty indentation ([@bfred-it](https://github.com/bfred-it))
|
||||
* Add support for an object in the style attribute ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Add support for an object in the class attribute ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Ignore fs module in browser builds ([@sokra](https://github.com/sokra))
|
||||
* Update dependencies ([@hildjj](https://github.com/hildjj))
|
||||
* Check mixin arguments are valid JavaScript expressions ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove symlink ([@slang800](https://github.com/slang800))
|
||||
|
||||
1.7.0 / 2014-09-17
|
||||
==================
|
||||
|
||||
* Add Doctype option on command line ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Support ES6 style rest args in mixins ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix support for unicode newlines (\u2028, \u2029) ([@rlidwka](https://github.com/rlidwka))
|
||||
* Expose `globals` option from the `with` module ([@sokra](https://github.com/sokra))
|
||||
* Lots of new documentation ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.6.0 / 2014-08-31
|
||||
==================
|
||||
|
||||
* Allow optional white space after `+` when calling a mixin ([@char101](https://github.com/char101))
|
||||
* Use void-elements module to replace internal self-closing list ([@hemanth](https://github.com/hemanth))
|
||||
* Fix a warning that eroniously warned for un-used blocks if in an extending template from an include (Reported by [@Dissimulazione](https://github.com/Dissimulazione))
|
||||
* Fix mixins not working at end of file ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix error reporting when mixin block was followed by blank lines ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
|
||||
1.5.0 / 2014-07-23
|
||||
==================
|
||||
|
||||
* Added compileFile API ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix line number in un-used blocks warning ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix a warning that eroniously warned for un-used blocks if they were under another block (Reported by [@pesho](https://github.com/pesho))
|
||||
|
||||
1.4.2 / 2014-07-16
|
||||
==================
|
||||
|
||||
* Fix a warning that eroniously warned for un-used blocks if they were under a "Code" element (Reported by [@narirou](https://github.com/narirou))
|
||||
|
||||
1.4.1 / 2014-07-16
|
||||
==================
|
||||
|
||||
* Fix an error that sometimes resulted in 'unexpected token "pipless-text"' being erroniously thrown (Reported by [@Artazor](https://github.com/Artazor) and [@thenitai](https://github.com/thenitai))
|
||||
|
||||
1.4.0 / 2014-07-15
|
||||
==================
|
||||
|
||||
* Fix CLI so it keeps watching when errors occur ([@AndrewTsao](https://github.com/AndrewTsao))
|
||||
* Support custom names for client side templates ([@ForbesLindesay](http://www.forbeslindesay.co.uk/) and [@dscape](https://github.com/dscape))
|
||||
* Allow whitepsace other than "space" before attributes passed to mixins (N.B. there is a small chance this could be a breaking change for you) ([@regular](https://github.com/regular))
|
||||
* Track dependencies so file watchers can be more clever ([@ForbesLindesay](http://www.forbeslindesay.co.uk/) and [@sdether](https://github.com/sdether))
|
||||
* Allow passing options to filtered includes ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix bugs with indentation in filters ([@ForbesLindesay](http://www.forbeslindesay.co.uk/) and [@lackac](https://github.com/lackac))
|
||||
* Warn on block names that are never used ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.3.1 / 2014-04-04
|
||||
==================
|
||||
|
||||
* Fix error with tags in xml that are self-closing in html ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix error message for inline tags with content ([@hiddentao](https://github.com/hiddentao))
|
||||
|
||||
1.3.0 / 2014-03-02
|
||||
==================
|
||||
|
||||
* Fix a bug where sometimes mixins were removed by an optimisation even though they were being called ([@ForbesLindesay](http://www.forbeslindesay.co.uk/), reported by [@leider](https://github.com/leider))
|
||||
* Updated with to support automatically detecting when a value is "global" and removed redundant `options.globals` option ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Improve warnings for tags with multiple attributes ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Deprecate (with a warning) `node.clone`, `block.replace`, `attrs.removeAttribute`, `attrs.getAttribute` - these are all internal APIs for the AST ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.2.0 / 2014-02-26
|
||||
==================
|
||||
|
||||
* Use variables instead of properties of jade, improving performance and reliability with nested templates ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Support compiling templates from stdin via a user typing ([@yorkie](https://github.com/yorkie))
|
||||
* Lazily add mixins ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix case fall-through ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Earlier errors for `when` without `case` and `else` without `if` ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Allow `if`/`else` etc. to not have a block.
|
||||
* Remove lib-cov legacy to make browserify work better ([@silver83](https://github.com/silver83))
|
||||
* Add and improve test coverage using istanbul ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.1.5 / 2014-01-19
|
||||
==================
|
||||
|
||||
* Add filename to and fix line numbers for missing space before text warning (@ijin82)
|
||||
* Fix filenames for some error reporting in extends/includes (@doublerebel)
|
||||
* Fix a corner case where a mixin was called with `&attributes` but no other attributes and a block that was supposed to be fixed in 1.1.4 ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.1.4 / 2014-01-09
|
||||
==================
|
||||
|
||||
* Fix a corner case where a mixin was called with `&attributes` but no other attributes and a block ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.1.3 / 2014-01-09
|
||||
==================
|
||||
|
||||
* Fix failure of npm prepublish not running
|
||||
|
||||
1.1.2 / 2014-01-09
|
||||
==================
|
||||
|
||||
* Fix same interaction of `&attributes` with `false` `null` or `undefined` but combined with dynamic attributes ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.1.1 / 2014-01-09
|
||||
==================
|
||||
|
||||
* Fix a bug when `&attributes` is combined with static attributes that evaluate to `false` or `null` or `undefined` ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.1.0 / 2014-01-07
|
||||
==================
|
||||
|
||||
* Fix class merging to work as documented ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Throw an error when the same attribute is duplicated multiple times ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Move more errors into the parser/lexer so they have more info about line numbers ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Support mixin blocks at the end of files ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.0.2 / 2013-12-31
|
||||
==================
|
||||
|
||||
* Fix a bug when `&attributes` is combined with dynamic attributes ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.0.1 / 2013-12-29
|
||||
==================
|
||||
|
||||
* Allow self closing tags to contian whitespace ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Allow tags to have a single white space after them ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Support text bodies of tags that begin with `//` rather than treating them as comments ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
|
||||
1.0.0 / 2013-12-22
|
||||
==================
|
||||
|
||||
* No longer support node@0.8 ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix error reporting in layouts & includes ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Allow a list of 'globals' to be passed as an array at compile time & don't automatically expose all globals ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Escape apostrophes in data attributes (@qualiabyte)
|
||||
* Fix mixin/block interaction ([@ForbesLindesay](http://www.forbeslindesay.co.uk/) & [@paulyoung](https://github.com/paulyoung))
|
||||
* Ignore trailing space after mixin declaration ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Make literal `.` work as expected ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove implicit text only for script/style ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Stop parsing comments and remove support for conditional comments ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Make filtering includes explicit ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove special assignment syntax ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove `!!!` shortcut for `doctype` ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove `5` shorcut for `html` doctype ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove `colons` option from the distant past ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Add a sepatate `compileClient` and `compileFileClient` to replace the `client` option ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove polyfills for supporting old browsers ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Allow interpolation for mixin names ([@jeromew](https://github.com/jeromew)
|
||||
* Use `node.type` instead of `node.constructor.name` so it can be minified ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Allow hyphens in filter names ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Throw an error if a self closing tag has content ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Support inline tags ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Replace `attributes` magic attribute with `&attributes(attributes)` ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove automatic tag wrapping for filters, you can just put the tags in yourself now ([@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Remove whitespace from tags nested inside pre tags ([@markdalgleish](http://markdalgleish.com))
|
||||
|
||||
0.35.0 / 2013-08-21
|
||||
===================
|
||||
|
||||
* Add support for space separated attributes (thanks to [@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Add earlier errors for invalid JavaScript expressions (thanks to [@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* Fix parsing files with UTF8 BOMs when they are includes or parent/layout templates (thanks to [@kiinoo](https://github.com/kiinoo))
|
||||
|
||||
0.34.1 / 2013-07-26
|
||||
===================
|
||||
|
||||
* fix render file not working when called with callback (reported by [@xieren58](https://github.com/xieren58))
|
||||
|
||||
0.34.0 / 2013-07-26
|
||||
===================
|
||||
|
||||
* callbacks only called once for async methods even if they throw (reported by [@davidcornu](https://github.com/davidcornu))
|
||||
* HTML comments are pretty printed better (thanks to [@eddiemonge](https://github.com/eddiemonge))
|
||||
* callbacks are optional and leaving them out results in synchronous operation (thanks to [@ForbesLindesay](http://www.forbeslindesay.co.uk/))
|
||||
* empty filter nodes are now permitted (thanks to [@coderanger](https://github.com/coderanger))
|
||||
* overhaul website and documentation (thanks to [@ForbesLindesay](http://www.forbeslindesay.co.uk/)), much more of this to come.
|
||||
|
||||
0.33.0 / 2013-07-12
|
||||
===================
|
||||
|
||||
* Hugely more powerful error reporting (especially with `compileDebug` set explicitly to `true`)
|
||||
* Add a warning for tags with multiple attributes
|
||||
* be strict about requiring newlines after tags to fix some odd corner cases
|
||||
* fix escaping of class to allow it to be unescaped (thanks to [@christiangenco](https://github.com/christiangenco))
|
||||
|
||||
0.32.0 / 2013-06-28
|
||||
===================
|
||||
|
||||
* remove `jade.version` and fix `jade --version`
|
||||
* add file name and line number to deprecation warnings
|
||||
* use constantinople for better constant detection
|
||||
* update `with` for a massive performance upgrade at compile time
|
||||
|
||||
0.31.2 / 2013-06-07
|
||||
===================
|
||||
|
||||
* fix overzealous deprecation warnings
|
||||
|
||||
0.31.1 / 2013-05-31
|
||||
===================
|
||||
|
||||
* fix line endings for executable command
|
||||
* fix `locals` variable being undefined
|
||||
* fix an obscure bug that could occur if multiple mixins interact badly (see [substack/lexical-scope#13](https://github.com/substack/lexical-scope/issues/13))
|
||||
|
||||
0.31.0 / 2013-05-30
|
||||
==================
|
||||
|
||||
* deprecate implicit text-only `script` and `style` tags
|
||||
* make `with` at compile time using `lexical-scope`
|
||||
* add `options.parser` that behaves exactly like `options.compiler`
|
||||
* add "component.json" for component (runtime) support
|
||||
* removed `hasOwnProperty` check in each loops
|
||||
* removed .min files from the repository (people can just generate these themselves)
|
||||
* use browserify to compile client side libraries
|
||||
* fix buggy block extending should now be fixed
|
||||
* fix preserve case of custom doctypes
|
||||
* fix regexps in attributes sometimes not being accepted
|
||||
* fix allow `$` sign in each loop variable names
|
||||
* fix mixins with buffered code on the same line
|
||||
* fix separate class names by ` ` rather than `,` (was sometimes incorrect)
|
||||
|
||||
0.30.0 / 2013-04-25
|
||||
==================
|
||||
|
||||
* add support for 'include' and 'extends' to use paths relative to basedir
|
||||
* fix accidental calling of functions in iteration block. Closes #986
|
||||
* fix: skip rethrow on client
|
||||
* fix each/else prefixed with `-`
|
||||
* fix multi-block prepend/append
|
||||
* swap -o and -O, set -o to --out
|
||||
|
||||
0.29.0 / 2013-04-16
|
||||
==================
|
||||
|
||||
* add "monocle" for watcher that actually works...
|
||||
* fix interpolation in blocks of text
|
||||
* fix attribute interpolation
|
||||
* move filters to an external library
|
||||
* fix JavaScript escaping corner cases
|
||||
|
||||
0.28.2 / 2013-03-04
|
||||
==================
|
||||
|
||||
* wtf coffeescript is not a dep
|
||||
|
||||
0.28.1 / 2013-01-10
|
||||
==================
|
||||
|
||||
* add passing of filename to include filters
|
||||
* fix wrong new lines for include filters
|
||||
|
||||
0.28.0 / 2013-01-08
|
||||
==================
|
||||
|
||||
* add .css and .js "filters". re #438
|
||||
* add include filters. Closes #283
|
||||
* fix "class:" within attribute escaping
|
||||
* removing ast filters
|
||||
* things I can't read:
|
||||
* 反馈地址
|
||||
* 样式
|
||||
* 联系
|
||||
* 初稿,翻译完
|
||||
* 接受大鸟的建议
|
||||
* 头晕,翻译一点点
|
||||
* 到过滤器翻译完毕
|
||||
* 翻译一部分
|
||||
* 中文翻译单独放
|
||||
* 特性部分
|
||||
* 再翻
|
||||
* 翻译一点点
|
||||
|
||||
0.27.7 / 2012-11-05
|
||||
==================
|
||||
|
||||
* fix each/else clause for enumerated objects
|
||||
* fix #764 (incorrect line number for error messages)
|
||||
* fix double-escaping of interpolated js slashes. Closes #784
|
||||
|
||||
0.27.6 / 2012-10-05
|
||||
==================
|
||||
|
||||
* Included templates can not override blocks of their parent. Closes #699
|
||||
|
||||
0.27.5 / 2012-09-24
|
||||
==================
|
||||
|
||||
* fix attr interpolation escaping. Closes #771
|
||||
|
||||
0.27.4 / 2012-09-18
|
||||
==================
|
||||
|
||||
* fix include yields. Closes #770
|
||||
|
||||
0.27.3 / 2012-09-18
|
||||
==================
|
||||
|
||||
* fix escaping of interpolation. Closes #769
|
||||
* loosen "mkdirp" version restriction [TooTallNate]
|
||||
|
||||
0.27.2 / 2012-08-07
|
||||
==================
|
||||
|
||||
* Revert "fixing string interpolation escaping #731", problems reported
|
||||
|
||||
0.27.1 / 2012-08-06
|
||||
==================
|
||||
|
||||
* fix attribute interpolation escaping #731
|
||||
* fix string interpolation escaping #731
|
||||
|
||||
0.27.0 / 2012-07-26
|
||||
==================
|
||||
|
||||
* added ability to pass in json file to `--obj`
|
||||
* add preliminary `each` `else` support. Closes #716
|
||||
* fix doctype bug overlooked in #712
|
||||
* fix stripping of utf-8 BOMs
|
||||
|
||||
0.26.3 / 2012-06-25
|
||||
==================
|
||||
|
||||
* Update version of commander that supports node v0.8.
|
||||
|
||||
0.26.2 / 2012-06-22
|
||||
==================
|
||||
|
||||
* Added --options alias of --obj
|
||||
* Added reserved word conflict prevention in Google's Closure Compiler
|
||||
* Added tag interpolation. Closes #657
|
||||
* Allow the compiled client to use it's own jade util functions [3rd-Eden]
|
||||
* Fixed `attrs()` escape bug [caseywebdev]
|
||||
|
||||
0.26.1 / 2012-05-27
|
||||
==================
|
||||
|
||||
* Changed default doctype to __html5__
|
||||
* Performance: statically compile attrs when possible [chowey]
|
||||
* Fixed some class attribute merging cases
|
||||
* Fixed so `block` doesn't consume `blockquotes` tag [chowey]
|
||||
* Fixed backslashes in text nodes [chowey]
|
||||
* Fixed / in text. Closes #638
|
||||
|
||||
0.26.0 / 2012-05-04
|
||||
==================
|
||||
|
||||
* Added package.json __component__ support
|
||||
* Added explicit self-closing tag support. Closes #605
|
||||
* Added `block` statement
|
||||
* Added mixin tag-like behaviour [chowey]
|
||||
* Fixed mixins with extends [chowey]
|
||||
|
||||
0.25.0 / 2012-04-18
|
||||
==================
|
||||
|
||||
* Added preliminary mixin block support. Closes #310
|
||||
* Fixed whitespace handling in various situations [chowey]
|
||||
* Fixed indentation in various situations [chowey]
|
||||
|
||||
0.24.0 / 2012-04-12
|
||||
==================
|
||||
|
||||
* Fixed unescaped attribute compilation
|
||||
* Fixed pretty-printing of text-only tags (__Warning__: this may affect rendering) [chowey]
|
||||
|
||||
0.23.0 / 2012-04-11
|
||||
==================
|
||||
|
||||
* Added data-attr json stringification support. Closes #572
|
||||
* Added unescaped attr support. Closes #198
|
||||
* Fixed #1070, reverted mixin function statements
|
||||
* Fixed jade.1 typo
|
||||
|
||||
0.22.1 / 2012-04-04
|
||||
==================
|
||||
|
||||
* Fixed source tags. now self-closing. Closes #308
|
||||
* Fixed: escape backslashes in coffeescript filter
|
||||
|
||||
0.22.0 / 2012-03-22
|
||||
==================
|
||||
|
||||
* Added jade manpage (`man jade` after installation for docs)
|
||||
* Added `-D, --no-debug` to jade(1)
|
||||
* Added `-p, --pretty` to jade(1)
|
||||
* Added `-c, --client` option to jade(1)
|
||||
* Fixed `-o { client: true }` with stdin
|
||||
* Fixed: skip blank lines in lexer (unless within pipeless text). Closes #399
|
||||
|
||||
0.21.0 / 2012-03-10
|
||||
==================
|
||||
|
||||
* Added new input/output test suite using Mocha's string diffing
|
||||
* Added alias `extend` -> `extends`. Closes #527 [guillermo]
|
||||
* Fixed include escapes. Closes #513
|
||||
* Fixed block-expansion with .foo and #foo short-hands. Closes #498
|
||||
|
||||
0.20.3 / 2012-02-16
|
||||
==================
|
||||
|
||||
* Changed: pass `.filename` to filters only
|
||||
|
||||
0.20.2 / 2012-02-16
|
||||
==================
|
||||
|
||||
* Fixed `:stylus` import capabilities, pass .filename
|
||||
|
||||
0.20.1 / 2012-02-02
|
||||
==================
|
||||
|
||||
* Fixed Block#includeBlock() with textOnly blocks
|
||||
|
||||
0.20.0 / 2011-12-28
|
||||
==================
|
||||
|
||||
* Added a browser example
|
||||
* Added `yield` for block `include`s
|
||||
* Changed: replaced internal `__` var with `__jade` [chrisleishman]
|
||||
* Fixed two globals. Closes #433
|
||||
|
||||
0.19.0 / 2011-12-02
|
||||
==================
|
||||
|
||||
* Added block `append` / `prepend` support. Closes #355
|
||||
* Added link in readme to jade-mode for Emacs
|
||||
* Added link to python implementation
|
||||
|
||||
0.18.0 / 2011-11-21
|
||||
==================
|
||||
|
||||
* Changed: only ['script', 'style'] are text-only. Closes #398'
|
||||
|
||||
0.17.0 / 2011-11-10
|
||||
==================
|
||||
|
||||
* jade.renderFile() is back! (for express 3.x)
|
||||
* Fixed `Object.keys()` failover bug
|
||||
|
||||
0.16.4 / 2011-10-24
|
||||
==================
|
||||
|
||||
* Fixed a test due to reserved keyword
|
||||
* Fixed: commander 0.1.x dep for 0.5.x
|
||||
|
||||
0.16.3 / 2011-10-24
|
||||
==================
|
||||
|
||||
* Added: allow leading space for conditional comments
|
||||
* Added quick implementation of a switch statement
|
||||
* Fixed parens in mixin args. Closes #380
|
||||
* Fixed: include files with a .jade extension as jade files
|
||||
|
||||
0.16.2 / 2011-09-30
|
||||
==================
|
||||
|
||||
* Fixed include regression. Closes #354
|
||||
|
||||
0.16.1 / 2011-09-29
|
||||
==================
|
||||
|
||||
* Fixed unexpected `else` bug when compileDebug: false
|
||||
* Fixed attr state issue for balancing pairs. Closes #353
|
||||
|
||||
0.16.0 / 2011-09-26
|
||||
==================
|
||||
|
||||
* Added `include` block support. Closes #303
|
||||
* Added template inheritance via `block` and `extends`. Closes #242
|
||||
* Added 'type="text/css"' to the style tags generated by filters.
|
||||
* Added 'uglifyjs' as an explicit devDependency.
|
||||
* Added -p, --path <path> flag to jade(1)
|
||||
* Added support for any arbitrary doctype
|
||||
* Added `jade.render(str[,options], fn)` back
|
||||
* Added first-class `while` support
|
||||
* Added first-class assignment support
|
||||
* Fixed runtime.js `Array.isArray()` polyfill. Closes #345
|
||||
* Fixed: set .filename option in jade(1) when passing filenames
|
||||
* Fixed `Object.keys()` polyfill typo. Closes #331
|
||||
* Fixed `include` error context
|
||||
* Renamed magic "index" to "$index". Closes #350
|
||||
|
||||
0.15.4 / 2011-09-05
|
||||
==================
|
||||
|
||||
* Fixed script template html. Closes #316
|
||||
* Revert "Fixed script() tag with trailing ".". Closes #314"
|
||||
|
||||
0.15.3 / 2011-08-30
|
||||
==================
|
||||
|
||||
* Added Makefile example. Closes #312
|
||||
* Fixed script() tag with trailing ".". Closes #314
|
||||
|
||||
0.15.2 / 2011-08-26
|
||||
==================
|
||||
|
||||
* Fixed new conditional boundaries. Closes #307
|
||||
|
||||
0.15.1 / 2011-08-26
|
||||
==================
|
||||
|
||||
* Fixed jade(1) support due to `res.render()` removal
|
||||
* Removed --watch support (use a makefile + watch...)
|
||||
|
||||
0.15.0 / 2011-08-26
|
||||
==================
|
||||
|
||||
* Added `client` option to reference runtime helpers
|
||||
* Added `Array.isArray()` for runtime.js as well
|
||||
* Added `Object.keys()` for the client-side runtime
|
||||
* Added first-class `if`, `unless`, `else` and `else if` support
|
||||
* Added first-class `each` / `for` support
|
||||
* Added `make benchmark` for continuous-bench
|
||||
* Removed `inline` option, SS helpers are no longer inlined either
|
||||
* Removed `Parser#debug()`
|
||||
* Removed `jade.render()` and `jade.renderFile()`
|
||||
* Fixed runtime.js `escape()` bug causing window.escape to be used
|
||||
* Fixed a bunch of tests
|
||||
|
||||
0.14.2 / 2011-08-16
|
||||
==================
|
||||
|
||||
* Added `include` support for non-jade files
|
||||
* Fixed code indentation when followed by newline(s). Closes #295 [reported by masylum]
|
||||
|
||||
0.14.1 / 2011-08-14
|
||||
==================
|
||||
|
||||
* Added `colons` option for everyone stuck with ":". Closes #231
|
||||
* Optimization: consecutive lines are merged in compiled js
|
||||
|
||||
0.14.0 / 2011-08-08
|
||||
==================
|
||||
|
||||
* Added array iteration with index example. Closes #276
|
||||
* Added _runtime.js_
|
||||
* Added `compileDebug` option to enable lineno instrumentation
|
||||
* Added `inline` option to disable inlining of helpers (for client-side)
|
||||
|
||||
0.13.0 / 2011-07-13
|
||||
==================
|
||||
|
||||
* Added `mixin` support
|
||||
* Added `include` support
|
||||
* Added array support for the class attribute
|
||||
|
||||
0.12.4 / 2011-06-23
|
||||
==================
|
||||
|
||||
* Fixed filter indentation bug. Closes #243
|
||||
|
||||
0.12.3 / 2011-06-21
|
||||
==================
|
||||
|
||||
* Fixed empty strings support. Closes #223
|
||||
* Fixed conditional comments documentation. Closes #245
|
||||
|
||||
0.12.2 / 2011-06-16
|
||||
==================
|
||||
|
||||
* Fixed `make test`
|
||||
* Fixed block comments
|
||||
|
||||
0.12.1 / 2011-06-04
|
||||
==================
|
||||
|
||||
* Fixed attribute interpolation with double quotes. Fixes #232 [topaxi]
|
||||
|
||||
0.12.0 / 2011-06-03
|
||||
==================
|
||||
|
||||
* Added `doctype` as alias of `!!!`
|
||||
* Added; doctype value is now case-insensitive
|
||||
* Added attribute interpolation support
|
||||
* Fixed; retain original indentation spaces in text blocks
|
||||
|
||||
0.11.1 / 2011-06-01
|
||||
==================
|
||||
|
||||
* Fixed text block indentation [Laszlo Bacsi]
|
||||
* Changed; utilizing devDependencies
|
||||
* Fixed try/catch issue with renderFile(). Closes #227
|
||||
* Removed attribute ":" support, use "=" (option for ':' coming soon)
|
||||
|
||||
0.11.0 / 2011-05-14
|
||||
==================
|
||||
|
||||
* Added `self` object to avoid poor `with(){}` performance [masylum]
|
||||
* Added `doctype` option [Jeremy Larkin]
|
||||
|
||||
0.10.7 / 2011-05-04
|
||||
==================
|
||||
|
||||
* expose Parser
|
||||
|
||||
0.10.6 / 2011-04-29
|
||||
==================
|
||||
|
||||
* Fixed CS `Object.keys()` [reported by robholland]
|
||||
|
||||
0.10.5 / 2011-04-26
|
||||
==================
|
||||
|
||||
* Added error context after the lineno
|
||||
* Added; indicate failing lineno with ">"
|
||||
* Added `Object.keys()` for the client-side
|
||||
* Fixed attr strings when containing the opposite quote. Closes 207
|
||||
* Fixed attr issue with js expressions within strings
|
||||
* Fixed single-quote filter escape bug. Closes #196
|
||||
|
||||
|
||||
0.10.4 / 2011-04-05
|
||||
==================
|
||||
|
||||
* Added `html` doctype, same as "5"
|
||||
* Fixed `pre`, no longer text-only
|
||||
|
||||
0.10.3 / 2011-03-30
|
||||
==================
|
||||
|
||||
* Fixed support for quoted attribute keys ex `rss("xmlns:atom"="atom")`
|
||||
|
||||
0.10.2 / 2011-03-30
|
||||
==================
|
||||
|
||||
* Fixed pipeless text bug with missing outdent
|
||||
|
||||
0.10.1 / 2011-03-28
|
||||
==================
|
||||
|
||||
* Fixed `support/compile.js` to exclude browser js in node
|
||||
* Fixes for IE [Patrick Pfeiffer]
|
||||
|
||||
0.10.0 / 2011-03-25
|
||||
==================
|
||||
|
||||
* Added AST-filter support back in the form of `<tag>[attrs]<:><block>`
|
||||
|
||||
0.9.3 / 2011-03-24
|
||||
==================
|
||||
|
||||
* Added `Block#unshift(node)`
|
||||
* Added `jade.js` for the client-side to the repo
|
||||
* Added `jade.min.js` for the client-side to the repo
|
||||
* Removed need for pipes in filters. Closes #185
|
||||
Note that this _will_ break filters used to
|
||||
manipulate the AST, until we have a different
|
||||
syntax for doing so.
|
||||
|
||||
0.9.2 / 2011-03-23
|
||||
==================
|
||||
|
||||
* Added jade `--version`
|
||||
* Removed `${}` interpolation support, use `#{}`
|
||||
|
||||
0.9.1 / 2011-03-16
|
||||
==================
|
||||
|
||||
* Fixed invalid `.map()` call due to recent changes
|
||||
|
||||
0.9.0 / 2011-03-16
|
||||
==================
|
||||
|
||||
* Added client-side browser support via `make jade.js` and `make jade.min.js`.
|
||||
|
||||
0.8.9 / 2011-03-15
|
||||
==================
|
||||
|
||||
* Fixed preservation of newlines in text blocks
|
||||
|
||||
0.8.8 / 2011-03-14
|
||||
==================
|
||||
|
||||
* Fixed jade(1) stdio
|
||||
|
||||
0.8.7 / 2011-03-14
|
||||
==================
|
||||
|
||||
* Added `mkdirs()` to jade(1)
|
||||
* Added jade(1) stdio support
|
||||
* Added new features to jade(1), `--watch`, recursive compilation etc [khingebjerg]
|
||||
* Fixed pipe-less text newlines
|
||||
* Removed jade(1) `--pipe` flag
|
||||
|
||||
0.8.6 / 2011-03-11
|
||||
==================
|
||||
|
||||
* Fixed parenthesized expressions in attrs. Closes #170
|
||||
* Changed; default interpolation values `== null` to ''. Closes #167
|
||||
|
||||
0.8.5 / 2011-03-09
|
||||
==================
|
||||
|
||||
* Added pipe-less text support with immediate ".". Closes #157
|
||||
* Fixed object support in attrs
|
||||
* Fixed array support for attrs
|
||||
|
||||
0.8.4 / 2011-03-08
|
||||
==================
|
||||
|
||||
* Fixed issue with expressions being evaluated several times. closes #162
|
||||
|
||||
0.8.2 / 2011-03-07
|
||||
==================
|
||||
|
||||
* Added markdown, discount, and markdown-js support to `:markdown`. Closes #160
|
||||
* Removed `:discount`
|
||||
|
||||
0.8.1 / 2011-03-04
|
||||
==================
|
||||
|
||||
* Added `pre` pipe-less text support (and auto-escaping)
|
||||
|
||||
0.8.0 / 2011-03-04
|
||||
==================
|
||||
|
||||
* Added block-expansion support. Closes #74
|
||||
* Added support for multi-line attrs without commas. Closes #65
|
||||
|
||||
0.7.1 / 2011-03-04
|
||||
==================
|
||||
|
||||
* Fixed `script()` etc pipe-less text with attrs
|
||||
|
||||
0.7.0 / 2011-03-04
|
||||
==================
|
||||
|
||||
* Removed `:javascript` filter (it doesn't really do anything special, use `script` tags)
|
||||
* Added pipe-less text support. Tags that only accept text nodes (`script`, `textarea`, etc) do not require `|`.
|
||||
* Added `:text` filter for ad-hoc pipe-less
|
||||
* Added flexible indentation. Tabs, arbitrary number of spaces etc
|
||||
* Added conditional-comment support. Closes #146
|
||||
* Added block comment support
|
||||
* Added rss example
|
||||
* Added `:stylus` filter
|
||||
* Added `:discount` filter
|
||||
* Fixed; auto-detect xml and do not self-close tags. Closes #147
|
||||
* Fixed whitespace issue. Closes #118
|
||||
* Fixed attrs. `,`, `=`, and `:` within attr value strings are valid Closes #133
|
||||
* Fixed; only output "" when code == null. Ex: `span.name= user.name` when undefined or null will not output "undefined". Closes #130
|
||||
* Fixed; throw on unexpected token instead of hanging
|
||||
|
||||
0.6.3 / 2011-02-02
|
||||
==================
|
||||
|
||||
* Added `each` support for Array-like objects [guillermo]
|
||||
|
||||
0.6.2 / 2011-02-02
|
||||
==================
|
||||
|
||||
* Added CSRF example, showing how you can transparently add inputs to a form
|
||||
* Added link to vim-jade
|
||||
* Fixed self-closing col support [guillermo]
|
||||
* Fixed exception when getAttribute or removeAttribute run into removed attributes [Naitik Shah]
|
||||
|
||||
0.6.0 / 2010-12-19
|
||||
==================
|
||||
|
||||
* Added unescaped interpolation variant `!{code}`. Closes #124
|
||||
* Changed; escape interpolated code by default `#{code}`
|
||||
|
||||
0.5.7 / 2010-12-08
|
||||
==================
|
||||
|
||||
* Fixed; hyphen in get `tag()`
|
||||
|
||||
0.5.6 / 2010-11-24
|
||||
==================
|
||||
|
||||
* Added `exports.compile(str, options)`
|
||||
* Renamed internal `_` to `__`, since `_()` is commonly used for translation
|
||||
|
||||
0.5.5 / 2010-10-30
|
||||
==================
|
||||
|
||||
* Add _coffeescript_ filter [Michael Hampton]
|
||||
* Added link to _slim_; a ruby implementation
|
||||
* Fixed quoted attributes issue.
|
||||
|
||||
* Fixed attribute issue with over greedy regexp.
|
||||
Previously "p(foo=(((('bar')))))= ((('baz')))"
|
||||
would __fail__ for example since the regexp
|
||||
would lookahead to far. Now we simply pair
|
||||
the delimiters.
|
||||
|
||||
0.5.4 / 2010-10-18
|
||||
==================
|
||||
|
||||
* Adding newline when using tag code when preceding text
|
||||
* Assume newline in tag text when preceding text
|
||||
* Changed; retain leading text whitespace
|
||||
* Fixed code block support to prevent multiple buffer openings [Jake Luer]
|
||||
* Fixed nested filter support
|
||||
|
||||
0.5.3 / 2010-10-06
|
||||
==================
|
||||
|
||||
* Fixed bug when tags with code also have a block [reported by chrisirhc]
|
||||
|
||||
0.5.2 / 2010-10-05
|
||||
==================
|
||||
|
||||
* Added; Text introduces newlines to mimic the grammar.
|
||||
Whitespace handling is a little tricky with this sort of grammar.
|
||||
Jade will now mimic the written grammar, meaning that text blocks
|
||||
using the "|" margin character will introduce a literal newline,
|
||||
where as immediate tag text (ex "a(href='#') Link") will not.
|
||||
|
||||
This may not be ideal, but it makes more sense than what Jade was
|
||||
previously doing.
|
||||
|
||||
* Added `Tag#text` to disambiguate between immediate / block text
|
||||
* Removed _pretty_ option (was kinda useless in the state it was in)
|
||||
* Reverted ignoring of newlines. Closes #92.
|
||||
* Fixed; `Parser#parse()` ignoring newlines
|
||||
|
||||
0.5.1 / 2010-10-04
|
||||
==================
|
||||
|
||||
* Added many examples
|
||||
* Added; compiler api is now public
|
||||
* Added; filters can accept / manipulate the parse tree
|
||||
* Added filter attribute support. Closes #79
|
||||
* Added LL(*) capabilities
|
||||
* Performance; wrapping code blocks in {} instead of `(function(){}).call(this)`
|
||||
* Performance; Optimized attribute buffering
|
||||
* Fixed trailing newlines in blocks
|
||||
|
||||
0.5.0 / 2010-09-11
|
||||
==================
|
||||
|
||||
* __Major__ refactor. Logic now separated into lexer/parser/compiler for future extensibility.
|
||||
* Added _pretty_ option
|
||||
* Added parse tree output for _debug_ option
|
||||
* Added new examples
|
||||
* Removed _context_ option, use _scope_
|
||||
|
||||
0.4.1 / 2010-09-09
|
||||
==================
|
||||
|
||||
* Added support for arbitrary indentation for single-line comments. Closes #71
|
||||
* Only strip first space in text (ex '| foo' will buffer ' foo')
|
||||
|
||||
0.4.0 / 2010-08-30
|
||||
==================
|
||||
|
||||
* Added tab naive support (tabs are converted to a single indent, aka two spaces). Closes #24
|
||||
* Added unbuffered comment support. Closes #62
|
||||
* Added hyphen support for tag names, ex: "fb:foo-bar"
|
||||
* Fixed bug with single quotes in comments. Closes #61
|
||||
* Fixed comment whitespace issue, previously padding. Closes #55
|
||||
|
||||
0.3.0 / 2010-08-04
|
||||
==================
|
||||
|
||||
* Added single line comment support. Closes #25
|
||||
* Removed CDATA from _:javascript_ filter. Closes #47
|
||||
* Removed _sys_ local
|
||||
* Fixed code following tag
|
||||
|
||||
0.2.4 / 2010-08-02
|
||||
==================
|
||||
|
||||
* Added Buffer support to `render()`
|
||||
* Fixed filter text block exception reporting
|
||||
* Fixed tag exception reporting
|
||||
|
||||
0.2.3 / 2010-07-27
|
||||
==================
|
||||
|
||||
* Fixed newlines before block
|
||||
* Fixed; tag text allowing arbitrary trailing whitespace
|
||||
|
||||
0.2.2 / 2010-07-16
|
||||
==================
|
||||
|
||||
* Added support for `jade.renderFile()` to utilize primed cache
|
||||
* Added link to [textmate bundle](http://github.com/miksago/jade-tmbundle)
|
||||
* Fixed filter issue with single quotes
|
||||
* Fixed hyphenated attr bug
|
||||
* Fixed interpolation single quotes. Closes #28
|
||||
* Fixed issue with comma in attrs
|
||||
|
||||
0.2.1 / 2010-07-09
|
||||
==================
|
||||
|
||||
* Added support for node-discount and markdown-js
|
||||
depending on which is available.
|
||||
|
||||
* Added support for tags to have blocks _and_ text.
|
||||
this kinda fucks with arbitrary whitespace unfortunately,
|
||||
but also fixes trailing spaces after tags _with_ blocks.
|
||||
|
||||
* Caching generated functions. Closes #46
|
||||
|
||||
0.2.0 / 2010-07-08
|
||||
==================
|
||||
|
||||
* Added `- each` support for readable iteration
|
||||
* Added [markdown-js](http://github.com/evilstreak/markdown-js) support (no compilation required)
|
||||
* Removed node-discount support
|
||||
|
||||
0.1.0 / 2010-07-05
|
||||
==================
|
||||
|
||||
* Added `${}` support for interpolation. Closes #45
|
||||
* Added support for quoted attr keys: `label("for": 'something')` is allowed (_although not required_) [Guillermo]
|
||||
* Added `:less` filter [jakeluer]
|
||||
|
||||
0.0.2 / 2010-07-03
|
||||
==================
|
||||
|
||||
* Added `context` as synonym for `scope` option [Guillermo]
|
||||
* Fixed attr splitting: `div(style:"color: red")` is now allowed
|
||||
* Fixed issue with `(` and `)` within attrs: `a(class: (a ? 'a' : 'b'))` is now allowed
|
||||
* Fixed issue with leading / trailing spaces in attrs: `a( href="#" )` is now allowed [Guillermo]
|
||||
|
||||
22
node_modules/jade/LICENSE
generated
vendored
Normal file
22
node_modules/jade/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
154
node_modules/jade/README.md
generated
vendored
Normal file
154
node_modules/jade/README.md
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
# [](http://jade-lang.com/)
|
||||
|
||||
Full documentation is at [jade-lang.com](http://jade-lang.com/)
|
||||
|
||||
Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com)
|
||||
and implemented with JavaScript for [node](http://nodejs.org) and browsers. For bug reports,
|
||||
feature requests and questions, [open an issue](https://github.com/jadejs/jade/issues/new).
|
||||
For discussion join the [chat room](https://gitter.im/jadejs/jade).
|
||||
|
||||
You can test drive Jade online [here](http://naltatis.github.com/jade-syntax-docs).
|
||||
|
||||
[](https://travis-ci.org/jadejs/jade)
|
||||
[](https://coveralls.io/r/jadejs/jade?branch=master)
|
||||
[](https://david-dm.org/jadejs/jade)
|
||||
[](https://david-dm.org/jadejs/jade#info=devDependencies)
|
||||
[](http://badge.fury.io/js/jade)
|
||||
[](https://gitter.im/jadejs/jade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
## Installation
|
||||
|
||||
via npm:
|
||||
|
||||
```bash
|
||||
$ npm install jade
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
Jade is a clean, whitespace sensitive syntax for writing html. Here is a simple example:
|
||||
|
||||
```jade
|
||||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
title= pageTitle
|
||||
script(type='text/javascript').
|
||||
if (foo) bar(1 + 5)
|
||||
body
|
||||
h1 Jade - node template engine
|
||||
#container.col
|
||||
if youAreUsingJade
|
||||
p You are amazing
|
||||
else
|
||||
p Get on it!
|
||||
p.
|
||||
Jade is a terse and simple templating language with a
|
||||
strong focus on performance and powerful features.
|
||||
```
|
||||
|
||||
becomes
|
||||
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Jade</title>
|
||||
<script type="text/javascript">
|
||||
if (foo) bar(1 + 5)
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Jade - node template engine</h1>
|
||||
<div id="container" class="col">
|
||||
<p>You are amazing</p>
|
||||
<p>Jade is a terse and simple templating language with a strong focus on performance and powerful features.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The official [jade tutorial](http://jade-lang.com/tutorial/) is a great place to start. While that (and the syntax documentation) is being finished, you can view some of the old documentation [here](https://github.com/jadejs/jade/blob/master/jade.md) and [here](https://github.com/jadejs/jade/blob/master/jade-language.md)
|
||||
|
||||
## API
|
||||
|
||||
For full API, see [jade-lang.com/api](http://jade-lang.com/api/)
|
||||
|
||||
```js
|
||||
var jade = require('jade');
|
||||
|
||||
// compile
|
||||
var fn = jade.compile('string of jade', options);
|
||||
var html = fn(locals);
|
||||
|
||||
// render
|
||||
var html = jade.render('string of jade', merge(options, locals));
|
||||
|
||||
// renderFile
|
||||
var html = jade.renderFile('filename.jade', merge(options, locals));
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
- `filename` Used in exceptions, and required when using includes
|
||||
- `compileDebug` When `false` no debug instrumentation is compiled
|
||||
- `pretty` Add pretty-indentation whitespace to output _(false by default)_
|
||||
|
||||
## Browser Support
|
||||
|
||||
The latest version of jade can be download for the browser in standalone form from [here](https://github.com/jadejs/jade/raw/master/jade.js). It only supports the very latest browsers though, and is a large file. It is recommended that you pre-compile your jade templates to JavaScript and then just use the [runtime.js](https://github.com/jadejs/jade/raw/master/runtime.js) library on the client.
|
||||
|
||||
To compile a template for use on the client using the command line, do:
|
||||
|
||||
```console
|
||||
$ jade --client --no-debug filename.jade
|
||||
```
|
||||
|
||||
which will produce `filename.js` containing the compiled template.
|
||||
|
||||
## Command Line
|
||||
|
||||
After installing the latest version of [node](http://nodejs.org/), install with:
|
||||
|
||||
```console
|
||||
$ npm install jade -g
|
||||
```
|
||||
|
||||
and run with
|
||||
|
||||
```console
|
||||
$ jade --help
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
Tutorials:
|
||||
|
||||
- cssdeck interactive [Jade syntax tutorial](http://cssdeck.com/labs/learning-the-jade-templating-engine-syntax)
|
||||
- cssdeck interactive [Jade logic tutorial](http://cssdeck.com/labs/jade-templating-tutorial-codecast-part-2)
|
||||
- [Jade について。](https://gist.github.com/japboy/5402844) (A Japanese Tutorial)
|
||||
- [Jade - 模板引擎](https://github.com/jadejs/jade/blob/master/Readme_zh-cn.md)
|
||||
|
||||
Implementations in other languages:
|
||||
|
||||
- [php](http://github.com/everzet/jade.php)
|
||||
- [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html)
|
||||
- [ruby](https://github.com/slim-template/slim)
|
||||
- [python](https://github.com/SyrusAkbary/pyjade)
|
||||
- [java](https://github.com/neuland/jade4j)
|
||||
|
||||
Other:
|
||||
|
||||
- [Emacs Mode](https://github.com/brianc/jade-mode)
|
||||
- [Vim Syntax](https://github.com/digitaltoad/vim-jade)
|
||||
- [TextMate Bundle](http://github.com/miksago/jade-tmbundle)
|
||||
- [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode)
|
||||
- [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs)
|
||||
- [html2jade](https://github.com/donpark/html2jade) converter
|
||||
- [jade2php](https://github.com/SE7ENSKY/jade2php) converter
|
||||
- [Jade Server](https://github.com/ded/jade-server) Ideal for building local prototypes apart from any application
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
1285
node_modules/jade/Readme_zh-cn.md
generated
vendored
Normal file
1285
node_modules/jade/Readme_zh-cn.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
295
node_modules/jade/bin/jade.js
generated
vendored
Normal file
295
node_modules/jade/bin/jade.js
generated
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var fs = require('fs')
|
||||
, program = require('commander')
|
||||
, path = require('path')
|
||||
, basename = path.basename
|
||||
, dirname = path.dirname
|
||||
, resolve = path.resolve
|
||||
, normalize = path.normalize
|
||||
, join = path.join
|
||||
, mkdirp = require('mkdirp')
|
||||
, jade = require('../');
|
||||
|
||||
// jade options
|
||||
|
||||
var options = {};
|
||||
|
||||
// options
|
||||
|
||||
program
|
||||
.version(require('../package.json').version)
|
||||
.usage('[options] [dir|file ...]')
|
||||
.option('-O, --obj <str|path>', 'JavaScript options object or JSON file containing it')
|
||||
.option('-o, --out <dir>', 'output the compiled html to <dir>')
|
||||
.option('-p, --path <path>', 'filename used to resolve includes')
|
||||
.option('-P, --pretty', 'compile pretty html output')
|
||||
.option('-c, --client', 'compile function for client-side runtime.js')
|
||||
.option('-n, --name <str>', 'The name of the compiled template (requires --client)')
|
||||
.option('-D, --no-debug', 'compile without debugging (smaller functions)')
|
||||
.option('-w, --watch', 'watch files for changes and automatically re-render')
|
||||
.option('-E, --extension <ext>', 'specify the output file extension')
|
||||
.option('-H, --hierarchy', 'keep directory hierarchy when a directory is specified')
|
||||
.option('--name-after-file', 'Name the template after the last section of the file path (requires --client and overriden by --name)')
|
||||
.option('--doctype <str>', 'Specify the doctype on the command line (useful if it is not specified by the template)')
|
||||
|
||||
|
||||
program.on('--help', function(){
|
||||
console.log(' Examples:');
|
||||
console.log('');
|
||||
console.log(' # translate jade the templates dir');
|
||||
console.log(' $ jade templates');
|
||||
console.log('');
|
||||
console.log(' # create {foo,bar}.html');
|
||||
console.log(' $ jade {foo,bar}.jade');
|
||||
console.log('');
|
||||
console.log(' # jade over stdio');
|
||||
console.log(' $ jade < my.jade > my.html');
|
||||
console.log('');
|
||||
console.log(' # jade over stdio');
|
||||
console.log(' $ echo \'h1 Jade!\' | jade');
|
||||
console.log('');
|
||||
console.log(' # foo, bar dirs rendering to /tmp');
|
||||
console.log(' $ jade foo bar --out /tmp ');
|
||||
console.log('');
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
// options given, parse them
|
||||
|
||||
if (program.obj) {
|
||||
options = parseObj(program.obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse object either in `input` or in the file called `input`. The latter is
|
||||
* searched first.
|
||||
*/
|
||||
function parseObj (input) {
|
||||
var str, out;
|
||||
try {
|
||||
str = fs.readFileSync(program.obj);
|
||||
} catch (e) {
|
||||
return eval('(' + program.obj + ')');
|
||||
}
|
||||
// We don't want to catch exceptions thrown in JSON.parse() so have to
|
||||
// use this two-step approach.
|
||||
return JSON.parse(str);
|
||||
}
|
||||
|
||||
// --path
|
||||
|
||||
if (program.path) options.filename = program.path;
|
||||
|
||||
// --no-debug
|
||||
|
||||
options.compileDebug = program.debug;
|
||||
|
||||
// --client
|
||||
|
||||
options.client = program.client;
|
||||
|
||||
// --pretty
|
||||
|
||||
options.pretty = program.pretty;
|
||||
|
||||
// --watch
|
||||
|
||||
options.watch = program.watch;
|
||||
|
||||
// --name
|
||||
|
||||
if (typeof program.name === 'string') {
|
||||
options.name = program.name;
|
||||
}
|
||||
|
||||
// --doctype
|
||||
|
||||
options.doctype = program.doctype;
|
||||
|
||||
// left-over args are file paths
|
||||
|
||||
var files = program.args;
|
||||
|
||||
// array of paths that are being watched
|
||||
|
||||
var watchList = [];
|
||||
|
||||
// function for rendering
|
||||
var render = program.watch ? tryRender : renderFile;
|
||||
|
||||
// compile files
|
||||
|
||||
if (files.length) {
|
||||
console.log();
|
||||
if (options.watch) {
|
||||
process.on('SIGINT', function() {
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
files.forEach(function (file) {
|
||||
render(file);
|
||||
});
|
||||
process.on('exit', function () {
|
||||
console.log();
|
||||
});
|
||||
// stdio
|
||||
} else {
|
||||
stdin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Watch for changes on path
|
||||
*
|
||||
* Renders `base` if specified, otherwise renders `path`.
|
||||
*/
|
||||
function watchFile(path, base, rootPath) {
|
||||
path = normalize(path);
|
||||
if (watchList.indexOf(path) !== -1) return;
|
||||
console.log(" \033[90mwatching \033[36m%s\033[0m", path);
|
||||
fs.watchFile(path, {persistent: true, interval: 200},
|
||||
function (curr, prev) {
|
||||
// File doesn't exist anymore. Keep watching.
|
||||
if (curr.mtime.getTime() === 0) return;
|
||||
// istanbul ignore if
|
||||
if (curr.mtime.getTime() === prev.mtime.getTime()) return;
|
||||
tryRender(base || path, rootPath);
|
||||
});
|
||||
watchList.push(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert error to string
|
||||
*/
|
||||
function errorToString(e) {
|
||||
return e.stack || /* istanbul ignore next */ (e.message || e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to render `path`; if an exception is thrown it is printed to stderr and
|
||||
* otherwise ignored.
|
||||
*
|
||||
* This is used in watch mode.
|
||||
*/
|
||||
function tryRender(path, rootPath) {
|
||||
try {
|
||||
renderFile(path, rootPath);
|
||||
} catch (e) {
|
||||
// keep watching when error occured.
|
||||
console.error(errorToString(e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile from stdin.
|
||||
*/
|
||||
|
||||
function stdin() {
|
||||
var buf = '';
|
||||
process.stdin.setEncoding('utf8');
|
||||
process.stdin.on('data', function(chunk){ buf += chunk; });
|
||||
process.stdin.on('end', function(){
|
||||
var output;
|
||||
if (options.client) {
|
||||
output = jade.compileClient(buf, options);
|
||||
} else {
|
||||
var fn = jade.compile(buf, options);
|
||||
var output = fn(options);
|
||||
}
|
||||
process.stdout.write(output);
|
||||
}).resume();
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
process.stdout.write('\n');
|
||||
process.stdin.emit('end');
|
||||
process.stdout.write('\n');
|
||||
process.exit();
|
||||
})
|
||||
}
|
||||
|
||||
var hierarchyWarned = false;
|
||||
|
||||
/**
|
||||
* Process the given path, compiling the jade files found.
|
||||
* Always walk the subdirectories.
|
||||
*
|
||||
* @param path path of the file, might be relative
|
||||
* @param rootPath path relative to the directory specified in the command
|
||||
*/
|
||||
|
||||
function renderFile(path, rootPath) {
|
||||
var re = /\.jade$/;
|
||||
var stat = fs.lstatSync(path);
|
||||
// Found jade file/\.jade$/
|
||||
if (stat.isFile() && re.test(path)) {
|
||||
// Try to watch the file if needed. watchFile takes care of duplicates.
|
||||
if (options.watch) watchFile(path, null, rootPath);
|
||||
if (program.nameAfterFile) {
|
||||
options.name = getNameFromFileName(path);
|
||||
}
|
||||
var fn = options.client
|
||||
? jade.compileFileClient(path, options)
|
||||
: jade.compileFile(path, options);
|
||||
if (options.watch && fn.dependencies) {
|
||||
// watch dependencies, and recompile the base
|
||||
fn.dependencies.forEach(function (dep) {
|
||||
watchFile(dep, path, rootPath);
|
||||
});
|
||||
}
|
||||
|
||||
// --extension
|
||||
var extname;
|
||||
if (program.extension) extname = '.' + program.extension;
|
||||
else if (options.client) extname = '.js';
|
||||
else extname = '.html';
|
||||
|
||||
// path: foo.jade -> foo.<ext>
|
||||
path = path.replace(re, extname);
|
||||
if (program.out) {
|
||||
// prepend output directory
|
||||
if (rootPath && program.hierarchy) {
|
||||
// replace the rootPath of the resolved path with output directory
|
||||
path = resolve(path).replace(new RegExp('^' + resolve(rootPath)), '');
|
||||
path = join(program.out, path);
|
||||
} else {
|
||||
if (rootPath && !hierarchyWarned) {
|
||||
console.warn('In Jade 2.0.0 --hierarchy will become the default.');
|
||||
hierarchyWarned = true;
|
||||
}
|
||||
// old behavior or if no rootPath handling is needed
|
||||
path = join(program.out, basename(path));
|
||||
}
|
||||
}
|
||||
var dir = resolve(dirname(path));
|
||||
mkdirp.sync(dir, 0755);
|
||||
var output = options.client ? fn : fn(options);
|
||||
fs.writeFileSync(path, output);
|
||||
console.log(' \033[90mrendered \033[36m%s\033[0m', normalize(path));
|
||||
// Found directory
|
||||
} else if (stat.isDirectory()) {
|
||||
var files = fs.readdirSync(path);
|
||||
files.map(function(filename) {
|
||||
return path + '/' + filename;
|
||||
}).forEach(function (file) {
|
||||
render(file, rootPath || path);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sensible name for a template function from a file path
|
||||
*
|
||||
* @param {String} filename
|
||||
* @returns {String}
|
||||
*/
|
||||
function getNameFromFileName(filename) {
|
||||
var file = basename(filename, '.jade');
|
||||
return file.toLowerCase().replace(/[^a-z0-9]+([a-z])/g, function (_, character) {
|
||||
return character.toUpperCase();
|
||||
}) + 'Template';
|
||||
}
|
||||
0
node_modules/jade/block-code.html
generated
vendored
Normal file
0
node_modules/jade/block-code.html
generated
vendored
Normal file
16
node_modules/jade/component.json
generated
vendored
Normal file
16
node_modules/jade/component.json
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "jade",
|
||||
"repo": "visionmedia/jade",
|
||||
"description": "Jade template runtime",
|
||||
"version": "1.11.0",
|
||||
"keywords": [
|
||||
"template"
|
||||
],
|
||||
"dependencies": {},
|
||||
"development": {},
|
||||
"license": "MIT",
|
||||
"scripts": [
|
||||
"lib/runtime.js"
|
||||
],
|
||||
"main": "lib/runtime.js"
|
||||
}
|
||||
9196
node_modules/jade/jade.js
generated
vendored
Normal file
9196
node_modules/jade/jade.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
723
node_modules/jade/lib/compiler.js
generated
vendored
Normal file
723
node_modules/jade/lib/compiler.js
generated
vendored
Normal file
@@ -0,0 +1,723 @@
|
||||
'use strict';
|
||||
|
||||
var nodes = require('./nodes');
|
||||
var filters = require('./filters');
|
||||
var doctypes = require('./doctypes');
|
||||
var runtime = require('./runtime');
|
||||
var utils = require('./utils');
|
||||
var selfClosing = require('void-elements');
|
||||
var parseJSExpression = require('character-parser').parseMax;
|
||||
var constantinople = require('constantinople');
|
||||
|
||||
function isConstant(src) {
|
||||
return constantinople(src, {jade: runtime, 'jade_interp': undefined});
|
||||
}
|
||||
function toConstant(src) {
|
||||
return constantinople.toConstant(src, {jade: runtime, 'jade_interp': undefined});
|
||||
}
|
||||
function errorAtNode(node, error) {
|
||||
error.line = node.line;
|
||||
error.filename = node.filename;
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize `Compiler` with the given `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @param {Object} options
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Compiler = module.exports = function Compiler(node, options) {
|
||||
this.options = options = options || {};
|
||||
this.node = node;
|
||||
this.hasCompiledDoctype = false;
|
||||
this.hasCompiledTag = false;
|
||||
this.pp = options.pretty || false;
|
||||
if (this.pp && typeof this.pp !== 'string') {
|
||||
this.pp = ' ';
|
||||
}
|
||||
this.debug = false !== options.compileDebug;
|
||||
this.indents = 0;
|
||||
this.parentIndents = 0;
|
||||
this.terse = false;
|
||||
this.mixins = {};
|
||||
this.dynamicMixins = false;
|
||||
if (options.doctype) this.setDoctype(options.doctype);
|
||||
};
|
||||
|
||||
/**
|
||||
* Compiler prototype.
|
||||
*/
|
||||
|
||||
Compiler.prototype = {
|
||||
|
||||
/**
|
||||
* Compile parse tree to JavaScript.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
compile: function(){
|
||||
this.buf = [];
|
||||
if (this.pp) this.buf.push("var jade_indent = [];");
|
||||
this.lastBufferedIdx = -1;
|
||||
this.visit(this.node);
|
||||
if (!this.dynamicMixins) {
|
||||
// if there are no dynamic mixins we can remove any un-used mixins
|
||||
var mixinNames = Object.keys(this.mixins);
|
||||
for (var i = 0; i < mixinNames.length; i++) {
|
||||
var mixin = this.mixins[mixinNames[i]];
|
||||
if (!mixin.used) {
|
||||
for (var x = 0; x < mixin.instances.length; x++) {
|
||||
for (var y = mixin.instances[x].start; y < mixin.instances[x].end; y++) {
|
||||
this.buf[y] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.buf.join('\n');
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the default doctype `name`. Sets terse mode to `true` when
|
||||
* html 5 is used, causing self-closing tags to end with ">" vs "/>",
|
||||
* and boolean attributes are not mirrored.
|
||||
*
|
||||
* @param {string} name
|
||||
* @api public
|
||||
*/
|
||||
|
||||
setDoctype: function(name){
|
||||
this.doctype = doctypes[name.toLowerCase()] || '<!DOCTYPE ' + name + '>';
|
||||
this.terse = this.doctype.toLowerCase() == '<!doctype html>';
|
||||
this.xml = 0 == this.doctype.indexOf('<?xml');
|
||||
},
|
||||
|
||||
/**
|
||||
* Buffer the given `str` exactly as is or with interpolation
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Boolean} interpolate
|
||||
* @api public
|
||||
*/
|
||||
|
||||
buffer: function (str, interpolate) {
|
||||
var self = this;
|
||||
if (interpolate) {
|
||||
var match = /(\\)?([#!]){((?:.|\n)*)$/.exec(str);
|
||||
if (match) {
|
||||
this.buffer(str.substr(0, match.index), false);
|
||||
if (match[1]) { // escape
|
||||
this.buffer(match[2] + '{', false);
|
||||
this.buffer(match[3], true);
|
||||
return;
|
||||
} else {
|
||||
var rest = match[3];
|
||||
var range = parseJSExpression(rest);
|
||||
var code = ('!' == match[2] ? '' : 'jade.escape') + "((jade_interp = " + range.src + ") == null ? '' : jade_interp)";
|
||||
this.bufferExpression(code);
|
||||
this.buffer(rest.substr(range.end + 1), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str = utils.stringify(str);
|
||||
str = str.substr(1, str.length - 2);
|
||||
|
||||
if (this.lastBufferedIdx == this.buf.length) {
|
||||
if (this.lastBufferedType === 'code') this.lastBuffered += ' + "';
|
||||
this.lastBufferedType = 'text';
|
||||
this.lastBuffered += str;
|
||||
this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + '");'
|
||||
} else {
|
||||
this.buf.push('buf.push("' + str + '");');
|
||||
this.lastBufferedType = 'text';
|
||||
this.bufferStartChar = '"';
|
||||
this.lastBuffered = str;
|
||||
this.lastBufferedIdx = this.buf.length;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Buffer the given `src` so it is evaluated at run time
|
||||
*
|
||||
* @param {String} src
|
||||
* @api public
|
||||
*/
|
||||
|
||||
bufferExpression: function (src) {
|
||||
if (isConstant(src)) {
|
||||
return this.buffer(toConstant(src) + '', false)
|
||||
}
|
||||
if (this.lastBufferedIdx == this.buf.length) {
|
||||
if (this.lastBufferedType === 'text') this.lastBuffered += '"';
|
||||
this.lastBufferedType = 'code';
|
||||
this.lastBuffered += ' + (' + src + ')';
|
||||
this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + ');'
|
||||
} else {
|
||||
this.buf.push('buf.push(' + src + ');');
|
||||
this.lastBufferedType = 'code';
|
||||
this.bufferStartChar = '';
|
||||
this.lastBuffered = '(' + src + ')';
|
||||
this.lastBufferedIdx = this.buf.length;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Buffer an indent based on the current `indent`
|
||||
* property and an additional `offset`.
|
||||
*
|
||||
* @param {Number} offset
|
||||
* @param {Boolean} newline
|
||||
* @api public
|
||||
*/
|
||||
|
||||
prettyIndent: function(offset, newline){
|
||||
offset = offset || 0;
|
||||
newline = newline ? '\n' : '';
|
||||
this.buffer(newline + Array(this.indents + offset).join(this.pp));
|
||||
if (this.parentIndents)
|
||||
this.buf.push("buf.push.apply(buf, jade_indent);");
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visit: function(node){
|
||||
var debug = this.debug;
|
||||
|
||||
if (debug) {
|
||||
this.buf.push('jade_debug.unshift(new jade.DebugItem( ' + node.line
|
||||
+ ', ' + (node.filename
|
||||
? utils.stringify(node.filename)
|
||||
: 'jade_debug[0].filename')
|
||||
+ ' ));');
|
||||
}
|
||||
|
||||
// Massive hack to fix our context
|
||||
// stack for - else[ if] etc
|
||||
if (false === node.debug && this.debug) {
|
||||
this.buf.pop();
|
||||
this.buf.pop();
|
||||
}
|
||||
|
||||
this.visitNode(node);
|
||||
|
||||
if (debug) this.buf.push('jade_debug.shift();');
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitNode: function(node){
|
||||
return this['visit' + node.type](node);
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit case `node`.
|
||||
*
|
||||
* @param {Literal} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitCase: function(node){
|
||||
var _ = this.withinCase;
|
||||
this.withinCase = true;
|
||||
this.buf.push('switch (' + node.expr + '){');
|
||||
this.visit(node.block);
|
||||
this.buf.push('}');
|
||||
this.withinCase = _;
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit when `node`.
|
||||
*
|
||||
* @param {Literal} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitWhen: function(node){
|
||||
if ('default' == node.expr) {
|
||||
this.buf.push('default:');
|
||||
} else {
|
||||
this.buf.push('case ' + node.expr + ':');
|
||||
}
|
||||
if (node.block) {
|
||||
this.visit(node.block);
|
||||
this.buf.push(' break;');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit literal `node`.
|
||||
*
|
||||
* @param {Literal} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitLiteral: function(node){
|
||||
this.buffer(node.str);
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit all nodes in `block`.
|
||||
*
|
||||
* @param {Block} block
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitBlock: function(block){
|
||||
var len = block.nodes.length
|
||||
, escape = this.escape
|
||||
, pp = this.pp
|
||||
|
||||
// Pretty print multi-line text
|
||||
if (pp && len > 1 && !escape && block.nodes[0].isText && block.nodes[1].isText)
|
||||
this.prettyIndent(1, true);
|
||||
|
||||
for (var i = 0; i < len; ++i) {
|
||||
// Pretty print text
|
||||
if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText)
|
||||
this.prettyIndent(1, false);
|
||||
|
||||
this.visit(block.nodes[i]);
|
||||
// Multiple text nodes are separated by newlines
|
||||
if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText)
|
||||
this.buffer('\n');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit a mixin's `block` keyword.
|
||||
*
|
||||
* @param {MixinBlock} block
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitMixinBlock: function(block){
|
||||
if (this.pp) this.buf.push("jade_indent.push('" + Array(this.indents + 1).join(this.pp) + "');");
|
||||
this.buf.push('block && block();');
|
||||
if (this.pp) this.buf.push("jade_indent.pop();");
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `doctype`. Sets terse mode to `true` when html 5
|
||||
* is used, causing self-closing tags to end with ">" vs "/>",
|
||||
* and boolean attributes are not mirrored.
|
||||
*
|
||||
* @param {Doctype} doctype
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitDoctype: function(doctype){
|
||||
if (doctype && (doctype.val || !this.doctype)) {
|
||||
this.setDoctype(doctype.val || 'default');
|
||||
}
|
||||
|
||||
if (this.doctype) this.buffer(this.doctype);
|
||||
this.hasCompiledDoctype = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `mixin`, generating a function that
|
||||
* may be called within the template.
|
||||
*
|
||||
* @param {Mixin} mixin
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitMixin: function(mixin){
|
||||
var name = 'jade_mixins[';
|
||||
var args = mixin.args || '';
|
||||
var block = mixin.block;
|
||||
var attrs = mixin.attrs;
|
||||
var attrsBlocks = mixin.attributeBlocks.slice();
|
||||
var pp = this.pp;
|
||||
var dynamic = mixin.name[0]==='#';
|
||||
var key = mixin.name;
|
||||
if (dynamic) this.dynamicMixins = true;
|
||||
name += (dynamic ? mixin.name.substr(2,mixin.name.length-3):'"'+mixin.name+'"')+']';
|
||||
|
||||
this.mixins[key] = this.mixins[key] || {used: false, instances: []};
|
||||
if (mixin.call) {
|
||||
this.mixins[key].used = true;
|
||||
if (pp) this.buf.push("jade_indent.push('" + Array(this.indents + 1).join(pp) + "');")
|
||||
if (block || attrs.length || attrsBlocks.length) {
|
||||
|
||||
this.buf.push(name + '.call({');
|
||||
|
||||
if (block) {
|
||||
this.buf.push('block: function(){');
|
||||
|
||||
// Render block with no indents, dynamically added when rendered
|
||||
this.parentIndents++;
|
||||
var _indents = this.indents;
|
||||
this.indents = 0;
|
||||
this.visit(mixin.block);
|
||||
this.indents = _indents;
|
||||
this.parentIndents--;
|
||||
|
||||
if (attrs.length || attrsBlocks.length) {
|
||||
this.buf.push('},');
|
||||
} else {
|
||||
this.buf.push('}');
|
||||
}
|
||||
}
|
||||
|
||||
if (attrsBlocks.length) {
|
||||
if (attrs.length) {
|
||||
var val = this.attrs(attrs);
|
||||
attrsBlocks.unshift(val);
|
||||
}
|
||||
this.buf.push('attributes: jade.merge([' + attrsBlocks.join(',') + '])');
|
||||
} else if (attrs.length) {
|
||||
var val = this.attrs(attrs);
|
||||
this.buf.push('attributes: ' + val);
|
||||
}
|
||||
|
||||
if (args) {
|
||||
this.buf.push('}, ' + args + ');');
|
||||
} else {
|
||||
this.buf.push('});');
|
||||
}
|
||||
|
||||
} else {
|
||||
this.buf.push(name + '(' + args + ');');
|
||||
}
|
||||
if (pp) this.buf.push("jade_indent.pop();")
|
||||
} else {
|
||||
var mixin_start = this.buf.length;
|
||||
args = args ? args.split(',') : [];
|
||||
var rest;
|
||||
if (args.length && /^\.\.\./.test(args[args.length - 1].trim())) {
|
||||
rest = args.pop().trim().replace(/^\.\.\./, '');
|
||||
}
|
||||
// we need use jade_interp here for v8: https://code.google.com/p/v8/issues/detail?id=4165
|
||||
// once fixed, use this: this.buf.push(name + ' = function(' + args.join(',') + '){');
|
||||
this.buf.push(name + ' = jade_interp = function(' + args.join(',') + '){');
|
||||
this.buf.push('var block = (this && this.block), attributes = (this && this.attributes) || {};');
|
||||
if (rest) {
|
||||
this.buf.push('var ' + rest + ' = [];');
|
||||
this.buf.push('for (jade_interp = ' + args.length + '; jade_interp < arguments.length; jade_interp++) {');
|
||||
this.buf.push(' ' + rest + '.push(arguments[jade_interp]);');
|
||||
this.buf.push('}');
|
||||
}
|
||||
this.parentIndents++;
|
||||
this.visit(block);
|
||||
this.parentIndents--;
|
||||
this.buf.push('};');
|
||||
var mixin_end = this.buf.length;
|
||||
this.mixins[key].instances.push({start: mixin_start, end: mixin_end});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `tag` buffering tag markup, generating
|
||||
* attributes, visiting the `tag`'s code and block.
|
||||
*
|
||||
* @param {Tag} tag
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitTag: function(tag){
|
||||
this.indents++;
|
||||
var name = tag.name
|
||||
, pp = this.pp
|
||||
, self = this;
|
||||
|
||||
function bufferName() {
|
||||
if (tag.buffer) self.bufferExpression(name);
|
||||
else self.buffer(name);
|
||||
}
|
||||
|
||||
if ('pre' == tag.name) this.escape = true;
|
||||
|
||||
if (!this.hasCompiledTag) {
|
||||
if (!this.hasCompiledDoctype && 'html' == name) {
|
||||
this.visitDoctype();
|
||||
}
|
||||
this.hasCompiledTag = true;
|
||||
}
|
||||
|
||||
// pretty print
|
||||
if (pp && !tag.isInline())
|
||||
this.prettyIndent(0, true);
|
||||
|
||||
if (tag.selfClosing || (!this.xml && selfClosing[tag.name])) {
|
||||
this.buffer('<');
|
||||
bufferName();
|
||||
this.visitAttributes(tag.attrs, tag.attributeBlocks.slice());
|
||||
this.terse
|
||||
? this.buffer('>')
|
||||
: this.buffer('/>');
|
||||
// if it is non-empty throw an error
|
||||
if (tag.block &&
|
||||
!(tag.block.type === 'Block' && tag.block.nodes.length === 0) &&
|
||||
tag.block.nodes.some(function (tag) {
|
||||
return tag.type !== 'Text' || !/^\s*$/.test(tag.val)
|
||||
})) {
|
||||
throw errorAtNode(tag, new Error(name + ' is self closing and should not have content.'));
|
||||
}
|
||||
} else {
|
||||
// Optimize attributes buffering
|
||||
this.buffer('<');
|
||||
bufferName();
|
||||
this.visitAttributes(tag.attrs, tag.attributeBlocks.slice());
|
||||
this.buffer('>');
|
||||
if (tag.code) this.visitCode(tag.code);
|
||||
this.visit(tag.block);
|
||||
|
||||
// pretty print
|
||||
if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline())
|
||||
this.prettyIndent(0, true);
|
||||
|
||||
this.buffer('</');
|
||||
bufferName();
|
||||
this.buffer('>');
|
||||
}
|
||||
|
||||
if ('pre' == tag.name) this.escape = false;
|
||||
|
||||
this.indents--;
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `filter`, throwing when the filter does not exist.
|
||||
*
|
||||
* @param {Filter} filter
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitFilter: function(filter){
|
||||
var text = filter.block.nodes.map(
|
||||
function(node){ return node.val; }
|
||||
).join('\n');
|
||||
filter.attrs.filename = this.options.filename;
|
||||
try {
|
||||
this.buffer(filters(filter.name, text, filter.attrs), true);
|
||||
} catch (err) {
|
||||
throw errorAtNode(filter, err);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `text` node.
|
||||
*
|
||||
* @param {Text} text
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitText: function(text){
|
||||
this.buffer(text.val, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit a `comment`, only buffering when the buffer flag is set.
|
||||
*
|
||||
* @param {Comment} comment
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitComment: function(comment){
|
||||
if (!comment.buffer) return;
|
||||
if (this.pp) this.prettyIndent(1, true);
|
||||
this.buffer('<!--' + comment.val + '-->');
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit a `BlockComment`.
|
||||
*
|
||||
* @param {Comment} comment
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitBlockComment: function(comment){
|
||||
if (!comment.buffer) return;
|
||||
if (this.pp) this.prettyIndent(1, true);
|
||||
this.buffer('<!--' + comment.val);
|
||||
this.visit(comment.block);
|
||||
if (this.pp) this.prettyIndent(1, true);
|
||||
this.buffer('-->');
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `code`, respecting buffer / escape flags.
|
||||
* If the code is followed by a block, wrap it in
|
||||
* a self-calling function.
|
||||
*
|
||||
* @param {Code} code
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitCode: function(code){
|
||||
// Wrap code blocks with {}.
|
||||
// we only wrap unbuffered code blocks ATM
|
||||
// since they are usually flow control
|
||||
|
||||
// Buffer code
|
||||
if (code.buffer) {
|
||||
var val = code.val.trim();
|
||||
val = 'null == (jade_interp = '+val+') ? "" : jade_interp';
|
||||
if (code.escape) val = 'jade.escape(' + val + ')';
|
||||
this.bufferExpression(val);
|
||||
} else {
|
||||
this.buf.push(code.val);
|
||||
}
|
||||
|
||||
// Block support
|
||||
if (code.block) {
|
||||
if (!code.buffer) this.buf.push('{');
|
||||
this.visit(code.block);
|
||||
if (!code.buffer) this.buf.push('}');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `each` block.
|
||||
*
|
||||
* @param {Each} each
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitEach: function(each){
|
||||
this.buf.push(''
|
||||
+ '// iterate ' + each.obj + '\n'
|
||||
+ ';(function(){\n'
|
||||
+ ' var $$obj = ' + each.obj + ';\n'
|
||||
+ ' if (\'number\' == typeof $$obj.length) {\n');
|
||||
|
||||
if (each.alternative) {
|
||||
this.buf.push(' if ($$obj.length) {');
|
||||
}
|
||||
|
||||
this.buf.push(''
|
||||
+ ' for (var ' + each.key + ' = 0, $$l = $$obj.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n'
|
||||
+ ' var ' + each.val + ' = $$obj[' + each.key + '];\n');
|
||||
|
||||
this.visit(each.block);
|
||||
|
||||
this.buf.push(' }\n');
|
||||
|
||||
if (each.alternative) {
|
||||
this.buf.push(' } else {');
|
||||
this.visit(each.alternative);
|
||||
this.buf.push(' }');
|
||||
}
|
||||
|
||||
this.buf.push(''
|
||||
+ ' } else {\n'
|
||||
+ ' var $$l = 0;\n'
|
||||
+ ' for (var ' + each.key + ' in $$obj) {\n'
|
||||
+ ' $$l++;'
|
||||
+ ' var ' + each.val + ' = $$obj[' + each.key + '];\n');
|
||||
|
||||
this.visit(each.block);
|
||||
|
||||
this.buf.push(' }\n');
|
||||
if (each.alternative) {
|
||||
this.buf.push(' if ($$l === 0) {');
|
||||
this.visit(each.alternative);
|
||||
this.buf.push(' }');
|
||||
}
|
||||
this.buf.push(' }\n}).call(this);\n');
|
||||
},
|
||||
|
||||
/**
|
||||
* Visit `attrs`.
|
||||
*
|
||||
* @param {Array} attrs
|
||||
* @api public
|
||||
*/
|
||||
|
||||
visitAttributes: function(attrs, attributeBlocks){
|
||||
if (attributeBlocks.length) {
|
||||
if (attrs.length) {
|
||||
var val = this.attrs(attrs);
|
||||
attributeBlocks.unshift(val);
|
||||
}
|
||||
this.bufferExpression('jade.attrs(jade.merge([' + attributeBlocks.join(',') + ']), ' + utils.stringify(this.terse) + ')');
|
||||
} else if (attrs.length) {
|
||||
this.attrs(attrs, true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Compile attributes.
|
||||
*/
|
||||
|
||||
attrs: function(attrs, buffer){
|
||||
var buf = [];
|
||||
var classes = [];
|
||||
var classEscaping = [];
|
||||
|
||||
attrs.forEach(function(attr){
|
||||
var key = attr.name;
|
||||
var escaped = attr.escaped;
|
||||
|
||||
if (key === 'class') {
|
||||
classes.push(attr.val);
|
||||
classEscaping.push(attr.escaped);
|
||||
} else if (isConstant(attr.val)) {
|
||||
if (buffer) {
|
||||
this.buffer(runtime.attr(key, toConstant(attr.val), escaped, this.terse));
|
||||
} else {
|
||||
var val = toConstant(attr.val);
|
||||
if (key === 'style') val = runtime.style(val);
|
||||
if (escaped && !(key.indexOf('data') === 0 && typeof val !== 'string')) {
|
||||
val = runtime.escape(val);
|
||||
}
|
||||
buf.push(utils.stringify(key) + ': ' + utils.stringify(val));
|
||||
}
|
||||
} else {
|
||||
if (buffer) {
|
||||
this.bufferExpression('jade.attr("' + key + '", ' + attr.val + ', ' + utils.stringify(escaped) + ', ' + utils.stringify(this.terse) + ')');
|
||||
} else {
|
||||
var val = attr.val;
|
||||
if (key === 'style') {
|
||||
val = 'jade.style(' + val + ')';
|
||||
}
|
||||
if (escaped && !(key.indexOf('data') === 0)) {
|
||||
val = 'jade.escape(' + val + ')';
|
||||
} else if (escaped) {
|
||||
val = '(typeof (jade_interp = ' + val + ') == "string" ? jade.escape(jade_interp) : jade_interp)';
|
||||
}
|
||||
buf.push(utils.stringify(key) + ': ' + val);
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
if (buffer) {
|
||||
if (classes.every(isConstant)) {
|
||||
this.buffer(runtime.cls(classes.map(toConstant), classEscaping));
|
||||
} else {
|
||||
this.bufferExpression('jade.cls([' + classes.join(',') + '], ' + utils.stringify(classEscaping) + ')');
|
||||
}
|
||||
} else if (classes.length) {
|
||||
if (classes.every(isConstant)) {
|
||||
classes = utils.stringify(runtime.joinClasses(classes.map(toConstant).map(runtime.joinClasses).map(function (cls, i) {
|
||||
return classEscaping[i] ? runtime.escape(cls) : cls;
|
||||
})));
|
||||
} else {
|
||||
classes = '(jade_interp = ' + utils.stringify(classEscaping) + ',' +
|
||||
' jade.joinClasses([' + classes.join(',') + '].map(jade.joinClasses).map(function (cls, i) {' +
|
||||
' return jade_interp[i] ? jade.escape(cls) : cls' +
|
||||
' }))' +
|
||||
')';
|
||||
}
|
||||
if (classes.length)
|
||||
buf.push('"class": ' + classes);
|
||||
}
|
||||
return '{' + buf.join(',') + '}';
|
||||
}
|
||||
};
|
||||
12
node_modules/jade/lib/doctypes.js
generated
vendored
Normal file
12
node_modules/jade/lib/doctypes.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
'default': '<!DOCTYPE html>'
|
||||
, 'xml': '<?xml version="1.0" encoding="utf-8" ?>'
|
||||
, 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
|
||||
, 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
||||
, 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'
|
||||
, '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
|
||||
, 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">'
|
||||
, 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
|
||||
};
|
||||
10
node_modules/jade/lib/filters-client.js
generated
vendored
Normal file
10
node_modules/jade/lib/filters-client.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = filter;
|
||||
function filter(name, str, options) {
|
||||
if (typeof filter[name] === 'function') {
|
||||
return filter[name](str, options);
|
||||
} else {
|
||||
throw new Error('unknown filter ":' + name + '"');
|
||||
}
|
||||
}
|
||||
96
node_modules/jade/lib/filters.js
generated
vendored
Normal file
96
node_modules/jade/lib/filters.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
'use strict';
|
||||
|
||||
var transformers = require('transformers');
|
||||
var jstransformer = require('jstransformer');
|
||||
var uglify = require('uglify-js');
|
||||
var CleanCSS = require('clean-css');
|
||||
|
||||
var warned = {};
|
||||
var alternatives = {
|
||||
uglifyJS: 'uglify-js',
|
||||
uglify: 'uglify-js',
|
||||
uglifyCSS: 'clean-css',
|
||||
'uglify-css': 'clean-css' ,
|
||||
uglifyJSON: 'json',
|
||||
'uglify-json': 'json',
|
||||
live: 'livescript',
|
||||
LiveScript: 'livescript',
|
||||
ls: 'livescript',
|
||||
// TODO: remove if we add support for coffeekup
|
||||
coffeekup: 'coffeecup',
|
||||
// The `style` transformer is not the same as the `stylus` jstransformer
|
||||
styl: 'stylus',
|
||||
coffee: 'coffee-script',
|
||||
coffeescript: 'coffee-script',
|
||||
coffeeScript: 'coffee-script',
|
||||
// these marker transformers haven't made sense in a long time
|
||||
css: 'verbatim',
|
||||
js: 'verbatim',
|
||||
};
|
||||
var deprecated = ['jqtpl', 'jazz'];
|
||||
function getMarkdownImplementation() {
|
||||
var implementations = ['marked', 'supermarked', 'markdown-js', 'markdown'];
|
||||
while (implementations.length) {
|
||||
try {
|
||||
require(implementations[0]);
|
||||
return implementations[0];
|
||||
} catch (ex) {
|
||||
implementations.shift();
|
||||
}
|
||||
}
|
||||
return 'markdown-it';
|
||||
}
|
||||
|
||||
module.exports = filter;
|
||||
function filter(name, str, options) {
|
||||
if (typeof filter[name] === 'function') {
|
||||
return filter[name](str, options);
|
||||
} else {
|
||||
var tr;
|
||||
try {
|
||||
tr = jstransformer(require('jstransformer-' + name));
|
||||
} catch (ex) {}
|
||||
if (tr) {
|
||||
// TODO: we may want to add a way for people to separately specify "locals"
|
||||
var result = tr.render(str, options, options).body;
|
||||
if (options && options.minify) {
|
||||
try {
|
||||
switch (tr.outputFormat) {
|
||||
case 'js':
|
||||
result = uglify.minify(result, {fromString: true}).code;
|
||||
break;
|
||||
case 'css':
|
||||
result = new CleanCSS().minify(result).styles;
|
||||
break;
|
||||
}
|
||||
} catch (ex) {
|
||||
// better to fail to minify than output nothing
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (transformers[name]) {
|
||||
if (!warned[name]) {
|
||||
warned[name] = true;
|
||||
if (name === 'md' || name === 'markdown') {
|
||||
var implementation = getMarkdownImplementation();
|
||||
console.log('Transformers.' + name + ' is deprecated, you must replace the :' +
|
||||
name + ' jade filter, with :' +
|
||||
implementation + ' and install jstransformer-' +
|
||||
implementation + ' before you update to jade@2.0.0.');
|
||||
} else if (alternatives[name]) {
|
||||
console.log('Transformers.' + name + ' is deprecated, you must replace the :' +
|
||||
name + ' jade filter, with :' +
|
||||
alternatives[name] + ' and install jstransformer-' +
|
||||
alternatives[name] + ' before you update to jade@2.0.0.');
|
||||
} else {
|
||||
console.log('Transformers.' + name + ' is deprecated, to continue using the :' +
|
||||
name + ' jade filter after jade@2.0.0, you will need to install jstransformer-' +
|
||||
name.toLowerCase() + '.');
|
||||
}
|
||||
}
|
||||
return transformers[name].renderSync(str, options);
|
||||
} else {
|
||||
throw new Error('unknown filter ":' + name + '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
418
node_modules/jade/lib/index.js
generated
vendored
Normal file
418
node_modules/jade/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,418 @@
|
||||
'use strict';
|
||||
|
||||
/*!
|
||||
* Jade
|
||||
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Parser = require('./parser')
|
||||
, Lexer = require('./lexer')
|
||||
, Compiler = require('./compiler')
|
||||
, runtime = require('./runtime')
|
||||
, addWith = require('with')
|
||||
, fs = require('fs')
|
||||
, utils = require('./utils');
|
||||
|
||||
/**
|
||||
* Expose self closing tags.
|
||||
*/
|
||||
|
||||
// FIXME: either stop exporting selfClosing in v2 or export the new object
|
||||
// form
|
||||
exports.selfClosing = Object.keys(require('void-elements'));
|
||||
|
||||
/**
|
||||
* Default supported doctypes.
|
||||
*/
|
||||
|
||||
exports.doctypes = require('./doctypes');
|
||||
|
||||
/**
|
||||
* Text filters.
|
||||
*/
|
||||
|
||||
exports.filters = require('./filters');
|
||||
|
||||
/**
|
||||
* Utilities.
|
||||
*/
|
||||
|
||||
exports.utils = utils;
|
||||
|
||||
/**
|
||||
* Expose `Compiler`.
|
||||
*/
|
||||
|
||||
exports.Compiler = Compiler;
|
||||
|
||||
/**
|
||||
* Expose `Parser`.
|
||||
*/
|
||||
|
||||
exports.Parser = Parser;
|
||||
|
||||
/**
|
||||
* Expose `Lexer`.
|
||||
*/
|
||||
|
||||
exports.Lexer = Lexer;
|
||||
|
||||
/**
|
||||
* Nodes.
|
||||
*/
|
||||
|
||||
exports.nodes = require('./nodes');
|
||||
|
||||
/**
|
||||
* Jade runtime helpers.
|
||||
*/
|
||||
|
||||
exports.runtime = runtime;
|
||||
|
||||
/**
|
||||
* Template function cache.
|
||||
*/
|
||||
|
||||
exports.cache = {};
|
||||
|
||||
/**
|
||||
* Parse the given `str` of jade and return a function body.
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Object} options
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function parse(str, options){
|
||||
|
||||
if (options.lexer) {
|
||||
console.warn('Using `lexer` as a local in render() is deprecated and '
|
||||
+ 'will be interpreted as an option in Jade 2.0.0');
|
||||
}
|
||||
|
||||
// Parse
|
||||
var parser = new (options.parser || Parser)(str, options.filename, options);
|
||||
var tokens;
|
||||
try {
|
||||
// Parse
|
||||
tokens = parser.parse();
|
||||
} catch (err) {
|
||||
parser = parser.context();
|
||||
runtime.rethrow(err, parser.filename, parser.lexer.lineno, parser.input);
|
||||
}
|
||||
|
||||
// Compile
|
||||
var compiler = new (options.compiler || Compiler)(tokens, options);
|
||||
var js;
|
||||
try {
|
||||
js = compiler.compile();
|
||||
} catch (err) {
|
||||
if (err.line && (err.filename || !options.filename)) {
|
||||
runtime.rethrow(err, err.filename, err.line, parser.input);
|
||||
} else {
|
||||
if (err instanceof Error) {
|
||||
err.message += '\n\nPlease report this entire error and stack trace to https://github.com/jadejs/jade/issues';
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Debug compiler
|
||||
if (options.debug) {
|
||||
console.error('\nCompiled Function:\n\n\u001b[90m%s\u001b[0m', js.replace(/^/gm, ' '));
|
||||
}
|
||||
|
||||
var globals = [];
|
||||
|
||||
if (options.globals) {
|
||||
globals = options.globals.slice();
|
||||
}
|
||||
|
||||
globals.push('jade');
|
||||
globals.push('jade_mixins');
|
||||
globals.push('jade_interp');
|
||||
globals.push('jade_debug');
|
||||
globals.push('buf');
|
||||
|
||||
var body = ''
|
||||
+ 'var buf = [];\n'
|
||||
+ 'var jade_mixins = {};\n'
|
||||
+ 'var jade_interp;\n'
|
||||
+ (options.self
|
||||
? 'var self = locals || {};\n' + js
|
||||
: addWith('locals || {}', '\n' + js, globals)) + ';'
|
||||
+ 'return buf.join("");';
|
||||
return {body: body, dependencies: parser.dependencies};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the template from a string or a file, either compiled on-the-fly or
|
||||
* read from cache (if enabled), and cache the template if needed.
|
||||
*
|
||||
* If `str` is not set, the file specified in `options.filename` will be read.
|
||||
*
|
||||
* If `options.cache` is true, this function reads the file from
|
||||
* `options.filename` so it must be set prior to calling this function.
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {String=} str
|
||||
* @return {Function}
|
||||
* @api private
|
||||
*/
|
||||
function handleTemplateCache (options, str) {
|
||||
var key = options.filename;
|
||||
if (options.cache && exports.cache[key]) {
|
||||
return exports.cache[key];
|
||||
} else {
|
||||
if (str === undefined) str = fs.readFileSync(options.filename, 'utf8');
|
||||
var templ = exports.compile(str, options);
|
||||
if (options.cache) exports.cache[key] = templ;
|
||||
return templ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a `Function` representation of the given jade `str`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `compileDebug` when `false` debugging code is stripped from the compiled
|
||||
template, when it is explicitly `true`, the source code is included in
|
||||
the compiled template for better accuracy.
|
||||
* - `filename` used to improve errors when `compileDebug` is not `false` and to resolve imports/extends
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Options} options
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.compile = function(str, options){
|
||||
var options = options || {}
|
||||
, filename = options.filename
|
||||
? utils.stringify(options.filename)
|
||||
: 'undefined'
|
||||
, fn;
|
||||
|
||||
str = String(str);
|
||||
|
||||
var parsed = parse(str, options);
|
||||
if (options.compileDebug !== false) {
|
||||
fn = [
|
||||
'var jade_debug = [ new jade.DebugItem( 1, ' + filename + ' ) ];'
|
||||
, 'try {'
|
||||
, parsed.body
|
||||
, '} catch (err) {'
|
||||
, ' jade.rethrow(err, jade_debug[0].filename, jade_debug[0].lineno' + (options.compileDebug === true ? ',' + utils.stringify(str) : '') + ');'
|
||||
, '}'
|
||||
].join('\n');
|
||||
} else {
|
||||
fn = parsed.body;
|
||||
}
|
||||
fn = new Function('locals, jade', fn)
|
||||
var res = function(locals){ return fn(locals, Object.create(runtime)) };
|
||||
if (options.client) {
|
||||
res.toString = function () {
|
||||
var err = new Error('The `client` option is deprecated, use the `jade.compileClient` method instead');
|
||||
err.name = 'Warning';
|
||||
console.error(err.stack || /* istanbul ignore next */ err.message);
|
||||
return exports.compileClient(str, options);
|
||||
};
|
||||
}
|
||||
res.dependencies = parsed.dependencies;
|
||||
return res;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compile a JavaScript source representation of the given jade `str`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `compileDebug` When it is `true`, the source code is included in
|
||||
* the compiled template for better error messages.
|
||||
* - `filename` used to improve errors when `compileDebug` is not `true` and to resolve imports/extends
|
||||
* - `name` the name of the resulting function (defaults to "template")
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Options} options
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.compileClientWithDependenciesTracked = function(str, options){
|
||||
var options = options || {};
|
||||
var name = options.name || 'template';
|
||||
var filename = options.filename ? utils.stringify(options.filename) : 'undefined';
|
||||
var fn;
|
||||
|
||||
str = String(str);
|
||||
options.compileDebug = options.compileDebug ? true : false;
|
||||
var parsed = parse(str, options);
|
||||
if (options.compileDebug) {
|
||||
fn = [
|
||||
'var jade_debug = [ new jade.DebugItem( 1, ' + filename + ' ) ];'
|
||||
, 'try {'
|
||||
, parsed.body
|
||||
, '} catch (err) {'
|
||||
, ' jade.rethrow(err, jade_debug[0].filename, jade_debug[0].lineno, ' + utils.stringify(str) + ');'
|
||||
, '}'
|
||||
].join('\n');
|
||||
} else {
|
||||
fn = parsed.body;
|
||||
}
|
||||
|
||||
return {body: 'function ' + name + '(locals) {\n' + fn + '\n}', dependencies: parsed.dependencies};
|
||||
};
|
||||
|
||||
/**
|
||||
* Compile a JavaScript source representation of the given jade `str`.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `compileDebug` When it is `true`, the source code is included in
|
||||
* the compiled template for better error messages.
|
||||
* - `filename` used to improve errors when `compileDebug` is not `true` and to resolve imports/extends
|
||||
* - `name` the name of the resulting function (defaults to "template")
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Options} options
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
exports.compileClient = function (str, options) {
|
||||
return exports.compileClientWithDependenciesTracked(str, options).body;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compile a `Function` representation of the given jade file.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `compileDebug` when `false` debugging code is stripped from the compiled
|
||||
template, when it is explicitly `true`, the source code is included in
|
||||
the compiled template for better accuracy.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Options} options
|
||||
* @return {Function}
|
||||
* @api public
|
||||
*/
|
||||
exports.compileFile = function (path, options) {
|
||||
options = options || {};
|
||||
options.filename = path;
|
||||
return handleTemplateCache(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the given `str` of jade.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - `cache` enable template caching
|
||||
* - `filename` filename required for `include` / `extends` and caching
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {Object|Function} options or fn
|
||||
* @param {Function|undefined} fn
|
||||
* @returns {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.render = function(str, options, fn){
|
||||
// support callback API
|
||||
if ('function' == typeof options) {
|
||||
fn = options, options = undefined;
|
||||
}
|
||||
if (typeof fn === 'function') {
|
||||
var res
|
||||
try {
|
||||
res = exports.render(str, options);
|
||||
} catch (ex) {
|
||||
return fn(ex);
|
||||
}
|
||||
return fn(null, res);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
// cache requires .filename
|
||||
if (options.cache && !options.filename) {
|
||||
throw new Error('the "filename" option is required for caching');
|
||||
}
|
||||
|
||||
return handleTemplateCache(options, str)(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Render a Jade file at the given `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Object|Function} options or callback
|
||||
* @param {Function|undefined} fn
|
||||
* @returns {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.renderFile = function(path, options, fn){
|
||||
// support callback API
|
||||
if ('function' == typeof options) {
|
||||
fn = options, options = undefined;
|
||||
}
|
||||
if (typeof fn === 'function') {
|
||||
var res
|
||||
try {
|
||||
res = exports.renderFile(path, options);
|
||||
} catch (ex) {
|
||||
return fn(ex);
|
||||
}
|
||||
return fn(null, res);
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
options.filename = path;
|
||||
return handleTemplateCache(options)(options);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compile a Jade file at the given `path` for use on the client.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Object} options
|
||||
* @returns {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.compileFileClient = function(path, options){
|
||||
var key = path + ':client';
|
||||
options = options || {};
|
||||
|
||||
options.filename = path;
|
||||
|
||||
if (options.cache && exports.cache[key]) {
|
||||
return exports.cache[key];
|
||||
}
|
||||
|
||||
var str = fs.readFileSync(options.filename, 'utf8');
|
||||
var out = exports.compileClient(str, options);
|
||||
if (options.cache) exports.cache[key] = out;
|
||||
return out;
|
||||
};
|
||||
|
||||
/**
|
||||
* Express support.
|
||||
*/
|
||||
|
||||
exports.__express = function(path, options, fn) {
|
||||
if(options.compileDebug == undefined && process.env.NODE_ENV === 'production') {
|
||||
options.compileDebug = false;
|
||||
}
|
||||
exports.renderFile(path, options, fn);
|
||||
}
|
||||
23
node_modules/jade/lib/inline-tags.js
generated
vendored
Normal file
23
node_modules/jade/lib/inline-tags.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = [
|
||||
'a'
|
||||
, 'abbr'
|
||||
, 'acronym'
|
||||
, 'b'
|
||||
, 'br'
|
||||
, 'code'
|
||||
, 'em'
|
||||
, 'font'
|
||||
, 'i'
|
||||
, 'img'
|
||||
, 'ins'
|
||||
, 'kbd'
|
||||
, 'map'
|
||||
, 'samp'
|
||||
, 'small'
|
||||
, 'span'
|
||||
, 'strong'
|
||||
, 'sub'
|
||||
, 'sup'
|
||||
];
|
||||
949
node_modules/jade/lib/lexer.js
generated
vendored
Normal file
949
node_modules/jade/lib/lexer.js
generated
vendored
Normal file
@@ -0,0 +1,949 @@
|
||||
'use strict';
|
||||
|
||||
var utils = require('./utils');
|
||||
var characterParser = require('character-parser');
|
||||
|
||||
|
||||
/**
|
||||
* Initialize `Lexer` with the given `str`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {String} filename
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var Lexer = module.exports = function Lexer(str, filename) {
|
||||
this.input = str.replace(/\r\n|\r/g, '\n');
|
||||
this.filename = filename;
|
||||
this.deferredTokens = [];
|
||||
this.lastIndents = 0;
|
||||
this.lineno = 1;
|
||||
this.stash = [];
|
||||
this.indentStack = [];
|
||||
this.indentRe = null;
|
||||
this.pipeless = false;
|
||||
};
|
||||
|
||||
|
||||
function assertExpression(exp) {
|
||||
//this verifies that a JavaScript expression is valid
|
||||
Function('', 'return (' + exp + ')');
|
||||
}
|
||||
function assertNestingCorrect(exp) {
|
||||
//this verifies that code is properly nested, but allows
|
||||
//invalid JavaScript such as the contents of `attributes`
|
||||
var res = characterParser(exp)
|
||||
if (res.isNesting()) {
|
||||
throw new Error('Nesting must match on expression `' + exp + '`')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lexer prototype.
|
||||
*/
|
||||
|
||||
Lexer.prototype = {
|
||||
|
||||
/**
|
||||
* Construct a token with the given `type` and `val`.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {String} val
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
tok: function(type, val){
|
||||
return {
|
||||
type: type
|
||||
, line: this.lineno
|
||||
, val: val
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Consume the given `len` of input.
|
||||
*
|
||||
* @param {Number} len
|
||||
* @api private
|
||||
*/
|
||||
|
||||
consume: function(len){
|
||||
this.input = this.input.substr(len);
|
||||
},
|
||||
|
||||
/**
|
||||
* Scan for `type` with the given `regexp`.
|
||||
*
|
||||
* @param {String} type
|
||||
* @param {RegExp} regexp
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
scan: function(regexp, type){
|
||||
var captures;
|
||||
if (captures = regexp.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
return this.tok(type, captures[1]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Defer the given `tok`.
|
||||
*
|
||||
* @param {Object} tok
|
||||
* @api private
|
||||
*/
|
||||
|
||||
defer: function(tok){
|
||||
this.deferredTokens.push(tok);
|
||||
},
|
||||
|
||||
/**
|
||||
* Lookahead `n` tokens.
|
||||
*
|
||||
* @param {Number} n
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
lookahead: function(n){
|
||||
var fetch = n - this.stash.length;
|
||||
while (fetch-- > 0) this.stash.push(this.next());
|
||||
return this.stash[--n];
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the indexOf `(` or `{` or `[` / `)` or `}` or `]` delimiters.
|
||||
*
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
bracketExpression: function(skip){
|
||||
skip = skip || 0;
|
||||
var start = this.input[skip];
|
||||
if (start != '(' && start != '{' && start != '[') throw new Error('unrecognized start character');
|
||||
var end = ({'(': ')', '{': '}', '[': ']'})[start];
|
||||
var range = characterParser.parseMax(this.input, {start: skip + 1});
|
||||
if (this.input[range.end] !== end) throw new Error('start character ' + start + ' does not match end character ' + this.input[range.end]);
|
||||
return range;
|
||||
},
|
||||
|
||||
/**
|
||||
* Stashed token.
|
||||
*/
|
||||
|
||||
stashed: function() {
|
||||
return this.stash.length
|
||||
&& this.stash.shift();
|
||||
},
|
||||
|
||||
/**
|
||||
* Deferred token.
|
||||
*/
|
||||
|
||||
deferred: function() {
|
||||
return this.deferredTokens.length
|
||||
&& this.deferredTokens.shift();
|
||||
},
|
||||
|
||||
/**
|
||||
* end-of-source.
|
||||
*/
|
||||
|
||||
eos: function() {
|
||||
if (this.input.length) return;
|
||||
if (this.indentStack.length) {
|
||||
this.indentStack.shift();
|
||||
return this.tok('outdent');
|
||||
} else {
|
||||
return this.tok('eos');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Blank line.
|
||||
*/
|
||||
|
||||
blank: function() {
|
||||
var captures;
|
||||
if (captures = /^\n *\n/.exec(this.input)) {
|
||||
this.consume(captures[0].length - 1);
|
||||
++this.lineno;
|
||||
if (this.pipeless) return this.tok('text', '');
|
||||
return this.next();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Comment.
|
||||
*/
|
||||
|
||||
comment: function() {
|
||||
var captures;
|
||||
if (captures = /^\/\/(-)?([^\n]*)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var tok = this.tok('comment', captures[2]);
|
||||
tok.buffer = '-' != captures[1];
|
||||
this.pipeless = true;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Interpolated tag.
|
||||
*/
|
||||
|
||||
interpolation: function() {
|
||||
if (/^#\{/.test(this.input)) {
|
||||
var match = this.bracketExpression(1);
|
||||
|
||||
this.consume(match.end + 1);
|
||||
return this.tok('interpolation', match.src);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Tag.
|
||||
*/
|
||||
|
||||
tag: function() {
|
||||
var captures;
|
||||
if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var tok, name = captures[1];
|
||||
if (':' == name[name.length - 1]) {
|
||||
name = name.slice(0, -1);
|
||||
tok = this.tok('tag', name);
|
||||
this.defer(this.tok(':'));
|
||||
if (this.input[0] !== ' ') {
|
||||
console.warn('Warning: space required after `:` on line ' + this.lineno +
|
||||
' of jade file "' + this.filename + '"');
|
||||
}
|
||||
while (' ' == this.input[0]) this.input = this.input.substr(1);
|
||||
} else {
|
||||
tok = this.tok('tag', name);
|
||||
}
|
||||
tok.selfClosing = !!captures[2];
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter.
|
||||
*/
|
||||
|
||||
filter: function() {
|
||||
var tok = this.scan(/^:([\w\-]+)/, 'filter');
|
||||
if (tok) {
|
||||
this.pipeless = true;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Doctype.
|
||||
*/
|
||||
|
||||
doctype: function() {
|
||||
if (this.scan(/^!!! *([^\n]+)?/, 'doctype')) {
|
||||
throw new Error('`!!!` is deprecated, you must now use `doctype`');
|
||||
}
|
||||
var node = this.scan(/^(?:doctype) *([^\n]+)?/, 'doctype');
|
||||
if (node && node.val && node.val.trim() === '5') {
|
||||
throw new Error('`doctype 5` is deprecated, you must now use `doctype html`');
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Id.
|
||||
*/
|
||||
|
||||
id: function() {
|
||||
return this.scan(/^#([\w-]+)/, 'id');
|
||||
},
|
||||
|
||||
/**
|
||||
* Class.
|
||||
*/
|
||||
|
||||
className: function() {
|
||||
return this.scan(/^\.([\w-]+)/, 'class');
|
||||
},
|
||||
|
||||
/**
|
||||
* Text.
|
||||
*/
|
||||
|
||||
text: function() {
|
||||
return this.scan(/^(?:\| ?| )([^\n]+)/, 'text') ||
|
||||
this.scan(/^\|?( )/, 'text') ||
|
||||
this.scan(/^(<[^\n]*)/, 'text');
|
||||
},
|
||||
|
||||
textFail: function () {
|
||||
var tok;
|
||||
if (tok = this.scan(/^([^\.\n][^\n]+)/, 'text')) {
|
||||
console.warn('Warning: missing space before text for line ' + this.lineno +
|
||||
' of jade file "' + this.filename + '"');
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Dot.
|
||||
*/
|
||||
|
||||
dot: function() {
|
||||
var match;
|
||||
if (match = this.scan(/^\./, 'dot')) {
|
||||
this.pipeless = true;
|
||||
return match;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends.
|
||||
*/
|
||||
|
||||
"extends": function() {
|
||||
return this.scan(/^extends? +([^\n]+)/, 'extends');
|
||||
},
|
||||
|
||||
/**
|
||||
* Block prepend.
|
||||
*/
|
||||
|
||||
prepend: function() {
|
||||
var captures;
|
||||
if (captures = /^prepend +([^\n]+)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var mode = 'prepend'
|
||||
, name = captures[1]
|
||||
, tok = this.tok('block', name);
|
||||
tok.mode = mode;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Block append.
|
||||
*/
|
||||
|
||||
append: function() {
|
||||
var captures;
|
||||
if (captures = /^append +([^\n]+)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var mode = 'append'
|
||||
, name = captures[1]
|
||||
, tok = this.tok('block', name);
|
||||
tok.mode = mode;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Block.
|
||||
*/
|
||||
|
||||
block: function() {
|
||||
var captures;
|
||||
if (captures = /^block\b *(?:(prepend|append) +)?([^\n]+)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var mode = captures[1] || 'replace'
|
||||
, name = captures[2]
|
||||
, tok = this.tok('block', name);
|
||||
|
||||
tok.mode = mode;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Mixin Block.
|
||||
*/
|
||||
|
||||
mixinBlock: function() {
|
||||
var captures;
|
||||
if (captures = /^block[ \t]*(\n|$)/.exec(this.input)) {
|
||||
this.consume(captures[0].length - captures[1].length);
|
||||
return this.tok('mixin-block');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Yield.
|
||||
*/
|
||||
|
||||
'yield': function() {
|
||||
return this.scan(/^yield */, 'yield');
|
||||
},
|
||||
|
||||
/**
|
||||
* Include.
|
||||
*/
|
||||
|
||||
include: function() {
|
||||
return this.scan(/^include +([^\n]+)/, 'include');
|
||||
},
|
||||
|
||||
/**
|
||||
* Include with filter
|
||||
*/
|
||||
|
||||
includeFiltered: function() {
|
||||
var captures;
|
||||
if (captures = /^include:([\w\-]+)([\( ])/.exec(this.input)) {
|
||||
this.consume(captures[0].length - 1);
|
||||
var filter = captures[1];
|
||||
var attrs = captures[2] === '(' ? this.attrs() : null;
|
||||
if (!(captures[2] === ' ' || this.input[0] === ' ')) {
|
||||
throw new Error('expected space after include:filter but got ' + utils.stringify(this.input[0]));
|
||||
}
|
||||
captures = /^ *([^\n]+)/.exec(this.input);
|
||||
if (!captures || captures[1].trim() === '') {
|
||||
throw new Error('missing path for include:filter');
|
||||
}
|
||||
this.consume(captures[0].length);
|
||||
var path = captures[1];
|
||||
var tok = this.tok('include', path);
|
||||
tok.filter = filter;
|
||||
tok.attrs = attrs;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Case.
|
||||
*/
|
||||
|
||||
"case": function() {
|
||||
return this.scan(/^case +([^\n]+)/, 'case');
|
||||
},
|
||||
|
||||
/**
|
||||
* When.
|
||||
*/
|
||||
|
||||
when: function() {
|
||||
return this.scan(/^when +([^:\n]+)/, 'when');
|
||||
},
|
||||
|
||||
/**
|
||||
* Default.
|
||||
*/
|
||||
|
||||
"default": function() {
|
||||
return this.scan(/^default */, 'default');
|
||||
},
|
||||
|
||||
/**
|
||||
* Call mixin.
|
||||
*/
|
||||
|
||||
call: function(){
|
||||
|
||||
var tok, captures;
|
||||
if (captures = /^\+(\s*)(([-\w]+)|(#\{))/.exec(this.input)) {
|
||||
// try to consume simple or interpolated call
|
||||
if (captures[3]) {
|
||||
// simple call
|
||||
this.consume(captures[0].length);
|
||||
tok = this.tok('call', captures[3]);
|
||||
} else {
|
||||
// interpolated call
|
||||
var match = this.bracketExpression(2 + captures[1].length);
|
||||
this.consume(match.end + 1);
|
||||
assertExpression(match.src);
|
||||
tok = this.tok('call', '#{'+match.src+'}');
|
||||
}
|
||||
|
||||
// Check for args (not attributes)
|
||||
if (captures = /^ *\(/.exec(this.input)) {
|
||||
var range = this.bracketExpression(captures[0].length - 1);
|
||||
if (!/^\s*[-\w]+ *=/.test(range.src)) { // not attributes
|
||||
this.consume(range.end + 1);
|
||||
tok.args = range.src;
|
||||
}
|
||||
if (tok.args) {
|
||||
assertExpression('[' + tok.args + ']');
|
||||
}
|
||||
}
|
||||
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Mixin.
|
||||
*/
|
||||
|
||||
mixin: function(){
|
||||
var captures;
|
||||
if (captures = /^mixin +([-\w]+)(?: *\((.*)\))? */.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var tok = this.tok('mixin', captures[1]);
|
||||
tok.args = captures[2];
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Conditional.
|
||||
*/
|
||||
|
||||
conditional: function() {
|
||||
var captures;
|
||||
if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var type = captures[1]
|
||||
var js = captures[2];
|
||||
var isIf = false;
|
||||
var isElse = false;
|
||||
|
||||
switch (type) {
|
||||
case 'if':
|
||||
assertExpression(js)
|
||||
js = 'if (' + js + ')';
|
||||
isIf = true;
|
||||
break;
|
||||
case 'unless':
|
||||
assertExpression(js)
|
||||
js = 'if (!(' + js + '))';
|
||||
isIf = true;
|
||||
break;
|
||||
case 'else if':
|
||||
assertExpression(js)
|
||||
js = 'else if (' + js + ')';
|
||||
isIf = true;
|
||||
isElse = true;
|
||||
break;
|
||||
case 'else':
|
||||
if (js && js.trim()) {
|
||||
throw new Error('`else` cannot have a condition, perhaps you meant `else if`');
|
||||
}
|
||||
js = 'else';
|
||||
isElse = true;
|
||||
break;
|
||||
}
|
||||
var tok = this.tok('code', js);
|
||||
tok.isElse = isElse;
|
||||
tok.isIf = isIf;
|
||||
tok.requiresBlock = true;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* While.
|
||||
*/
|
||||
|
||||
"while": function() {
|
||||
var captures;
|
||||
if (captures = /^while +([^\n]+)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
assertExpression(captures[1])
|
||||
var tok = this.tok('code', 'while (' + captures[1] + ')');
|
||||
tok.requiresBlock = true;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Each.
|
||||
*/
|
||||
|
||||
each: function() {
|
||||
var captures;
|
||||
if (captures = /^(?:- *)?(?:each|for) +([a-zA-Z_$][\w$]*)(?: *, *([a-zA-Z_$][\w$]*))? * in *([^\n]+)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var tok = this.tok('each', captures[1]);
|
||||
tok.key = captures[2] || '$index';
|
||||
assertExpression(captures[3])
|
||||
tok.code = captures[3];
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Code.
|
||||
*/
|
||||
|
||||
code: function() {
|
||||
var captures;
|
||||
if (captures = /^(!?=|-)[ \t]*([^\n]+)/.exec(this.input)) {
|
||||
this.consume(captures[0].length);
|
||||
var flags = captures[1];
|
||||
captures[1] = captures[2];
|
||||
var tok = this.tok('code', captures[1]);
|
||||
tok.escape = flags.charAt(0) === '=';
|
||||
tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '=';
|
||||
if (tok.buffer) assertExpression(captures[1])
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Block code.
|
||||
*/
|
||||
|
||||
blockCode: function() {
|
||||
var captures;
|
||||
if (captures = /^-\n/.exec(this.input)) {
|
||||
this.consume(captures[0].length - 1);
|
||||
var tok = this.tok('blockCode');
|
||||
this.pipeless = true;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Attributes.
|
||||
*/
|
||||
|
||||
attrs: function() {
|
||||
if ('(' == this.input.charAt(0)) {
|
||||
var index = this.bracketExpression().end
|
||||
, str = this.input.substr(1, index-1)
|
||||
, tok = this.tok('attrs');
|
||||
|
||||
assertNestingCorrect(str);
|
||||
|
||||
var quote = '';
|
||||
var interpolate = function (attr) {
|
||||
return attr.replace(/(\\)?#\{(.+)/g, function(_, escape, expr){
|
||||
if (escape) return _;
|
||||
try {
|
||||
var range = characterParser.parseMax(expr);
|
||||
if (expr[range.end] !== '}') return _.substr(0, 2) + interpolate(_.substr(2));
|
||||
assertExpression(range.src)
|
||||
return quote + " + (" + range.src + ") + " + quote + interpolate(expr.substr(range.end + 1));
|
||||
} catch (ex) {
|
||||
return _.substr(0, 2) + interpolate(_.substr(2));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.consume(index + 1);
|
||||
tok.attrs = [];
|
||||
|
||||
var escapedAttr = true
|
||||
var key = '';
|
||||
var val = '';
|
||||
var interpolatable = '';
|
||||
var state = characterParser.defaultState();
|
||||
var loc = 'key';
|
||||
var isEndOfAttribute = function (i) {
|
||||
if (key.trim() === '') return false;
|
||||
if (i === str.length) return true;
|
||||
if (loc === 'key') {
|
||||
if (str[i] === ' ' || str[i] === '\n') {
|
||||
for (var x = i; x < str.length; x++) {
|
||||
if (str[x] != ' ' && str[x] != '\n') {
|
||||
if (str[x] === '=' || str[x] === '!' || str[x] === ',') return false;
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str[i] === ','
|
||||
} else if (loc === 'value' && !state.isNesting()) {
|
||||
try {
|
||||
assertExpression(val);
|
||||
if (str[i] === ' ' || str[i] === '\n') {
|
||||
for (var x = i; x < str.length; x++) {
|
||||
if (str[x] != ' ' && str[x] != '\n') {
|
||||
if (characterParser.isPunctuator(str[x]) && str[x] != '"' && str[x] != "'") return false;
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str[i] === ',';
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.lineno += str.split("\n").length - 1;
|
||||
|
||||
for (var i = 0; i <= str.length; i++) {
|
||||
if (isEndOfAttribute(i)) {
|
||||
val = val.trim();
|
||||
if (val) assertExpression(val)
|
||||
key = key.trim();
|
||||
key = key.replace(/^['"]|['"]$/g, '');
|
||||
tok.attrs.push({
|
||||
name: key,
|
||||
val: '' == val ? true : val,
|
||||
escaped: escapedAttr
|
||||
});
|
||||
key = val = '';
|
||||
loc = 'key';
|
||||
escapedAttr = false;
|
||||
} else {
|
||||
switch (loc) {
|
||||
case 'key-char':
|
||||
if (str[i] === quote) {
|
||||
loc = 'key';
|
||||
if (i + 1 < str.length && [' ', ',', '!', '=', '\n'].indexOf(str[i + 1]) === -1)
|
||||
throw new Error('Unexpected character ' + str[i + 1] + ' expected ` `, `\\n`, `,`, `!` or `=`');
|
||||
} else {
|
||||
key += str[i];
|
||||
}
|
||||
break;
|
||||
case 'key':
|
||||
if (key === '' && (str[i] === '"' || str[i] === "'")) {
|
||||
loc = 'key-char';
|
||||
quote = str[i];
|
||||
} else if (str[i] === '!' || str[i] === '=') {
|
||||
escapedAttr = str[i] !== '!';
|
||||
if (str[i] === '!') i++;
|
||||
if (str[i] !== '=') throw new Error('Unexpected character ' + str[i] + ' expected `=`');
|
||||
loc = 'value';
|
||||
state = characterParser.defaultState();
|
||||
} else {
|
||||
key += str[i]
|
||||
}
|
||||
break;
|
||||
case 'value':
|
||||
state = characterParser.parseChar(str[i], state);
|
||||
if (state.isString()) {
|
||||
loc = 'string';
|
||||
quote = str[i];
|
||||
interpolatable = str[i];
|
||||
} else {
|
||||
val += str[i];
|
||||
}
|
||||
break;
|
||||
case 'string':
|
||||
state = characterParser.parseChar(str[i], state);
|
||||
interpolatable += str[i];
|
||||
if (!state.isString()) {
|
||||
loc = 'value';
|
||||
val += interpolate(interpolatable);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('/' == this.input.charAt(0)) {
|
||||
this.consume(1);
|
||||
tok.selfClosing = true;
|
||||
}
|
||||
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* &attributes block
|
||||
*/
|
||||
attributesBlock: function () {
|
||||
var captures;
|
||||
if (/^&attributes\b/.test(this.input)) {
|
||||
this.consume(11);
|
||||
var args = this.bracketExpression();
|
||||
this.consume(args.end + 1);
|
||||
return this.tok('&attributes', args.src);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Indent | Outdent | Newline.
|
||||
*/
|
||||
|
||||
indent: function() {
|
||||
var captures, re;
|
||||
|
||||
// established regexp
|
||||
if (this.indentRe) {
|
||||
captures = this.indentRe.exec(this.input);
|
||||
// determine regexp
|
||||
} else {
|
||||
// tabs
|
||||
re = /^\n(\t*) */;
|
||||
captures = re.exec(this.input);
|
||||
|
||||
// spaces
|
||||
if (captures && !captures[1].length) {
|
||||
re = /^\n( *)/;
|
||||
captures = re.exec(this.input);
|
||||
}
|
||||
|
||||
// established
|
||||
if (captures && captures[1].length) this.indentRe = re;
|
||||
}
|
||||
|
||||
if (captures) {
|
||||
var tok
|
||||
, indents = captures[1].length;
|
||||
|
||||
++this.lineno;
|
||||
this.consume(indents + 1);
|
||||
|
||||
if (' ' == this.input[0] || '\t' == this.input[0]) {
|
||||
throw new Error('Invalid indentation, you can use tabs or spaces but not both');
|
||||
}
|
||||
|
||||
// blank line
|
||||
if ('\n' == this.input[0]) {
|
||||
this.pipeless = false;
|
||||
return this.tok('newline');
|
||||
}
|
||||
|
||||
// outdent
|
||||
if (this.indentStack.length && indents < this.indentStack[0]) {
|
||||
while (this.indentStack.length && this.indentStack[0] > indents) {
|
||||
this.stash.push(this.tok('outdent'));
|
||||
this.indentStack.shift();
|
||||
}
|
||||
tok = this.stash.pop();
|
||||
// indent
|
||||
} else if (indents && indents != this.indentStack[0]) {
|
||||
this.indentStack.unshift(indents);
|
||||
tok = this.tok('indent', indents);
|
||||
// newline
|
||||
} else {
|
||||
tok = this.tok('newline');
|
||||
}
|
||||
|
||||
this.pipeless = false;
|
||||
return tok;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Pipe-less text consumed only when
|
||||
* pipeless is true;
|
||||
*/
|
||||
|
||||
pipelessText: function() {
|
||||
if (!this.pipeless) return;
|
||||
var captures, re;
|
||||
|
||||
// established regexp
|
||||
if (this.indentRe) {
|
||||
captures = this.indentRe.exec(this.input);
|
||||
// determine regexp
|
||||
} else {
|
||||
// tabs
|
||||
re = /^\n(\t*) */;
|
||||
captures = re.exec(this.input);
|
||||
|
||||
// spaces
|
||||
if (captures && !captures[1].length) {
|
||||
re = /^\n( *)/;
|
||||
captures = re.exec(this.input);
|
||||
}
|
||||
|
||||
// established
|
||||
if (captures && captures[1].length) this.indentRe = re;
|
||||
}
|
||||
|
||||
var indents = captures && captures[1].length;
|
||||
if (indents && (this.indentStack.length === 0 || indents > this.indentStack[0])) {
|
||||
var indent = captures[1];
|
||||
var line;
|
||||
var tokens = [];
|
||||
var isMatch;
|
||||
do {
|
||||
// text has `\n` as a prefix
|
||||
var i = this.input.substr(1).indexOf('\n');
|
||||
if (-1 == i) i = this.input.length - 1;
|
||||
var str = this.input.substr(1, i);
|
||||
isMatch = str.substr(0, indent.length) === indent || !str.trim();
|
||||
if (isMatch) {
|
||||
// consume test along with `\n` prefix if match
|
||||
this.consume(str.length + 1);
|
||||
++this.lineno;
|
||||
tokens.push(str.substr(indent.length));
|
||||
}
|
||||
} while(this.input.length && isMatch);
|
||||
while (this.input.length === 0 && tokens[tokens.length - 1] === '') tokens.pop();
|
||||
return this.tok('pipeless-text', tokens);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* ':'
|
||||
*/
|
||||
|
||||
colon: function() {
|
||||
var good = /^: +/.test(this.input);
|
||||
var res = this.scan(/^: */, ':');
|
||||
if (res && !good) {
|
||||
console.warn('Warning: space required after `:` on line ' + this.lineno +
|
||||
' of jade file "' + this.filename + '"');
|
||||
}
|
||||
return res;
|
||||
},
|
||||
|
||||
fail: function () {
|
||||
throw new Error('unexpected text ' + this.input.substr(0, 5));
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the next token object, or those
|
||||
* previously stashed by lookahead.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
advance: function(){
|
||||
return this.stashed()
|
||||
|| this.next();
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the next token object.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
next: function() {
|
||||
return this.deferred()
|
||||
|| this.blank()
|
||||
|| this.eos()
|
||||
|| this.pipelessText()
|
||||
|| this.yield()
|
||||
|| this.doctype()
|
||||
|| this.interpolation()
|
||||
|| this["case"]()
|
||||
|| this.when()
|
||||
|| this["default"]()
|
||||
|| this["extends"]()
|
||||
|| this.append()
|
||||
|| this.prepend()
|
||||
|| this.block()
|
||||
|| this.mixinBlock()
|
||||
|| this.include()
|
||||
|| this.includeFiltered()
|
||||
|| this.mixin()
|
||||
|| this.call()
|
||||
|| this.conditional()
|
||||
|| this.each()
|
||||
|| this["while"]()
|
||||
|| this.tag()
|
||||
|| this.filter()
|
||||
|| this.blockCode()
|
||||
|| this.code()
|
||||
|| this.id()
|
||||
|| this.className()
|
||||
|| this.attrs()
|
||||
|| this.attributesBlock()
|
||||
|| this.indent()
|
||||
|| this.text()
|
||||
|| this.comment()
|
||||
|| this.colon()
|
||||
|| this.dot()
|
||||
|| this.textFail()
|
||||
|| this.fail();
|
||||
}
|
||||
};
|
||||
83
node_modules/jade/lib/nodes/attrs.js
generated
vendored
Normal file
83
node_modules/jade/lib/nodes/attrs.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Attrs` node.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Attrs = module.exports = function Attrs() {
|
||||
this.attributeNames = [];
|
||||
this.attrs = [];
|
||||
this.attributeBlocks = [];
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Attrs.prototype = Object.create(Node.prototype);
|
||||
Attrs.prototype.constructor = Attrs;
|
||||
|
||||
Attrs.prototype.type = 'Attrs';
|
||||
|
||||
/**
|
||||
* Set attribute `name` to `val`, keep in mind these become
|
||||
* part of a raw js object literal, so to quote a value you must
|
||||
* '"quote me"', otherwise or example 'user.name' is literal JavaScript.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {String} val
|
||||
* @param {Boolean} escaped
|
||||
* @return {Tag} for chaining
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Attrs.prototype.setAttribute = function(name, val, escaped){
|
||||
if (name !== 'class' && this.attributeNames.indexOf(name) !== -1) {
|
||||
throw new Error('Duplicate attribute "' + name + '" is not allowed.');
|
||||
}
|
||||
this.attributeNames.push(name);
|
||||
this.attrs.push({ name: name, val: val, escaped: escaped });
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove attribute `name` when present.
|
||||
*
|
||||
* @param {String} name
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Attrs.prototype.removeAttribute = function(name){
|
||||
var err = new Error('attrs.removeAttribute is deprecated and will be removed in v2.0.0');
|
||||
console.warn(err.stack);
|
||||
|
||||
for (var i = 0, len = this.attrs.length; i < len; ++i) {
|
||||
if (this.attrs[i] && this.attrs[i].name == name) {
|
||||
delete this.attrs[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get attribute value by `name`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Attrs.prototype.getAttribute = function(name){
|
||||
var err = new Error('attrs.getAttribute is deprecated and will be removed in v2.0.0');
|
||||
console.warn(err.stack);
|
||||
|
||||
for (var i = 0, len = this.attrs.length; i < len; ++i) {
|
||||
if (this.attrs[i] && this.attrs[i].name == name) {
|
||||
return this.attrs[i].val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Attrs.prototype.addAttributes = function (src) {
|
||||
this.attributeBlocks.push(src);
|
||||
};
|
||||
24
node_modules/jade/lib/nodes/block-comment.js
generated
vendored
Normal file
24
node_modules/jade/lib/nodes/block-comment.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `BlockComment` with the given `block`.
|
||||
*
|
||||
* @param {String} val
|
||||
* @param {Block} block
|
||||
* @param {Boolean} buffer
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var BlockComment = module.exports = function BlockComment(val, block, buffer) {
|
||||
this.block = block;
|
||||
this.val = val;
|
||||
this.buffer = buffer;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
BlockComment.prototype = Object.create(Node.prototype);
|
||||
BlockComment.prototype.constructor = BlockComment;
|
||||
|
||||
BlockComment.prototype.type = 'BlockComment';
|
||||
118
node_modules/jade/lib/nodes/block.js
generated
vendored
Normal file
118
node_modules/jade/lib/nodes/block.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a new `Block` with an optional `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Block = module.exports = function Block(node){
|
||||
this.nodes = [];
|
||||
if (node) this.push(node);
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Block.prototype = Object.create(Node.prototype);
|
||||
Block.prototype.constructor = Block;
|
||||
|
||||
Block.prototype.type = 'Block';
|
||||
|
||||
/**
|
||||
* Block flag.
|
||||
*/
|
||||
|
||||
Block.prototype.isBlock = true;
|
||||
|
||||
/**
|
||||
* Replace the nodes in `other` with the nodes
|
||||
* in `this` block.
|
||||
*
|
||||
* @param {Block} other
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Block.prototype.replace = function(other){
|
||||
var err = new Error('block.replace is deprecated and will be removed in v2.0.0');
|
||||
console.warn(err.stack);
|
||||
|
||||
other.nodes = this.nodes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Push the given `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @return {Number}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Block.prototype.push = function(node){
|
||||
return this.nodes.push(node);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this block is empty.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Block.prototype.isEmpty = function(){
|
||||
return 0 == this.nodes.length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Unshift the given `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @return {Number}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Block.prototype.unshift = function(node){
|
||||
return this.nodes.unshift(node);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the "last" block, or the first `yield` node.
|
||||
*
|
||||
* @return {Block}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Block.prototype.includeBlock = function(){
|
||||
var ret = this
|
||||
, node;
|
||||
|
||||
for (var i = 0, len = this.nodes.length; i < len; ++i) {
|
||||
node = this.nodes[i];
|
||||
if (node.yield) return node;
|
||||
else if (node.textOnly) continue;
|
||||
else if (node.includeBlock) ret = node.includeBlock();
|
||||
else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock();
|
||||
if (ret.yield) return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a clone of this block.
|
||||
*
|
||||
* @return {Block}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Block.prototype.clone = function(){
|
||||
var err = new Error('block.clone is deprecated and will be removed in v2.0.0');
|
||||
console.warn(err.stack);
|
||||
|
||||
var clone = new Block;
|
||||
for (var i = 0, len = this.nodes.length; i < len; ++i) {
|
||||
clone.push(this.nodes[i].clone());
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
33
node_modules/jade/lib/nodes/case.js
generated
vendored
Normal file
33
node_modules/jade/lib/nodes/case.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a new `Case` with `expr`.
|
||||
*
|
||||
* @param {String} expr
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Case = exports = module.exports = function Case(expr, block){
|
||||
this.expr = expr;
|
||||
this.block = block;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Case.prototype = Object.create(Node.prototype);
|
||||
Case.prototype.constructor = Case;
|
||||
|
||||
Case.prototype.type = 'Case';
|
||||
|
||||
var When = exports.When = function When(expr, block){
|
||||
this.expr = expr;
|
||||
this.block = block;
|
||||
this.debug = false;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
When.prototype = Object.create(Node.prototype);
|
||||
When.prototype.constructor = When;
|
||||
|
||||
When.prototype.type = 'When';
|
||||
26
node_modules/jade/lib/nodes/code.js
generated
vendored
Normal file
26
node_modules/jade/lib/nodes/code.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Code` node with the given code `val`.
|
||||
* Code may also be optionally buffered and escaped.
|
||||
*
|
||||
* @param {String} val
|
||||
* @param {Boolean} buffer
|
||||
* @param {Boolean} escape
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Code = module.exports = function Code(val, buffer, escape) {
|
||||
this.val = val;
|
||||
this.buffer = buffer;
|
||||
this.escape = escape;
|
||||
if (val.match(/^ *else/)) this.debug = false;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Code.prototype = Object.create(Node.prototype);
|
||||
Code.prototype.constructor = Code;
|
||||
|
||||
Code.prototype.type = 'Code'; // prevent the minifiers removing this
|
||||
23
node_modules/jade/lib/nodes/comment.js
generated
vendored
Normal file
23
node_modules/jade/lib/nodes/comment.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Comment` with the given `val`, optionally `buffer`,
|
||||
* otherwise the comment may render in the output.
|
||||
*
|
||||
* @param {String} val
|
||||
* @param {Boolean} buffer
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Comment = module.exports = function Comment(val, buffer) {
|
||||
this.val = val;
|
||||
this.buffer = buffer;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Comment.prototype = Object.create(Node.prototype);
|
||||
Comment.prototype.constructor = Comment;
|
||||
|
||||
Comment.prototype.type = 'Comment';
|
||||
20
node_modules/jade/lib/nodes/doctype.js
generated
vendored
Normal file
20
node_modules/jade/lib/nodes/doctype.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Doctype` with the given `val`.
|
||||
*
|
||||
* @param {String} val
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Doctype = module.exports = function Doctype(val) {
|
||||
this.val = val;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Doctype.prototype = Object.create(Node.prototype);
|
||||
Doctype.prototype.constructor = Doctype;
|
||||
|
||||
Doctype.prototype.type = 'Doctype';
|
||||
26
node_modules/jade/lib/nodes/each.js
generated
vendored
Normal file
26
node_modules/jade/lib/nodes/each.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize an `Each` node, representing iteration
|
||||
*
|
||||
* @param {String} obj
|
||||
* @param {String} val
|
||||
* @param {String} key
|
||||
* @param {Block} block
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Each = module.exports = function Each(obj, val, key, block) {
|
||||
this.obj = obj;
|
||||
this.val = val;
|
||||
this.key = key;
|
||||
this.block = block;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Each.prototype = Object.create(Node.prototype);
|
||||
Each.prototype.constructor = Each;
|
||||
|
||||
Each.prototype.type = 'Each';
|
||||
24
node_modules/jade/lib/nodes/filter.js
generated
vendored
Normal file
24
node_modules/jade/lib/nodes/filter.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Filter` node with the given
|
||||
* filter `name` and `block`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Block|Node} block
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Filter = module.exports = function Filter(name, block, attrs) {
|
||||
this.name = name;
|
||||
this.block = block;
|
||||
this.attrs = attrs;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Filter.prototype = Object.create(Node.prototype);
|
||||
Filter.prototype.constructor = Filter;
|
||||
|
||||
Filter.prototype.type = 'Filter';
|
||||
16
node_modules/jade/lib/nodes/index.js
generated
vendored
Normal file
16
node_modules/jade/lib/nodes/index.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
exports.Node = require('./node');
|
||||
exports.Tag = require('./tag');
|
||||
exports.Code = require('./code');
|
||||
exports.Each = require('./each');
|
||||
exports.Case = require('./case');
|
||||
exports.Text = require('./text');
|
||||
exports.Block = require('./block');
|
||||
exports.MixinBlock = require('./mixin-block');
|
||||
exports.Mixin = require('./mixin');
|
||||
exports.Filter = require('./filter');
|
||||
exports.Comment = require('./comment');
|
||||
exports.Literal = require('./literal');
|
||||
exports.BlockComment = require('./block-comment');
|
||||
exports.Doctype = require('./doctype');
|
||||
20
node_modules/jade/lib/nodes/literal.js
generated
vendored
Normal file
20
node_modules/jade/lib/nodes/literal.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Literal` node with the given `str.
|
||||
*
|
||||
* @param {String} str
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Literal = module.exports = function Literal(str) {
|
||||
this.str = str;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Literal.prototype = Object.create(Node.prototype);
|
||||
Literal.prototype.constructor = Literal;
|
||||
|
||||
Literal.prototype.type = 'Literal';
|
||||
18
node_modules/jade/lib/nodes/mixin-block.js
generated
vendored
Normal file
18
node_modules/jade/lib/nodes/mixin-block.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a new `Block` with an optional `node`.
|
||||
*
|
||||
* @param {Node} node
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var MixinBlock = module.exports = function MixinBlock(){};
|
||||
|
||||
// Inherit from `Node`.
|
||||
MixinBlock.prototype = Object.create(Node.prototype);
|
||||
MixinBlock.prototype.constructor = MixinBlock;
|
||||
|
||||
MixinBlock.prototype.type = 'MixinBlock';
|
||||
26
node_modules/jade/lib/nodes/mixin.js
generated
vendored
Normal file
26
node_modules/jade/lib/nodes/mixin.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
var Attrs = require('./attrs');
|
||||
|
||||
/**
|
||||
* Initialize a new `Mixin` with `name` and `block`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {String} args
|
||||
* @param {Block} block
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Mixin = module.exports = function Mixin(name, args, block, call){
|
||||
Attrs.call(this);
|
||||
this.name = name;
|
||||
this.args = args;
|
||||
this.block = block;
|
||||
this.call = call;
|
||||
};
|
||||
|
||||
// Inherit from `Attrs`.
|
||||
Mixin.prototype = Object.create(Attrs.prototype);
|
||||
Mixin.prototype.constructor = Mixin;
|
||||
|
||||
Mixin.prototype.type = 'Mixin';
|
||||
18
node_modules/jade/lib/nodes/node.js
generated
vendored
Normal file
18
node_modules/jade/lib/nodes/node.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
var Node = module.exports = function Node(){};
|
||||
|
||||
/**
|
||||
* Clone this node (return itself)
|
||||
*
|
||||
* @return {Node}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Node.prototype.clone = function(){
|
||||
var err = new Error('node.clone is deprecated and will be removed in v2.0.0');
|
||||
console.warn(err.stack);
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.type = '';
|
||||
89
node_modules/jade/lib/nodes/tag.js
generated
vendored
Normal file
89
node_modules/jade/lib/nodes/tag.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
'use strict';
|
||||
|
||||
var Attrs = require('./attrs');
|
||||
var Block = require('./block');
|
||||
var inlineTags = require('../inline-tags');
|
||||
|
||||
/**
|
||||
* Initialize a `Tag` node with the given tag `name` and optional `block`.
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Block} block
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Tag = module.exports = function Tag(name, block) {
|
||||
Attrs.call(this);
|
||||
this.name = name;
|
||||
this.block = block || new Block;
|
||||
};
|
||||
|
||||
// Inherit from `Attrs`.
|
||||
Tag.prototype = Object.create(Attrs.prototype);
|
||||
Tag.prototype.constructor = Tag;
|
||||
|
||||
Tag.prototype.type = 'Tag';
|
||||
|
||||
/**
|
||||
* Clone this tag.
|
||||
*
|
||||
* @return {Tag}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Tag.prototype.clone = function(){
|
||||
var err = new Error('tag.clone is deprecated and will be removed in v2.0.0');
|
||||
console.warn(err.stack);
|
||||
|
||||
var clone = new Tag(this.name, this.block.clone());
|
||||
clone.line = this.line;
|
||||
clone.attrs = this.attrs;
|
||||
clone.textOnly = this.textOnly;
|
||||
return clone;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this tag is an inline tag.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Tag.prototype.isInline = function(){
|
||||
return ~inlineTags.indexOf(this.name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this tag's contents can be inlined. Used for pretty printing.
|
||||
*
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Tag.prototype.canInline = function(){
|
||||
var nodes = this.block.nodes;
|
||||
|
||||
function isInline(node){
|
||||
// Recurse if the node is a block
|
||||
if (node.isBlock) return node.nodes.every(isInline);
|
||||
return node.isText || (node.isInline && node.isInline());
|
||||
}
|
||||
|
||||
// Empty tag
|
||||
if (!nodes.length) return true;
|
||||
|
||||
// Text-only or inline-only tag
|
||||
if (1 == nodes.length) return isInline(nodes[0]);
|
||||
|
||||
// Multi-line inline-only tag
|
||||
if (this.block.nodes.every(isInline)) {
|
||||
for (var i = 1, len = nodes.length; i < len; ++i) {
|
||||
if (nodes[i-1].isText && nodes[i].isText)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mixed tag
|
||||
return false;
|
||||
};
|
||||
26
node_modules/jade/lib/nodes/text.js
generated
vendored
Normal file
26
node_modules/jade/lib/nodes/text.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
var Node = require('./node');
|
||||
|
||||
/**
|
||||
* Initialize a `Text` node with optional `line`.
|
||||
*
|
||||
* @param {String} line
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Text = module.exports = function Text(line) {
|
||||
this.val = line;
|
||||
};
|
||||
|
||||
// Inherit from `Node`.
|
||||
Text.prototype = Object.create(Node.prototype);
|
||||
Text.prototype.constructor = Text;
|
||||
|
||||
Text.prototype.type = 'Text';
|
||||
|
||||
/**
|
||||
* Flag as text.
|
||||
*/
|
||||
|
||||
Text.prototype.isText = true;
|
||||
846
node_modules/jade/lib/parser.js
generated
vendored
Normal file
846
node_modules/jade/lib/parser.js
generated
vendored
Normal file
@@ -0,0 +1,846 @@
|
||||
'use strict';
|
||||
|
||||
var Lexer = require('./lexer');
|
||||
var nodes = require('./nodes');
|
||||
var utils = require('./utils');
|
||||
var filters = require('./filters');
|
||||
var path = require('path');
|
||||
var constantinople = require('constantinople');
|
||||
var parseJSExpression = require('character-parser').parseMax;
|
||||
var extname = path.extname;
|
||||
|
||||
/**
|
||||
* Initialize `Parser` with the given input `str` and `filename`.
|
||||
*
|
||||
* @param {String} str
|
||||
* @param {String} filename
|
||||
* @param {Object} options
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var Parser = exports = module.exports = function Parser(str, filename, options){
|
||||
//Strip any UTF-8 BOM off of the start of `str`, if it exists.
|
||||
this.input = str.replace(/^\uFEFF/, '');
|
||||
this.lexer = new Lexer(this.input, filename);
|
||||
this.filename = filename;
|
||||
this.blocks = {};
|
||||
this.mixins = {};
|
||||
this.options = options;
|
||||
this.contexts = [this];
|
||||
this.inMixin = 0;
|
||||
this.dependencies = [];
|
||||
this.inBlock = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parser prototype.
|
||||
*/
|
||||
|
||||
Parser.prototype = {
|
||||
|
||||
/**
|
||||
* Save original constructor
|
||||
*/
|
||||
|
||||
constructor: Parser,
|
||||
|
||||
/**
|
||||
* Push `parser` onto the context stack,
|
||||
* or pop and return a `Parser`.
|
||||
*/
|
||||
|
||||
context: function(parser){
|
||||
if (parser) {
|
||||
this.contexts.push(parser);
|
||||
} else {
|
||||
return this.contexts.pop();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the next token object.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
advance: function(){
|
||||
return this.lexer.advance();
|
||||
},
|
||||
|
||||
/**
|
||||
* Single token lookahead.
|
||||
*
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
peek: function() {
|
||||
return this.lookahead(1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Return lexer lineno.
|
||||
*
|
||||
* @return {Number}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
line: function() {
|
||||
return this.lexer.lineno;
|
||||
},
|
||||
|
||||
/**
|
||||
* `n` token lookahead.
|
||||
*
|
||||
* @param {Number} n
|
||||
* @return {Object}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
lookahead: function(n){
|
||||
return this.lexer.lookahead(n);
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse input returning a string of js for evaluation.
|
||||
*
|
||||
* @return {String}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
parse: function(){
|
||||
var block = new nodes.Block, parser;
|
||||
block.line = 0;
|
||||
block.filename = this.filename;
|
||||
|
||||
while ('eos' != this.peek().type) {
|
||||
if ('newline' == this.peek().type) {
|
||||
this.advance();
|
||||
} else {
|
||||
var next = this.peek();
|
||||
var expr = this.parseExpr();
|
||||
expr.filename = expr.filename || this.filename;
|
||||
expr.line = next.line;
|
||||
block.push(expr);
|
||||
}
|
||||
}
|
||||
|
||||
if (parser = this.extending) {
|
||||
this.context(parser);
|
||||
var ast = parser.parse();
|
||||
this.context();
|
||||
|
||||
// hoist mixins
|
||||
for (var name in this.mixins)
|
||||
ast.unshift(this.mixins[name]);
|
||||
return ast;
|
||||
}
|
||||
|
||||
if (!this.extending && !this.included && Object.keys(this.blocks).length){
|
||||
var blocks = [];
|
||||
utils.walkAST(block, function (node) {
|
||||
if (node.type === 'Block' && node.name) {
|
||||
blocks.push(node.name);
|
||||
}
|
||||
});
|
||||
Object.keys(this.blocks).forEach(function (name) {
|
||||
if (blocks.indexOf(name) === -1 && !this.blocks[name].isSubBlock) {
|
||||
console.warn('Warning: Unexpected block "'
|
||||
+ name
|
||||
+ '" '
|
||||
+ ' on line '
|
||||
+ this.blocks[name].line
|
||||
+ ' of '
|
||||
+ (this.blocks[name].filename)
|
||||
+ '. This block is never used. This warning will be an error in v2.0.0');
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
return block;
|
||||
},
|
||||
|
||||
/**
|
||||
* Expect the given type, or throw an exception.
|
||||
*
|
||||
* @param {String} type
|
||||
* @api private
|
||||
*/
|
||||
|
||||
expect: function(type){
|
||||
if (this.peek().type === type) {
|
||||
return this.advance();
|
||||
} else {
|
||||
throw new Error('expected "' + type + '", but got "' + this.peek().type + '"');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Accept the given `type`.
|
||||
*
|
||||
* @param {String} type
|
||||
* @api private
|
||||
*/
|
||||
|
||||
accept: function(type){
|
||||
if (this.peek().type === type) {
|
||||
return this.advance();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* tag
|
||||
* | doctype
|
||||
* | mixin
|
||||
* | include
|
||||
* | filter
|
||||
* | comment
|
||||
* | text
|
||||
* | each
|
||||
* | code
|
||||
* | yield
|
||||
* | id
|
||||
* | class
|
||||
* | interpolation
|
||||
*/
|
||||
|
||||
parseExpr: function(){
|
||||
switch (this.peek().type) {
|
||||
case 'tag':
|
||||
return this.parseTag();
|
||||
case 'mixin':
|
||||
return this.parseMixin();
|
||||
case 'block':
|
||||
return this.parseBlock();
|
||||
case 'mixin-block':
|
||||
return this.parseMixinBlock();
|
||||
case 'case':
|
||||
return this.parseCase();
|
||||
case 'extends':
|
||||
return this.parseExtends();
|
||||
case 'include':
|
||||
return this.parseInclude();
|
||||
case 'doctype':
|
||||
return this.parseDoctype();
|
||||
case 'filter':
|
||||
return this.parseFilter();
|
||||
case 'comment':
|
||||
return this.parseComment();
|
||||
case 'text':
|
||||
return this.parseText();
|
||||
case 'each':
|
||||
return this.parseEach();
|
||||
case 'code':
|
||||
return this.parseCode();
|
||||
case 'blockCode':
|
||||
return this.parseBlockCode();
|
||||
case 'call':
|
||||
return this.parseCall();
|
||||
case 'interpolation':
|
||||
return this.parseInterpolation();
|
||||
case 'yield':
|
||||
this.advance();
|
||||
var block = new nodes.Block;
|
||||
block.yield = true;
|
||||
return block;
|
||||
case 'id':
|
||||
case 'class':
|
||||
var tok = this.advance();
|
||||
this.lexer.defer(this.lexer.tok('tag', 'div'));
|
||||
this.lexer.defer(tok);
|
||||
return this.parseExpr();
|
||||
default:
|
||||
throw new Error('unexpected token "' + this.peek().type + '"');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Text
|
||||
*/
|
||||
|
||||
parseText: function(){
|
||||
var tok = this.expect('text');
|
||||
var tokens = this.parseInlineTagsInText(tok.val);
|
||||
if (tokens.length === 1) return tokens[0];
|
||||
var node = new nodes.Block;
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
node.push(tokens[i]);
|
||||
};
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* ':' expr
|
||||
* | block
|
||||
*/
|
||||
|
||||
parseBlockExpansion: function(){
|
||||
if (':' == this.peek().type) {
|
||||
this.advance();
|
||||
return new nodes.Block(this.parseExpr());
|
||||
} else {
|
||||
return this.block();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* case
|
||||
*/
|
||||
|
||||
parseCase: function(){
|
||||
var val = this.expect('case').val;
|
||||
var node = new nodes.Case(val);
|
||||
node.line = this.line();
|
||||
|
||||
var block = new nodes.Block;
|
||||
block.line = this.line();
|
||||
block.filename = this.filename;
|
||||
this.expect('indent');
|
||||
while ('outdent' != this.peek().type) {
|
||||
switch (this.peek().type) {
|
||||
case 'comment':
|
||||
case 'newline':
|
||||
this.advance();
|
||||
break;
|
||||
case 'when':
|
||||
block.push(this.parseWhen());
|
||||
break;
|
||||
case 'default':
|
||||
block.push(this.parseDefault());
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unexpected token "' + this.peek().type
|
||||
+ '", expected "when", "default" or "newline"');
|
||||
}
|
||||
}
|
||||
this.expect('outdent');
|
||||
|
||||
node.block = block;
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* when
|
||||
*/
|
||||
|
||||
parseWhen: function(){
|
||||
var val = this.expect('when').val;
|
||||
if (this.peek().type !== 'newline')
|
||||
return new nodes.Case.When(val, this.parseBlockExpansion());
|
||||
else
|
||||
return new nodes.Case.When(val);
|
||||
},
|
||||
|
||||
/**
|
||||
* default
|
||||
*/
|
||||
|
||||
parseDefault: function(){
|
||||
this.expect('default');
|
||||
return new nodes.Case.When('default', this.parseBlockExpansion());
|
||||
},
|
||||
|
||||
/**
|
||||
* code
|
||||
*/
|
||||
|
||||
parseCode: function(afterIf){
|
||||
var tok = this.expect('code');
|
||||
var node = new nodes.Code(tok.val, tok.buffer, tok.escape);
|
||||
var block;
|
||||
node.line = this.line();
|
||||
|
||||
// throw an error if an else does not have an if
|
||||
if (tok.isElse && !tok.hasIf) {
|
||||
throw new Error('Unexpected else without if');
|
||||
}
|
||||
|
||||
// handle block
|
||||
block = 'indent' == this.peek().type;
|
||||
if (block) {
|
||||
node.block = this.block();
|
||||
}
|
||||
|
||||
// handle missing block
|
||||
if (tok.requiresBlock && !block) {
|
||||
node.block = new nodes.Block();
|
||||
}
|
||||
|
||||
// mark presense of if for future elses
|
||||
if (tok.isIf && this.peek().isElse) {
|
||||
this.peek().hasIf = true;
|
||||
} else if (tok.isIf && this.peek().type === 'newline' && this.lookahead(2).isElse) {
|
||||
this.lookahead(2).hasIf = true;
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* block code
|
||||
*/
|
||||
|
||||
parseBlockCode: function(){
|
||||
var tok = this.expect('blockCode');
|
||||
var node;
|
||||
var body = this.peek();
|
||||
var text;
|
||||
if (body.type === 'pipeless-text') {
|
||||
this.advance();
|
||||
text = body.val.join('\n');
|
||||
} else {
|
||||
text = '';
|
||||
}
|
||||
node = new nodes.Code(text, false, false);
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* comment
|
||||
*/
|
||||
|
||||
parseComment: function(){
|
||||
var tok = this.expect('comment');
|
||||
var node;
|
||||
|
||||
var block;
|
||||
if (block = this.parseTextBlock()) {
|
||||
node = new nodes.BlockComment(tok.val, block, tok.buffer);
|
||||
} else {
|
||||
node = new nodes.Comment(tok.val, tok.buffer);
|
||||
}
|
||||
|
||||
node.line = this.line();
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* doctype
|
||||
*/
|
||||
|
||||
parseDoctype: function(){
|
||||
var tok = this.expect('doctype');
|
||||
var node = new nodes.Doctype(tok.val);
|
||||
node.line = this.line();
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* filter attrs? text-block
|
||||
*/
|
||||
|
||||
parseFilter: function(){
|
||||
var tok = this.expect('filter');
|
||||
var attrs = this.accept('attrs');
|
||||
var block;
|
||||
|
||||
block = this.parseTextBlock() || new nodes.Block();
|
||||
|
||||
var options = {};
|
||||
if (attrs) {
|
||||
attrs.attrs.forEach(function (attribute) {
|
||||
options[attribute.name] = constantinople.toConstant(attribute.val);
|
||||
});
|
||||
}
|
||||
|
||||
var node = new nodes.Filter(tok.val, block, options);
|
||||
node.line = this.line();
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* each block
|
||||
*/
|
||||
|
||||
parseEach: function(){
|
||||
var tok = this.expect('each');
|
||||
var node = new nodes.Each(tok.code, tok.val, tok.key);
|
||||
node.line = this.line();
|
||||
node.block = this.block();
|
||||
if (this.peek().type == 'code' && this.peek().val == 'else') {
|
||||
this.advance();
|
||||
node.alternative = this.block();
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
* Resolves a path relative to the template for use in
|
||||
* includes and extends
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String} purpose Used in error messages.
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
resolvePath: function (path, purpose) {
|
||||
var p = require('path');
|
||||
var dirname = p.dirname;
|
||||
var basename = p.basename;
|
||||
var join = p.join;
|
||||
|
||||
if (path[0] !== '/' && !this.filename)
|
||||
throw new Error('the "filename" option is required to use "' + purpose + '" with "relative" paths');
|
||||
|
||||
if (path[0] === '/' && !this.options.basedir)
|
||||
throw new Error('the "basedir" option is required to use "' + purpose + '" with "absolute" paths');
|
||||
|
||||
path = join(path[0] === '/' ? this.options.basedir : dirname(this.filename), path);
|
||||
|
||||
if (basename(path).indexOf('.') === -1) path += '.jade';
|
||||
|
||||
return path;
|
||||
},
|
||||
|
||||
/**
|
||||
* 'extends' name
|
||||
*/
|
||||
|
||||
parseExtends: function(){
|
||||
var fs = require('fs');
|
||||
|
||||
var path = this.resolvePath(this.expect('extends').val.trim(), 'extends');
|
||||
if ('.jade' != path.substr(-5)) path += '.jade';
|
||||
|
||||
this.dependencies.push(path);
|
||||
var str = fs.readFileSync(path, 'utf8');
|
||||
var parser = new this.constructor(str, path, this.options);
|
||||
parser.dependencies = this.dependencies;
|
||||
|
||||
parser.blocks = this.blocks;
|
||||
parser.included = this.included;
|
||||
parser.contexts = this.contexts;
|
||||
this.extending = parser;
|
||||
|
||||
// TODO: null node
|
||||
return new nodes.Literal('');
|
||||
},
|
||||
|
||||
/**
|
||||
* 'block' name block
|
||||
*/
|
||||
|
||||
parseBlock: function(){
|
||||
var block = this.expect('block');
|
||||
var mode = block.mode;
|
||||
var name = block.val.trim();
|
||||
|
||||
var line = block.line;
|
||||
|
||||
this.inBlock++;
|
||||
block = 'indent' == this.peek().type
|
||||
? this.block()
|
||||
: new nodes.Block(new nodes.Literal(''));
|
||||
this.inBlock--;
|
||||
block.name = name;
|
||||
block.line = line;
|
||||
|
||||
var prev = this.blocks[name] || {prepended: [], appended: []}
|
||||
if (prev.mode === 'replace') return this.blocks[name] = prev;
|
||||
|
||||
var allNodes = prev.prepended.concat(block.nodes).concat(prev.appended);
|
||||
|
||||
switch (mode) {
|
||||
case 'append':
|
||||
prev.appended = prev.parser === this ?
|
||||
prev.appended.concat(block.nodes) :
|
||||
block.nodes.concat(prev.appended);
|
||||
break;
|
||||
case 'prepend':
|
||||
prev.prepended = prev.parser === this ?
|
||||
block.nodes.concat(prev.prepended) :
|
||||
prev.prepended.concat(block.nodes);
|
||||
break;
|
||||
}
|
||||
block.nodes = allNodes;
|
||||
block.appended = prev.appended;
|
||||
block.prepended = prev.prepended;
|
||||
block.mode = mode;
|
||||
block.parser = this;
|
||||
|
||||
block.isSubBlock = this.inBlock > 0;
|
||||
|
||||
return this.blocks[name] = block;
|
||||
},
|
||||
|
||||
parseMixinBlock: function () {
|
||||
var block = this.expect('mixin-block');
|
||||
if (!this.inMixin) {
|
||||
throw new Error('Anonymous blocks are not allowed unless they are part of a mixin.');
|
||||
}
|
||||
return new nodes.MixinBlock();
|
||||
},
|
||||
|
||||
/**
|
||||
* include block?
|
||||
*/
|
||||
|
||||
parseInclude: function(){
|
||||
var fs = require('fs');
|
||||
var tok = this.expect('include');
|
||||
|
||||
var path = this.resolvePath(tok.val.trim(), 'include');
|
||||
this.dependencies.push(path);
|
||||
// has-filter
|
||||
if (tok.filter) {
|
||||
var str = fs.readFileSync(path, 'utf8').replace(/\r/g, '');
|
||||
var options = {filename: path};
|
||||
if (tok.attrs) {
|
||||
tok.attrs.attrs.forEach(function (attribute) {
|
||||
options[attribute.name] = constantinople.toConstant(attribute.val);
|
||||
});
|
||||
}
|
||||
str = filters(tok.filter, str, options);
|
||||
return new nodes.Literal(str);
|
||||
}
|
||||
|
||||
// non-jade
|
||||
if ('.jade' != path.substr(-5)) {
|
||||
var str = fs.readFileSync(path, 'utf8').replace(/\r/g, '');
|
||||
return new nodes.Literal(str);
|
||||
}
|
||||
|
||||
var str = fs.readFileSync(path, 'utf8');
|
||||
var parser = new this.constructor(str, path, this.options);
|
||||
parser.dependencies = this.dependencies;
|
||||
|
||||
parser.blocks = utils.merge({}, this.blocks);
|
||||
parser.included = true;
|
||||
|
||||
parser.mixins = this.mixins;
|
||||
|
||||
this.context(parser);
|
||||
var ast = parser.parse();
|
||||
this.context();
|
||||
ast.filename = path;
|
||||
|
||||
if ('indent' == this.peek().type) {
|
||||
ast.includeBlock().push(this.block());
|
||||
}
|
||||
|
||||
return ast;
|
||||
},
|
||||
|
||||
/**
|
||||
* call ident block
|
||||
*/
|
||||
|
||||
parseCall: function(){
|
||||
var tok = this.expect('call');
|
||||
var name = tok.val;
|
||||
var args = tok.args;
|
||||
var mixin = new nodes.Mixin(name, args, new nodes.Block, true);
|
||||
|
||||
this.tag(mixin);
|
||||
if (mixin.code) {
|
||||
mixin.block.push(mixin.code);
|
||||
mixin.code = null;
|
||||
}
|
||||
if (mixin.block.isEmpty()) mixin.block = null;
|
||||
return mixin;
|
||||
},
|
||||
|
||||
/**
|
||||
* mixin block
|
||||
*/
|
||||
|
||||
parseMixin: function(){
|
||||
var tok = this.expect('mixin');
|
||||
var name = tok.val;
|
||||
var args = tok.args;
|
||||
var mixin;
|
||||
|
||||
// definition
|
||||
if ('indent' == this.peek().type) {
|
||||
this.inMixin++;
|
||||
mixin = new nodes.Mixin(name, args, this.block(), false);
|
||||
this.mixins[name] = mixin;
|
||||
this.inMixin--;
|
||||
return mixin;
|
||||
// call
|
||||
} else {
|
||||
return new nodes.Mixin(name, args, null, true);
|
||||
}
|
||||
},
|
||||
|
||||
parseInlineTagsInText: function (str) {
|
||||
var line = this.line();
|
||||
|
||||
var match = /(\\)?#\[((?:.|\n)*)$/.exec(str);
|
||||
if (match) {
|
||||
if (match[1]) { // escape
|
||||
var text = new nodes.Text(str.substr(0, match.index) + '#[');
|
||||
text.line = line;
|
||||
var rest = this.parseInlineTagsInText(match[2]);
|
||||
if (rest[0].type === 'Text') {
|
||||
text.val += rest[0].val;
|
||||
rest.shift();
|
||||
}
|
||||
return [text].concat(rest);
|
||||
} else {
|
||||
var text = new nodes.Text(str.substr(0, match.index));
|
||||
text.line = line;
|
||||
var buffer = [text];
|
||||
var rest = match[2];
|
||||
var range = parseJSExpression(rest);
|
||||
var inner = new Parser(range.src, this.filename, this.options);
|
||||
buffer.push(inner.parse());
|
||||
return buffer.concat(this.parseInlineTagsInText(rest.substr(range.end + 1)));
|
||||
}
|
||||
} else {
|
||||
var text = new nodes.Text(str);
|
||||
text.line = line;
|
||||
return [text];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* indent (text | newline)* outdent
|
||||
*/
|
||||
|
||||
parseTextBlock: function(){
|
||||
var block = new nodes.Block;
|
||||
block.line = this.line();
|
||||
var body = this.peek();
|
||||
if (body.type !== 'pipeless-text') return;
|
||||
this.advance();
|
||||
block.nodes = body.val.reduce(function (accumulator, text) {
|
||||
return accumulator.concat(this.parseInlineTagsInText(text));
|
||||
}.bind(this), []);
|
||||
return block;
|
||||
},
|
||||
|
||||
/**
|
||||
* indent expr* outdent
|
||||
*/
|
||||
|
||||
block: function(){
|
||||
var block = new nodes.Block;
|
||||
block.line = this.line();
|
||||
block.filename = this.filename;
|
||||
this.expect('indent');
|
||||
while ('outdent' != this.peek().type) {
|
||||
if ('newline' == this.peek().type) {
|
||||
this.advance();
|
||||
} else {
|
||||
var expr = this.parseExpr();
|
||||
expr.filename = this.filename;
|
||||
block.push(expr);
|
||||
}
|
||||
}
|
||||
this.expect('outdent');
|
||||
return block;
|
||||
},
|
||||
|
||||
/**
|
||||
* interpolation (attrs | class | id)* (text | code | ':')? newline* block?
|
||||
*/
|
||||
|
||||
parseInterpolation: function(){
|
||||
var tok = this.advance();
|
||||
var tag = new nodes.Tag(tok.val);
|
||||
tag.buffer = true;
|
||||
return this.tag(tag);
|
||||
},
|
||||
|
||||
/**
|
||||
* tag (attrs | class | id)* (text | code | ':')? newline* block?
|
||||
*/
|
||||
|
||||
parseTag: function(){
|
||||
var tok = this.advance();
|
||||
var tag = new nodes.Tag(tok.val);
|
||||
|
||||
tag.selfClosing = tok.selfClosing;
|
||||
|
||||
return this.tag(tag);
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse tag.
|
||||
*/
|
||||
|
||||
tag: function(tag){
|
||||
tag.line = this.line();
|
||||
|
||||
var seenAttrs = false;
|
||||
// (attrs | class | id)*
|
||||
out:
|
||||
while (true) {
|
||||
switch (this.peek().type) {
|
||||
case 'id':
|
||||
case 'class':
|
||||
var tok = this.advance();
|
||||
tag.setAttribute(tok.type, "'" + tok.val + "'");
|
||||
continue;
|
||||
case 'attrs':
|
||||
if (seenAttrs) {
|
||||
console.warn(this.filename + ', line ' + this.peek().line + ':\nYou should not have jade tags with multiple attributes.');
|
||||
}
|
||||
seenAttrs = true;
|
||||
var tok = this.advance();
|
||||
var attrs = tok.attrs;
|
||||
|
||||
if (tok.selfClosing) tag.selfClosing = true;
|
||||
|
||||
for (var i = 0; i < attrs.length; i++) {
|
||||
tag.setAttribute(attrs[i].name, attrs[i].val, attrs[i].escaped);
|
||||
}
|
||||
continue;
|
||||
case '&attributes':
|
||||
var tok = this.advance();
|
||||
tag.addAttributes(tok.val);
|
||||
break;
|
||||
default:
|
||||
break out;
|
||||
}
|
||||
}
|
||||
|
||||
// check immediate '.'
|
||||
if ('dot' == this.peek().type) {
|
||||
tag.textOnly = true;
|
||||
this.advance();
|
||||
}
|
||||
|
||||
// (text | code | ':')?
|
||||
switch (this.peek().type) {
|
||||
case 'text':
|
||||
tag.block.push(this.parseText());
|
||||
break;
|
||||
case 'code':
|
||||
tag.code = this.parseCode();
|
||||
break;
|
||||
case ':':
|
||||
this.advance();
|
||||
tag.block = new nodes.Block;
|
||||
tag.block.push(this.parseExpr());
|
||||
break;
|
||||
case 'newline':
|
||||
case 'indent':
|
||||
case 'outdent':
|
||||
case 'eos':
|
||||
case 'pipeless-text':
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unexpected token `' + this.peek().type + '` expected `text`, `code`, `:`, `newline` or `eos`')
|
||||
}
|
||||
|
||||
// newline*
|
||||
while ('newline' == this.peek().type) this.advance();
|
||||
|
||||
// block?
|
||||
if (tag.textOnly) {
|
||||
tag.block = this.parseTextBlock() || new nodes.Block();
|
||||
} else if ('indent' == this.peek().type) {
|
||||
var block = this.block();
|
||||
for (var i = 0, len = block.nodes.length; i < len; ++i) {
|
||||
tag.block.push(block.nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
};
|
||||
246
node_modules/jade/lib/runtime.js
generated
vendored
Normal file
246
node_modules/jade/lib/runtime.js
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Merge two attribute objects giving precedence
|
||||
* to values in object `b`. Classes are special-cased
|
||||
* allowing for arrays and merging/joining appropriately
|
||||
* resulting in a string.
|
||||
*
|
||||
* @param {Object} a
|
||||
* @param {Object} b
|
||||
* @return {Object} a
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.merge = function merge(a, b) {
|
||||
if (arguments.length === 1) {
|
||||
var attrs = a[0];
|
||||
for (var i = 1; i < a.length; i++) {
|
||||
attrs = merge(attrs, a[i]);
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
var ac = a['class'];
|
||||
var bc = b['class'];
|
||||
|
||||
if (ac || bc) {
|
||||
ac = ac || [];
|
||||
bc = bc || [];
|
||||
if (!Array.isArray(ac)) ac = [ac];
|
||||
if (!Array.isArray(bc)) bc = [bc];
|
||||
a['class'] = ac.concat(bc).filter(nulls);
|
||||
}
|
||||
|
||||
for (var key in b) {
|
||||
if (key != 'class') {
|
||||
a[key] = b[key];
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter null `val`s.
|
||||
*
|
||||
* @param {*} val
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function nulls(val) {
|
||||
return val != null && val !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* join array as classes.
|
||||
*
|
||||
* @param {*} val
|
||||
* @return {String}
|
||||
*/
|
||||
exports.joinClasses = joinClasses;
|
||||
function joinClasses(val) {
|
||||
return (Array.isArray(val) ? val.map(joinClasses) :
|
||||
(val && typeof val === 'object') ? Object.keys(val).filter(function (key) { return val[key]; }) :
|
||||
[val]).filter(nulls).join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the given classes.
|
||||
*
|
||||
* @param {Array} classes
|
||||
* @param {Array.<Boolean>} escaped
|
||||
* @return {String}
|
||||
*/
|
||||
exports.cls = function cls(classes, escaped) {
|
||||
var buf = [];
|
||||
for (var i = 0; i < classes.length; i++) {
|
||||
if (escaped && escaped[i]) {
|
||||
buf.push(exports.escape(joinClasses([classes[i]])));
|
||||
} else {
|
||||
buf.push(joinClasses(classes[i]));
|
||||
}
|
||||
}
|
||||
var text = joinClasses(buf);
|
||||
if (text.length) {
|
||||
return ' class="' + text + '"';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.style = function (val) {
|
||||
if (val && typeof val === 'object') {
|
||||
return Object.keys(val).map(function (style) {
|
||||
return style + ':' + val[style];
|
||||
}).join(';');
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Render the given attribute.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {String} val
|
||||
* @param {Boolean} escaped
|
||||
* @param {Boolean} terse
|
||||
* @return {String}
|
||||
*/
|
||||
exports.attr = function attr(key, val, escaped, terse) {
|
||||
if (key === 'style') {
|
||||
val = exports.style(val);
|
||||
}
|
||||
if ('boolean' == typeof val || null == val) {
|
||||
if (val) {
|
||||
return ' ' + (terse ? key : key + '="' + key + '"');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
} else if (0 == key.indexOf('data') && 'string' != typeof val) {
|
||||
if (JSON.stringify(val).indexOf('&') !== -1) {
|
||||
console.warn('Since Jade 2.0.0, ampersands (`&`) in data attributes ' +
|
||||
'will be escaped to `&`');
|
||||
};
|
||||
if (val && typeof val.toISOString === 'function') {
|
||||
console.warn('Jade will eliminate the double quotes around dates in ' +
|
||||
'ISO form after 2.0.0');
|
||||
}
|
||||
return ' ' + key + "='" + JSON.stringify(val).replace(/'/g, ''') + "'";
|
||||
} else if (escaped) {
|
||||
if (val && typeof val.toISOString === 'function') {
|
||||
console.warn('Jade will stringify dates in ISO form after 2.0.0');
|
||||
}
|
||||
return ' ' + key + '="' + exports.escape(val) + '"';
|
||||
} else {
|
||||
if (val && typeof val.toISOString === 'function') {
|
||||
console.warn('Jade will stringify dates in ISO form after 2.0.0');
|
||||
}
|
||||
return ' ' + key + '="' + val + '"';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the given attributes object.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {Object} escaped
|
||||
* @return {String}
|
||||
*/
|
||||
exports.attrs = function attrs(obj, terse){
|
||||
var buf = [];
|
||||
|
||||
var keys = Object.keys(obj);
|
||||
|
||||
if (keys.length) {
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
var key = keys[i]
|
||||
, val = obj[key];
|
||||
|
||||
if ('class' == key) {
|
||||
if (val = joinClasses(val)) {
|
||||
buf.push(' ' + key + '="' + val + '"');
|
||||
}
|
||||
} else {
|
||||
buf.push(exports.attr(key, val, false, terse));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Escape the given string of `html`.
|
||||
*
|
||||
* @param {String} html
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var jade_encode_html_rules = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"'
|
||||
};
|
||||
var jade_match_html = /[&<>"]/g;
|
||||
|
||||
function jade_encode_char(c) {
|
||||
return jade_encode_html_rules[c] || c;
|
||||
}
|
||||
|
||||
exports.escape = jade_escape;
|
||||
function jade_escape(html){
|
||||
var result = String(html).replace(jade_match_html, jade_encode_char);
|
||||
if (result === '' + html) return html;
|
||||
else return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Re-throw the given `err` in context to the
|
||||
* the jade in `filename` at the given `lineno`.
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {String} filename
|
||||
* @param {String} lineno
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.rethrow = function rethrow(err, filename, lineno, str){
|
||||
if (!(err instanceof Error)) throw err;
|
||||
if ((typeof window != 'undefined' || !filename) && !str) {
|
||||
err.message += ' on line ' + lineno;
|
||||
throw err;
|
||||
}
|
||||
try {
|
||||
str = str || require('fs').readFileSync(filename, 'utf8')
|
||||
} catch (ex) {
|
||||
rethrow(err, null, lineno)
|
||||
}
|
||||
var context = 3
|
||||
, lines = str.split('\n')
|
||||
, start = Math.max(lineno - context, 0)
|
||||
, end = Math.min(lines.length, lineno + context);
|
||||
|
||||
// Error context
|
||||
var context = lines.slice(start, end).map(function(line, i){
|
||||
var curr = i + start + 1;
|
||||
return (curr == lineno ? ' > ' : ' ')
|
||||
+ curr
|
||||
+ '| '
|
||||
+ line;
|
||||
}).join('\n');
|
||||
|
||||
// Alter exception message
|
||||
err.path = filename;
|
||||
err.message = (filename || 'Jade') + ':' + lineno
|
||||
+ '\n' + context + '\n\n' + err.message;
|
||||
throw err;
|
||||
};
|
||||
|
||||
exports.DebugItem = function DebugItem(lineno, filename) {
|
||||
this.lineno = lineno;
|
||||
this.filename = filename;
|
||||
}
|
||||
53
node_modules/jade/lib/utils.js
generated
vendored
Normal file
53
node_modules/jade/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Merge `b` into `a`.
|
||||
*
|
||||
* @param {Object} a
|
||||
* @param {Object} b
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
exports.merge = function(a, b) {
|
||||
for (var key in b) a[key] = b[key];
|
||||
return a;
|
||||
};
|
||||
|
||||
exports.stringify = function(str) {
|
||||
return JSON.stringify(str)
|
||||
.replace(/\u2028/g, '\\u2028')
|
||||
.replace(/\u2029/g, '\\u2029');
|
||||
};
|
||||
|
||||
exports.walkAST = function walkAST(ast, before, after) {
|
||||
before && before(ast);
|
||||
switch (ast.type) {
|
||||
case 'Block':
|
||||
ast.nodes.forEach(function (node) {
|
||||
walkAST(node, before, after);
|
||||
});
|
||||
break;
|
||||
case 'Case':
|
||||
case 'Each':
|
||||
case 'Mixin':
|
||||
case 'Tag':
|
||||
case 'When':
|
||||
case 'Code':
|
||||
ast.block && walkAST(ast.block, before, after);
|
||||
break;
|
||||
case 'Attrs':
|
||||
case 'BlockComment':
|
||||
case 'Comment':
|
||||
case 'Doctype':
|
||||
case 'Filter':
|
||||
case 'Literal':
|
||||
case 'MixinBlock':
|
||||
case 'Text':
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unexpected node type ' + ast.type);
|
||||
break;
|
||||
}
|
||||
after && after(ast);
|
||||
};
|
||||
15
node_modules/jade/node_modules/.bin/cleancss
generated
vendored
Normal file
15
node_modules/jade/node_modules/.bin/cleancss
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
basedir=`dirname "$0"`
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
"$basedir/node" "$basedir/../clean-css/bin/cleancss" "$@"
|
||||
ret=$?
|
||||
else
|
||||
node "$basedir/../clean-css/bin/cleancss" "$@"
|
||||
ret=$?
|
||||
fi
|
||||
exit $ret
|
||||
7
node_modules/jade/node_modules/.bin/cleancss.cmd
generated
vendored
Normal file
7
node_modules/jade/node_modules/.bin/cleancss.cmd
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
@IF EXIST "%~dp0\node.exe" (
|
||||
"%~dp0\node.exe" "%~dp0\..\clean-css\bin\cleancss" %*
|
||||
) ELSE (
|
||||
@SETLOCAL
|
||||
@SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
node "%~dp0\..\clean-css\bin\cleancss" %*
|
||||
)
|
||||
15
node_modules/jade/node_modules/.bin/mkdirp
generated
vendored
Normal file
15
node_modules/jade/node_modules/.bin/mkdirp
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
basedir=`dirname "$0"`
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
"$basedir/node" "$basedir/../mkdirp/bin/cmd.js" "$@"
|
||||
ret=$?
|
||||
else
|
||||
node "$basedir/../mkdirp/bin/cmd.js" "$@"
|
||||
ret=$?
|
||||
fi
|
||||
exit $ret
|
||||
7
node_modules/jade/node_modules/.bin/mkdirp.cmd
generated
vendored
Normal file
7
node_modules/jade/node_modules/.bin/mkdirp.cmd
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
@IF EXIST "%~dp0\node.exe" (
|
||||
"%~dp0\node.exe" "%~dp0\..\mkdirp\bin\cmd.js" %*
|
||||
) ELSE (
|
||||
@SETLOCAL
|
||||
@SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
node "%~dp0\..\mkdirp\bin\cmd.js" %*
|
||||
)
|
||||
15
node_modules/jade/node_modules/.bin/uglifyjs
generated
vendored
Normal file
15
node_modules/jade/node_modules/.bin/uglifyjs
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
basedir=`dirname "$0"`
|
||||
|
||||
case `uname` in
|
||||
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
|
||||
esac
|
||||
|
||||
if [ -x "$basedir/node" ]; then
|
||||
"$basedir/node" "$basedir/../uglify-js/bin/uglifyjs" "$@"
|
||||
ret=$?
|
||||
else
|
||||
node "$basedir/../uglify-js/bin/uglifyjs" "$@"
|
||||
ret=$?
|
||||
fi
|
||||
exit $ret
|
||||
7
node_modules/jade/node_modules/.bin/uglifyjs.cmd
generated
vendored
Normal file
7
node_modules/jade/node_modules/.bin/uglifyjs.cmd
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
@IF EXIST "%~dp0\node.exe" (
|
||||
"%~dp0\node.exe" "%~dp0\..\uglify-js\bin\uglifyjs" %*
|
||||
) ELSE (
|
||||
@SETLOCAL
|
||||
@SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||
node "%~dp0\..\uglify-js\bin\uglifyjs" %*
|
||||
)
|
||||
2
node_modules/jade/node_modules/character-parser/.npmignore
generated
vendored
Normal file
2
node_modules/jade/node_modules/character-parser/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
test/
|
||||
.travis.yml
|
||||
19
node_modules/jade/node_modules/character-parser/LICENSE
generated
vendored
Normal file
19
node_modules/jade/node_modules/character-parser/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013 Forbes Lindesay
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
142
node_modules/jade/node_modules/character-parser/README.md
generated
vendored
Normal file
142
node_modules/jade/node_modules/character-parser/README.md
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
# character-parser
|
||||
|
||||
Parse JavaScript one character at a time to look for snippets in Templates. This is not a validator, it's just designed to allow you to have sections of JavaScript delimited by brackets robustly.
|
||||
|
||||
[](https://travis-ci.org/ForbesLindesay/character-parser)
|
||||
|
||||
## Installation
|
||||
|
||||
npm install character-parser
|
||||
|
||||
## Usage
|
||||
|
||||
Work out how much depth changes:
|
||||
|
||||
```js
|
||||
var state = parse('foo(arg1, arg2, {\n foo: [a, b\n');
|
||||
assert(state.roundDepth === 1);
|
||||
assert(state.curlyDepth === 1);
|
||||
assert(state.squareDepth === 1);
|
||||
parse(' c, d]\n })', state);
|
||||
assert(state.squareDepth === 0);
|
||||
assert(state.curlyDepth === 0);
|
||||
assert(state.roundDepth === 0);
|
||||
```
|
||||
|
||||
### Bracketed Expressions
|
||||
|
||||
Find all the contents of a bracketed expression:
|
||||
|
||||
```js
|
||||
var section = parser.parseMax('foo="(", bar="}") bing bong');
|
||||
assert(section.start === 0);
|
||||
assert(section.end === 16);//exclusive end of string
|
||||
assert(section.src = 'foo="(", bar="}"');
|
||||
|
||||
|
||||
var section = parser.parseMax('{foo="(", bar="}"} bing bong', {start: 1});
|
||||
assert(section.start === 1);
|
||||
assert(section.end === 17);//exclusive end of string
|
||||
assert(section.src = 'foo="(", bar="}"');
|
||||
```
|
||||
|
||||
The bracketed expression parsing simply parses up to but excluding the first unmatched closed bracket (`)`, `}`, `]`). It is clever enough to ignore brackets in comments or strings.
|
||||
|
||||
|
||||
### Custom Delimited Expressions
|
||||
|
||||
Find code up to a custom delimiter:
|
||||
|
||||
```js
|
||||
var section = parser.parseUntil('foo.bar("%>").baz%> bing bong', '%>');
|
||||
assert(section.start === 0);
|
||||
assert(section.end === 17);//exclusive end of string
|
||||
assert(section.src = 'foo.bar("%>").baz');
|
||||
|
||||
var section = parser.parseUntil('<%foo.bar("%>").baz%> bing bong', '%>', {start: 2});
|
||||
assert(section.start === 2);
|
||||
assert(section.end === 19);//exclusive end of string
|
||||
assert(section.src = 'foo.bar("%>").baz');
|
||||
```
|
||||
|
||||
Delimiters are ignored if they are inside strings or comments.
|
||||
|
||||
## API
|
||||
|
||||
### parse(str, state = defaultState(), options = {start: 0, end: src.length})
|
||||
|
||||
Parse a string starting at the index start, and return the state after parsing that string.
|
||||
|
||||
If you want to parse one string in multiple sections you should keep passing the resulting state to the next parse operation.
|
||||
|
||||
Returns a `State` object.
|
||||
|
||||
### parseMax(src, options = {start: 0})
|
||||
|
||||
Parses the source until the first unmatched close bracket (any of `)`, `}`, `]`). It returns an object with the structure:
|
||||
|
||||
```js
|
||||
{
|
||||
start: 0,//index of first character of string
|
||||
end: 13,//index of first character after the end of string
|
||||
src: 'source string'
|
||||
}
|
||||
```
|
||||
|
||||
### parseUntil(src, delimiter, options = {start: 0, includeLineComment: false})
|
||||
|
||||
Parses the source until the first occurence of `delimiter` which is not in a string or a comment. If `includeLineComment` is `true`, it will still count if the delimiter occurs in a line comment, but not in a block comment. It returns an object with the structure:
|
||||
|
||||
```js
|
||||
{
|
||||
start: 0,//index of first character of string
|
||||
end: 13,//index of first character after the end of string
|
||||
src: 'source string'
|
||||
}
|
||||
```
|
||||
|
||||
### parseChar(character, state = defaultState())
|
||||
|
||||
Parses the single character and returns the state. See `parse` for the structure of the returned state object. N.B. character must be a single character not a multi character string.
|
||||
|
||||
### defaultState()
|
||||
|
||||
Get a default starting state.
|
||||
|
||||
### isPunctuator(character)
|
||||
|
||||
Returns `true` if `character` represents punctuation in JavaScript.
|
||||
|
||||
### isKeyword(name)
|
||||
|
||||
Returns `true` if `name` is a keyword in JavaScript.
|
||||
|
||||
## State
|
||||
|
||||
A state is an object with the following structure
|
||||
|
||||
```js
|
||||
{
|
||||
lineComment: false, //true if inside a line comment
|
||||
blockComment: false, //true if inside a block comment
|
||||
|
||||
singleQuote: false, //true if inside a single quoted string
|
||||
doubleQuote: false, //true if inside a double quoted string
|
||||
regexp: false, //true if inside a regular expression
|
||||
escaped: false, //true if in a string and the last character was an escape character
|
||||
|
||||
roundDepth: 0, //number of un-closed open `(` brackets
|
||||
curlyDepth: 0, //number of un-closed open `{` brackets
|
||||
squareDepth: 0 //number of un-closed open `[` brackets
|
||||
}
|
||||
```
|
||||
|
||||
It also has the following useful methods:
|
||||
|
||||
- `.isString()` returns `true` if the current location is inside a string.
|
||||
- `.isComment()` returns `true` if the current location is inside a comment.
|
||||
- `isNesting()` returns `true` if the current location is anything but at the top level, i.e. with no nesting.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
231
node_modules/jade/node_modules/character-parser/index.js
generated
vendored
Normal file
231
node_modules/jade/node_modules/character-parser/index.js
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
exports = (module.exports = parse);
|
||||
exports.parse = parse;
|
||||
function parse(src, state, options) {
|
||||
options = options || {};
|
||||
state = state || exports.defaultState();
|
||||
var start = options.start || 0;
|
||||
var end = options.end || src.length;
|
||||
var index = start;
|
||||
while (index < end) {
|
||||
if (state.roundDepth < 0 || state.curlyDepth < 0 || state.squareDepth < 0) {
|
||||
throw new SyntaxError('Mismatched Bracket: ' + src[index - 1]);
|
||||
}
|
||||
exports.parseChar(src[index++], state);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
exports.parseMax = parseMax;
|
||||
function parseMax(src, options) {
|
||||
options = options || {};
|
||||
var start = options.start || 0;
|
||||
var index = start;
|
||||
var state = exports.defaultState();
|
||||
while (state.roundDepth >= 0 && state.curlyDepth >= 0 && state.squareDepth >= 0) {
|
||||
if (index >= src.length) {
|
||||
throw new Error('The end of the string was reached with no closing bracket found.');
|
||||
}
|
||||
exports.parseChar(src[index++], state);
|
||||
}
|
||||
var end = index - 1;
|
||||
return {
|
||||
start: start,
|
||||
end: end,
|
||||
src: src.substring(start, end)
|
||||
};
|
||||
}
|
||||
|
||||
exports.parseUntil = parseUntil;
|
||||
function parseUntil(src, delimiter, options) {
|
||||
options = options || {};
|
||||
var includeLineComment = options.includeLineComment || false;
|
||||
var start = options.start || 0;
|
||||
var index = start;
|
||||
var state = exports.defaultState();
|
||||
while (state.isString() || state.regexp || state.blockComment ||
|
||||
(!includeLineComment && state.lineComment) || !startsWith(src, delimiter, index)) {
|
||||
exports.parseChar(src[index++], state);
|
||||
}
|
||||
var end = index;
|
||||
return {
|
||||
start: start,
|
||||
end: end,
|
||||
src: src.substring(start, end)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
exports.parseChar = parseChar;
|
||||
function parseChar(character, state) {
|
||||
if (character.length !== 1) throw new Error('Character must be a string of length 1');
|
||||
state = state || exports.defaultState();
|
||||
state.src = state.src || '';
|
||||
state.src += character;
|
||||
var wasComment = state.blockComment || state.lineComment;
|
||||
var lastChar = state.history ? state.history[0] : '';
|
||||
|
||||
if (state.regexpStart) {
|
||||
if (character === '/' || character == '*') {
|
||||
state.regexp = false;
|
||||
}
|
||||
state.regexpStart = false;
|
||||
}
|
||||
if (state.lineComment) {
|
||||
if (character === '\n') {
|
||||
state.lineComment = false;
|
||||
}
|
||||
} else if (state.blockComment) {
|
||||
if (state.lastChar === '*' && character === '/') {
|
||||
state.blockComment = false;
|
||||
}
|
||||
} else if (state.singleQuote) {
|
||||
if (character === '\'' && !state.escaped) {
|
||||
state.singleQuote = false;
|
||||
} else if (character === '\\' && !state.escaped) {
|
||||
state.escaped = true;
|
||||
} else {
|
||||
state.escaped = false;
|
||||
}
|
||||
} else if (state.doubleQuote) {
|
||||
if (character === '"' && !state.escaped) {
|
||||
state.doubleQuote = false;
|
||||
} else if (character === '\\' && !state.escaped) {
|
||||
state.escaped = true;
|
||||
} else {
|
||||
state.escaped = false;
|
||||
}
|
||||
} else if (state.regexp) {
|
||||
if (character === '/' && !state.escaped) {
|
||||
state.regexp = false;
|
||||
} else if (character === '\\' && !state.escaped) {
|
||||
state.escaped = true;
|
||||
} else {
|
||||
state.escaped = false;
|
||||
}
|
||||
} else if (lastChar === '/' && character === '/') {
|
||||
state.history = state.history.substr(1);
|
||||
state.lineComment = true;
|
||||
} else if (lastChar === '/' && character === '*') {
|
||||
state.history = state.history.substr(1);
|
||||
state.blockComment = true;
|
||||
} else if (character === '/' && isRegexp(state.history)) {
|
||||
state.regexp = true;
|
||||
state.regexpStart = true;
|
||||
} else if (character === '\'') {
|
||||
state.singleQuote = true;
|
||||
} else if (character === '"') {
|
||||
state.doubleQuote = true;
|
||||
} else if (character === '(') {
|
||||
state.roundDepth++;
|
||||
} else if (character === ')') {
|
||||
state.roundDepth--;
|
||||
} else if (character === '{') {
|
||||
state.curlyDepth++;
|
||||
} else if (character === '}') {
|
||||
state.curlyDepth--;
|
||||
} else if (character === '[') {
|
||||
state.squareDepth++;
|
||||
} else if (character === ']') {
|
||||
state.squareDepth--;
|
||||
}
|
||||
if (!state.blockComment && !state.lineComment && !wasComment) state.history = character + state.history;
|
||||
state.lastChar = character; // store last character for ending block comments
|
||||
return state;
|
||||
}
|
||||
|
||||
exports.defaultState = function () { return new State() };
|
||||
function State() {
|
||||
this.lineComment = false;
|
||||
this.blockComment = false;
|
||||
|
||||
this.singleQuote = false;
|
||||
this.doubleQuote = false;
|
||||
this.regexp = false;
|
||||
|
||||
this.escaped = false;
|
||||
|
||||
this.roundDepth = 0;
|
||||
this.curlyDepth = 0;
|
||||
this.squareDepth = 0;
|
||||
|
||||
this.history = ''
|
||||
this.lastChar = ''
|
||||
}
|
||||
State.prototype.isString = function () {
|
||||
return this.singleQuote || this.doubleQuote;
|
||||
}
|
||||
State.prototype.isComment = function () {
|
||||
return this.lineComment || this.blockComment;
|
||||
}
|
||||
State.prototype.isNesting = function () {
|
||||
return this.isString() || this.isComment() || this.regexp || this.roundDepth > 0 || this.curlyDepth > 0 || this.squareDepth > 0
|
||||
}
|
||||
|
||||
function startsWith(str, start, i) {
|
||||
return str.substr(i || 0, start.length) === start;
|
||||
}
|
||||
|
||||
exports.isPunctuator = isPunctuator
|
||||
function isPunctuator(c) {
|
||||
if (!c) return true; // the start of a string is a punctuator
|
||||
var code = c.charCodeAt(0)
|
||||
|
||||
switch (code) {
|
||||
case 46: // . dot
|
||||
case 40: // ( open bracket
|
||||
case 41: // ) close bracket
|
||||
case 59: // ; semicolon
|
||||
case 44: // , comma
|
||||
case 123: // { open curly brace
|
||||
case 125: // } close curly brace
|
||||
case 91: // [
|
||||
case 93: // ]
|
||||
case 58: // :
|
||||
case 63: // ?
|
||||
case 126: // ~
|
||||
case 37: // %
|
||||
case 38: // &
|
||||
case 42: // *:
|
||||
case 43: // +
|
||||
case 45: // -
|
||||
case 47: // /
|
||||
case 60: // <
|
||||
case 62: // >
|
||||
case 94: // ^
|
||||
case 124: // |
|
||||
case 33: // !
|
||||
case 61: // =
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
exports.isKeyword = isKeyword
|
||||
function isKeyword(id) {
|
||||
return (id === 'if') || (id === 'in') || (id === 'do') || (id === 'var') || (id === 'for') || (id === 'new') ||
|
||||
(id === 'try') || (id === 'let') || (id === 'this') || (id === 'else') || (id === 'case') ||
|
||||
(id === 'void') || (id === 'with') || (id === 'enum') || (id === 'while') || (id === 'break') || (id === 'catch') ||
|
||||
(id === 'throw') || (id === 'const') || (id === 'yield') || (id === 'class') || (id === 'super') ||
|
||||
(id === 'return') || (id === 'typeof') || (id === 'delete') || (id === 'switch') || (id === 'export') ||
|
||||
(id === 'import') || (id === 'default') || (id === 'finally') || (id === 'extends') || (id === 'function') ||
|
||||
(id === 'continue') || (id === 'debugger') || (id === 'package') || (id === 'private') || (id === 'interface') ||
|
||||
(id === 'instanceof') || (id === 'implements') || (id === 'protected') || (id === 'public') || (id === 'static') ||
|
||||
(id === 'yield') || (id === 'let');
|
||||
}
|
||||
|
||||
function isRegexp(history) {
|
||||
//could be start of regexp or divide sign
|
||||
|
||||
history = history.replace(/^\s*/, '');
|
||||
|
||||
//unless its an `if`, `while`, `for` or `with` it's a divide, so we assume it's a divide
|
||||
if (history[0] === ')') return false;
|
||||
//unless it's a function expression, it's a regexp, so we assume it's a regexp
|
||||
if (history[0] === '}') return true;
|
||||
//any punctuation means it's a regexp
|
||||
if (isPunctuator(history[0])) return true;
|
||||
//if the last thing was a keyword then it must be a regexp (e.g. `typeof /foo/`)
|
||||
if (/^\w+\b/.test(history) && isKeyword(/^\w+\b/.exec(history)[0].split('').reverse().join(''))) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
56
node_modules/jade/node_modules/character-parser/package.json
generated
vendored
Normal file
56
node_modules/jade/node_modules/character-parser/package.json
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "character-parser",
|
||||
"version": "1.2.1",
|
||||
"description": "Parse JavaScript one character at a time to look for snippets in Templates. This is not a validator, it's just designed to allow you to have sections of JavaScript delimited by brackets robustly.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "mocha -R spec"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ForbesLindesay/character-parser.git"
|
||||
},
|
||||
"keywords": [
|
||||
"parser",
|
||||
"JavaScript",
|
||||
"bracket",
|
||||
"nesting",
|
||||
"comment",
|
||||
"string",
|
||||
"escape",
|
||||
"escaping"
|
||||
],
|
||||
"author": {
|
||||
"name": "ForbesLindesay"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"better-assert": "~1.0.0",
|
||||
"mocha": "~1.9.0"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/ForbesLindesay/character-parser/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ForbesLindesay/character-parser",
|
||||
"_id": "character-parser@1.2.1",
|
||||
"dist": {
|
||||
"shasum": "c0dde4ab182713b919b970959a123ecc1a30fcd6",
|
||||
"tarball": "http://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz"
|
||||
},
|
||||
"_from": "character-parser@1.2.1",
|
||||
"_npmVersion": "1.4.3",
|
||||
"_npmUser": {
|
||||
"name": "forbeslindesay",
|
||||
"email": "forbes@lindeay.co.uk"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "forbeslindesay",
|
||||
"email": "forbes@lindesay.co.uk"
|
||||
}
|
||||
],
|
||||
"directories": {},
|
||||
"_shasum": "c0dde4ab182713b919b970959a123ecc1a30fcd6",
|
||||
"_resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
||||
985
node_modules/jade/node_modules/clean-css/History.md
generated
vendored
Normal file
985
node_modules/jade/node_modules/clean-css/History.md
generated
vendored
Normal file
@@ -0,0 +1,985 @@
|
||||
[3.4.2 / 2015-09-14](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.1...v3.4.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#598](https://github.com/jakubpawlowicz/clean-css/issues/598) - restructuring border properties.
|
||||
* Fixed issue [#654](https://github.com/jakubpawlowicz/clean-css/issues/654) - disables length optimizations.
|
||||
* Fixed issue [#655](https://github.com/jakubpawlowicz/clean-css/issues/655) - shorthands override merging.
|
||||
* Fixed issue [#660](https://github.com/jakubpawlowicz/clean-css/issues/660) - !important token overriding.
|
||||
* Fixed issue [#662](https://github.com/jakubpawlowicz/clean-css/issues/662) - !important selector reducing.
|
||||
* Fixed issue [#667](https://github.com/jakubpawlowicz/clean-css/issues/667) - rebasing remote URLs.
|
||||
|
||||
[3.4.1 / 2015-08-27](https://github.com/jakubpawlowicz/clean-css/compare/v3.4.0...v3.4.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#652](https://github.com/jakubpawlowicz/clean-css/issues/652) - order of restoring and removing tokens.
|
||||
|
||||
[3.4.0 / 2015-08-27](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.10...v3.4.0)
|
||||
==================
|
||||
|
||||
* Adds an option for a fine-grained `@import` control.
|
||||
* Adds unit compatibility switches to disable length optimizations.
|
||||
* Adds inferring proxy settings from HTTP_PROXY environment variable.
|
||||
* Adds support for Polymer / Web Components special selectors.
|
||||
* Adds support for Polymer mixins.
|
||||
* Adds testing source maps in batch mode.
|
||||
* Unifies wrappers for simple & advanced optimizations.
|
||||
* Fixed issue [#596](https://github.com/jakubpawlowicz/clean-css/issues/596) - support for !ie IE<8 hack.
|
||||
* Fixed issue [#599](https://github.com/jakubpawlowicz/clean-css/issues/599) - support for inlined source maps.
|
||||
* Fixed issue [#607](https://github.com/jakubpawlowicz/clean-css/issues/607) - adds better rule reordering.
|
||||
* Fixed issue [#612](https://github.com/jakubpawlowicz/clean-css/issues/612) - adds HTTP proxy support.
|
||||
* Fixed issue [#618](https://github.com/jakubpawlowicz/clean-css/issues/618) - adds safer function validation.
|
||||
* Fixed issue [#625](https://github.com/jakubpawlowicz/clean-css/issues/625) - adds length unit optimizations.
|
||||
* Fixed issue [#632](https://github.com/jakubpawlowicz/clean-css/issues/632) - adds disabling remote `import`s.
|
||||
* Fixed issue [#635](https://github.com/jakubpawlowicz/clean-css/issues/635) - adds safer `0%` optimizations.
|
||||
* Fixed issue [#644](https://github.com/jakubpawlowicz/clean-css/issues/644) - adds time unit optimizations.
|
||||
* Fixed issue [#645](https://github.com/jakubpawlowicz/clean-css/issues/645) - adds bottom to top `media` merging.
|
||||
* Fixed issue [#648](https://github.com/jakubpawlowicz/clean-css/issues/648) - adds property level at-rule support.
|
||||
|
||||
[3.3.10 / 2015-08-27](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.9...v3.3.10)
|
||||
==================
|
||||
|
||||
* Adds better comments + keepBreaks handling.
|
||||
* Adds better text normalizing in source maps mode.
|
||||
* Fixes non-adjacent optimizations for source maps.
|
||||
* Fixes removing unused items.
|
||||
* Improves `outline` break up with source maps.
|
||||
* Refixed issue [#629](https://github.com/jakubpawlowicz/clean-css/issues/629) - source maps & background shorthands.
|
||||
|
||||
[3.3.9 / 2015-08-09](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.8...v3.3.9)
|
||||
==================
|
||||
|
||||
* Fixed issue [#640](https://github.com/jakubpawlowicz/clean-css/issues/640) - URI processing regression.
|
||||
|
||||
[3.3.8 / 2015-08-06](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.7...v3.3.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#629](https://github.com/jakubpawlowicz/clean-css/issues/629) - source maps & background shorthands.
|
||||
* Fixed issue [#630](https://github.com/jakubpawlowicz/clean-css/issues/630) - vendor prefixed flex optimizations.
|
||||
* Fixed issue [#633](https://github.com/jakubpawlowicz/clean-css/issues/633) - handling data URI with brackets.
|
||||
* Fixed issue [#634](https://github.com/jakubpawlowicz/clean-css/issues/634) - merging :placeholder selectors.
|
||||
|
||||
[3.3.7 / 2015-07-29](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.6...v3.3.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#616](https://github.com/jakubpawlowicz/clean-css/issues/616) - ordering in restructuring.
|
||||
|
||||
[3.3.6 / 2015-07-14](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.5...v3.3.6)
|
||||
==================
|
||||
|
||||
* Fixed issue [#620](https://github.com/jakubpawlowicz/clean-css/issues/620) - `bold` style in font shorthands.
|
||||
|
||||
[3.3.5 / 2015-07-01](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.4...v3.3.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#608](https://github.com/jakubpawlowicz/clean-css/issues/608) - custom URI protocols handling.
|
||||
|
||||
[3.3.4 / 2015-06-24](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.3...v3.3.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#610](https://github.com/jakubpawlowicz/clean-css/issues/610) - `border:inherit` restoring.
|
||||
* Fixed issue [#611](https://github.com/jakubpawlowicz/clean-css/issues/611) - edge case in quote stripping.
|
||||
|
||||
[3.3.3 / 2015-06-16](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.2...v3.3.3)
|
||||
==================
|
||||
|
||||
* Fixed issue [#603](https://github.com/jakubpawlowicz/clean-css/issues/603) - IE suffix hack defaults to on.
|
||||
|
||||
[3.3.2 / 2015-06-14](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.1...v3.3.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#595](https://github.com/jakubpawlowicz/clean-css/issues/595) - more relaxed block matching.
|
||||
* Fixed issue [#601](https://github.com/jakubpawlowicz/clean-css/issues/601) - percentage minifying inside `flex`.
|
||||
* Fixed issue [#602](https://github.com/jakubpawlowicz/clean-css/issues/602) - backslash IE hacks after a space.
|
||||
|
||||
[3.3.1 / 2015-06-02](https://github.com/jakubpawlowicz/clean-css/compare/v3.3.0...v3.3.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#590](https://github.com/jakubpawlowicz/clean-css/issues/590) - edge case in `@import` processing.
|
||||
|
||||
[3.3.0 / 2015-05-31](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.11...v3.3.0)
|
||||
==================
|
||||
|
||||
* Cleans up url rebase code getting rid of unnecessary state.
|
||||
* Cleans up tokenizer code getting rid of unnecessary state.
|
||||
* Moves source maps tracker into lib/source-maps/track.
|
||||
* Moves tokenizer code into lib/tokenizer.
|
||||
* Moves URL scanner into lib/urls/reduce (was named incorrectly before).
|
||||
* Moves URL rebasing & rewriting into lib/urls.
|
||||
* Fixed issue [#375](https://github.com/jakubpawlowicz/clean-css/issues/375) - unit compatibility switches.
|
||||
* Fixed issue [#436](https://github.com/jakubpawlowicz/clean-css/issues/436) - refactors URI rewriting.
|
||||
* Fixed issue [#448](https://github.com/jakubpawlowicz/clean-css/issues/448) - rebasing no protocol URIs.
|
||||
* Fixed issue [#517](https://github.com/jakubpawlowicz/clean-css/issues/517) - turning off color optimizations.
|
||||
* Fixed issue [#542](https://github.com/jakubpawlowicz/clean-css/issues/542) - space after closing brace in IE.
|
||||
* Fixed issue [#562](https://github.com/jakubpawlowicz/clean-css/issues/562) - optimizing invalid color values.
|
||||
* Fixed issue [#563](https://github.com/jakubpawlowicz/clean-css/issues/563) - `background:inherit` restoring.
|
||||
* Fixed issue [#570](https://github.com/jakubpawlowicz/clean-css/issues/570) - rebasing "no-url()" imports.
|
||||
* Fixed issue [#574](https://github.com/jakubpawlowicz/clean-css/issues/574) - rewriting internal URLs.
|
||||
* Fixed issue [#575](https://github.com/jakubpawlowicz/clean-css/issues/575) - missing directory as a `target`.
|
||||
* Fixed issue [#577](https://github.com/jakubpawlowicz/clean-css/issues/577) - `background-clip` into shorthand.
|
||||
* Fixed issue [#579](https://github.com/jakubpawlowicz/clean-css/issues/579) - `background-origin` into shorthand.
|
||||
* Fixed issue [#580](https://github.com/jakubpawlowicz/clean-css/issues/580) - mixed `@import` processing.
|
||||
* Fixed issue [#582](https://github.com/jakubpawlowicz/clean-css/issues/582) - overriding with prefixed values.
|
||||
* Fixed issue [#583](https://github.com/jakubpawlowicz/clean-css/issues/583) - URL quoting for SVG data.
|
||||
* Fixed issue [#587](https://github.com/jakubpawlowicz/clean-css/issues/587) - too aggressive `border` reordering.
|
||||
|
||||
[3.2.11 / 2015-05-31](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.10...v3.2.11)
|
||||
==================
|
||||
|
||||
* Fixed issue [#563](https://github.com/jakubpawlowicz/clean-css/issues/563) - `background:inherit` restoring.
|
||||
* Fixed issue [#582](https://github.com/jakubpawlowicz/clean-css/issues/582) - overriding with prefixed values.
|
||||
* Fixed issue [#583](https://github.com/jakubpawlowicz/clean-css/issues/583) - URL quoting for SVG data.
|
||||
* Fixed issue [#587](https://github.com/jakubpawlowicz/clean-css/issues/587) - too aggressive `border` reordering.
|
||||
|
||||
[3.2.10 / 2015-05-14](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.9...v3.2.10)
|
||||
==================
|
||||
|
||||
* Fixed issue [#572](https://github.com/jakubpawlowicz/clean-css/issues/572) - empty elements removal.
|
||||
|
||||
[3.2.9 / 2015-05-08](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.8...v3.2.9)
|
||||
==================
|
||||
|
||||
* Fixed issue [#567](https://github.com/jakubpawlowicz/clean-css/issues/567) - merging colors as functions.
|
||||
|
||||
[3.2.8 / 2015-05-04](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.7...v3.2.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#561](https://github.com/jakubpawlowicz/clean-css/issues/561) - restructuring special selectors.
|
||||
|
||||
[3.2.7 / 2015-05-03](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.6...v3.2.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#551](https://github.com/jakubpawlowicz/clean-css/issues/551) - edge case in restructuring.
|
||||
* Fixed issue [#553](https://github.com/jakubpawlowicz/clean-css/issues/553) - another style of SVG fallback.
|
||||
* Fixed issue [#558](https://github.com/jakubpawlowicz/clean-css/issues/558) - units in same selector merging.
|
||||
|
||||
[3.2.6 / 2015-04-28](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.5...v3.2.6)
|
||||
==================
|
||||
|
||||
* Fixed issue [#550](https://github.com/jakubpawlowicz/clean-css/issues/550) - proper `contentSources` tracking.
|
||||
* Fixed issue [#556](https://github.com/jakubpawlowicz/clean-css/issues/556) - regression in IE backslash hacks.
|
||||
|
||||
[3.2.5 / 2015-04-25](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.4...v3.2.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#543](https://github.com/jakubpawlowicz/clean-css/issues/543) - better "comment in body" handling.
|
||||
* Fixed issue [#548](https://github.com/jakubpawlowicz/clean-css/issues/548) - regression in font minifying.
|
||||
* Fixed issue [#549](https://github.com/jakubpawlowicz/clean-css/issues/549) - special comments in source maps.
|
||||
|
||||
[3.2.4 / 2015-04-24](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.3...v3.2.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#544](https://github.com/jakubpawlowicz/clean-css/issues/544) - regression in same value merging.
|
||||
* Fixed issue [#546](https://github.com/jakubpawlowicz/clean-css/issues/546) - IE<11 `calc()` issue.
|
||||
|
||||
[3.2.3 / 2015-04-22](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.2...v3.2.3)
|
||||
==================
|
||||
|
||||
* Fixed issue [#541](https://github.com/jakubpawlowicz/clean-css/issues/541) - `outline-style:auto` in shorthand.
|
||||
|
||||
[3.2.2 / 2015-04-21](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.1...v3.2.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#537](https://github.com/jakubpawlowicz/clean-css/issues/537) - regression in simple optimizer.
|
||||
|
||||
[3.2.1 / 2015-04-20](https://github.com/jakubpawlowicz/clean-css/compare/v3.2.0...v3.2.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#534](https://github.com/jakubpawlowicz/clean-css/issues/534) - wrong `@font-face` stringifying.
|
||||
|
||||
[3.2.0 / 2015-04-19](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.9...v3.2.0)
|
||||
==================
|
||||
|
||||
* Bumps commander to 2.8.x.
|
||||
* Fixes remote asset rebasing when passing data as a hash.
|
||||
* Improves path resolution inside source maps.
|
||||
* Makes `root` option implicitely default to `process.cwd()`.
|
||||
* Fixed issue [#371](https://github.com/jakubpawlowicz/clean-css/issues/371) - `background` fallback with `none`.
|
||||
* Fixed issue [#376](https://github.com/jakubpawlowicz/clean-css/issues/376) - option to disable `0[unit]` -> `0`.
|
||||
* Fixed issue [#396](https://github.com/jakubpawlowicz/clean-css/issues/396) - better input source maps tracking.
|
||||
* Fixed issue [#397](https://github.com/jakubpawlowicz/clean-css/issues/397) - support for source map sources.
|
||||
* Fixed issue [#399](https://github.com/jakubpawlowicz/clean-css/issues/399) - support compacting with source maps.
|
||||
* Fixed issue [#429](https://github.com/jakubpawlowicz/clean-css/issues/429) - unifies data tokenization.
|
||||
* Fixed issue [#446](https://github.com/jakubpawlowicz/clean-css/issues/446) - `list-style` fuzzy matching.
|
||||
* Fixed issue [#468](https://github.com/jakubpawlowicz/clean-css/issues/468) - bumps `source-map` to 0.4.x.
|
||||
* Fixed issue [#480](https://github.com/jakubpawlowicz/clean-css/issues/480) - extracting uppercase property names.
|
||||
* Fixed issue [#487](https://github.com/jakubpawlowicz/clean-css/issues/487) - source map paths under Windows.
|
||||
* Fixed issue [#490](https://github.com/jakubpawlowicz/clean-css/issues/490) - vendor prefixed multivalue `background`.
|
||||
* Fixed issue [#500](https://github.com/jakubpawlowicz/clean-css/issues/500) - merging duplicate adjacent properties.
|
||||
* Fixed issue [#504](https://github.com/jakubpawlowicz/clean-css/issues/504) - keeping `url()` quotes.
|
||||
* Fixed issue [#507](https://github.com/jakubpawlowicz/clean-css/issues/507) - merging longhands into many shorthands.
|
||||
* Fixed issue [#508](https://github.com/jakubpawlowicz/clean-css/issues/508) - removing duplicate media queries.
|
||||
* Fixed issue [#521](https://github.com/jakubpawlowicz/clean-css/issues/521) - unit optimizations inside `calc()`.
|
||||
* Fixed issue [#524](https://github.com/jakubpawlowicz/clean-css/issues/524) - timeouts in `@import` inlining.
|
||||
* Fixed issue [#526](https://github.com/jakubpawlowicz/clean-css/issues/526) - shorthand overriding into a function.
|
||||
* Fixed issue [#528](https://github.com/jakubpawlowicz/clean-css/issues/528) - better support for IE<9 hacks.
|
||||
* Fixed issue [#529](https://github.com/jakubpawlowicz/clean-css/issues/529) - wrong font weight minification.
|
||||
|
||||
[3.1.9 / 2015-04-04](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.8...v3.1.9)
|
||||
==================
|
||||
|
||||
* Fixes issue [#511](https://github.com/jakubpawlowicz/clean-css/issues/511) - `)` advanced processing.
|
||||
|
||||
[3.1.8 / 2015-03-17](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.7...v3.1.8)
|
||||
==================
|
||||
|
||||
* Fixes issue [#498](https://github.com/jakubpawlowicz/clean-css/issues/498) - reordering and flexbox.
|
||||
* Fixes issue [#499](https://github.com/jakubpawlowicz/clean-css/issues/499) - too aggressive `-` removal.
|
||||
|
||||
[3.1.7 / 2015-03-16](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.6...v3.1.7)
|
||||
==================
|
||||
|
||||
* Backports fix to [#480](https://github.com/jakubpawlowicz/clean-css/issues/480) - reordering and uppercase properties.
|
||||
* Fixes issue [#496](https://github.com/jakubpawlowicz/clean-css/issues/496) - space after bracket removal.
|
||||
|
||||
[3.1.6 / 2015-03-12](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.5...v3.1.6)
|
||||
==================
|
||||
|
||||
* Fixes issue [#489](https://github.com/jakubpawlowicz/clean-css/issues/489) - `AlphaImageLoader` IE filter.
|
||||
|
||||
[3.1.5 / 2015-03-06](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.4...v3.1.5)
|
||||
==================
|
||||
|
||||
* Fixes issue [#483](https://github.com/jakubpawlowicz/clean-css/issues/483) - property order in restructuring.
|
||||
|
||||
[3.1.4 / 2015-03-04](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.3...v3.1.4)
|
||||
==================
|
||||
|
||||
* Fixes issue [#472](https://github.com/jakubpawlowicz/clean-css/issues/472) - broken function minification.
|
||||
* Fixes issue [#477](https://github.com/jakubpawlowicz/clean-css/issues/477) - `@import`s order in restructuring.
|
||||
* Fixes issue [#478](https://github.com/jakubpawlowicz/clean-css/issues/478) - ultimate fix to brace whitespace.
|
||||
|
||||
[3.1.3 / 2015-03-03](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.2...v3.1.3)
|
||||
==================
|
||||
|
||||
* Fixes issue [#464](https://github.com/jakubpawlowicz/clean-css/issues/464) - data URI with quoted braces.
|
||||
* Fixes issue [#475](https://github.com/jakubpawlowicz/clean-css/issues/475) - whitespace after closing brace.
|
||||
|
||||
[3.1.2 / 2015-03-01](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.1...v3.1.2)
|
||||
==================
|
||||
|
||||
* Refixed issue [#471](https://github.com/jakubpawlowicz/clean-css/issues/471) - correct order after restructuring.
|
||||
* Fixes issue [#466](https://github.com/jakubpawlowicz/clean-css/issues/466) - rebuilding background shorthand.
|
||||
* Fixes issue [#462](https://github.com/jakubpawlowicz/clean-css/issues/462) - escaped apostrophes in selectors.
|
||||
|
||||
[3.1.1 / 2015-02-27](https://github.com/jakubpawlowicz/clean-css/compare/v3.1.0...v3.1.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#469](https://github.com/jakubpawlowicz/clean-css/issues/469) - extracting broken property.
|
||||
* Fixed issue [#470](https://github.com/jakubpawlowicz/clean-css/issues/470) - negative padding removal.
|
||||
* Fixed issue [#471](https://github.com/jakubpawlowicz/clean-css/issues/471) - correct order after restructuring.
|
||||
|
||||
[3.1.0 / 2015-02-26](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.10...v3.1.0)
|
||||
==================
|
||||
|
||||
* Adds `0deg` to `0` minification where possible.
|
||||
* Adds better non-adjacent selector merging when body is the same.
|
||||
* Adds official support for node.js 0.12.
|
||||
* Adds official support for io.js 1.0.
|
||||
* Adds restructuring optimizations to reorganize selectors, which vastly improves minification.
|
||||
* Fixed issue [#158](https://github.com/jakubpawlowicz/clean-css/issues/158) - adds body-based selectors reduction.
|
||||
* Fixed issue [#182](https://github.com/jakubpawlowicz/clean-css/issues/182) - removing space after closing brace.
|
||||
* Fixed issue [#204](https://github.com/jakubpawlowicz/clean-css/issues/204) - `@media` merging.
|
||||
* Fixed issue [#351](https://github.com/jakubpawlowicz/clean-css/issues/351) - remote `@import`s after content.
|
||||
* Fixed issue [#357](https://github.com/jakubpawlowicz/clean-css/issues/357) - non-standard but valid URLs.
|
||||
* Fixed issue [#416](https://github.com/jakubpawlowicz/clean-css/issues/416) - accepts hash as `minify` argument.
|
||||
* Fixed issue [#419](https://github.com/jakubpawlowicz/clean-css/issues/419) - multiple input source maps.
|
||||
* Fixed issue [#435](https://github.com/jakubpawlowicz/clean-css/issues/435) - `background-clip` in shorthand.
|
||||
* Fixed issue [#439](https://github.com/jakubpawlowicz/clean-css/issues/439) - `background-origin` in shorthand.
|
||||
* Fixed issue [#442](https://github.com/jakubpawlowicz/clean-css/issues/442) - space before adjacent `nav`.
|
||||
* Fixed issue [#445](https://github.com/jakubpawlowicz/clean-css/issues/445) - regression issue in url processor.
|
||||
* Fixed issue [#449](https://github.com/jakubpawlowicz/clean-css/issues/449) - warns of missing close braces.
|
||||
* Fixed issue [#463](https://github.com/jakubpawlowicz/clean-css/issues/463) - relative remote `@import` URLs.
|
||||
|
||||
[3.0.10 / 2015-02-07](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.9...v3.0.10)
|
||||
==================
|
||||
|
||||
* Fixed issue [#453](https://github.com/jakubpawlowicz/clean-css/issues/453) - double `background-repeat`.
|
||||
* Fixed issue [#455](https://github.com/jakubpawlowicz/clean-css/issues/455) - property extracting regression.
|
||||
|
||||
[3.0.9 / 2015-02-04](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.8...v3.0.9)
|
||||
==================
|
||||
|
||||
* Fixed issue [#452](https://github.com/jakubpawlowicz/clean-css/issues/452) - regression in advanced merging.
|
||||
|
||||
[3.0.8 / 2015-01-31](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.7...v3.0.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#447](https://github.com/jakubpawlowicz/clean-css/issues/447) - `background-color` in shorthands.
|
||||
* Fixed issue [#450](https://github.com/jakubpawlowicz/clean-css/issues/450) - name to hex color converting.
|
||||
|
||||
[3.0.7 / 2015-01-22](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.6...v3.0.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#441](https://github.com/jakubpawlowicz/clean-css/issues/441) - hex to name color converting.
|
||||
|
||||
[3.0.6 / 2015-01-20](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.5...v3.0.6)
|
||||
==================
|
||||
|
||||
* Refixed issue [#414](https://github.com/jakubpawlowicz/clean-css/issues/414) - source maps position fallback.
|
||||
|
||||
[3.0.5 / 2015-01-18](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.4...v3.0.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#414](https://github.com/jakubpawlowicz/clean-css/issues/414) - source maps position fallback.
|
||||
* Fixed issue [#433](https://github.com/jakubpawlowicz/clean-css/issues/433) - meging `!important` in shorthands.
|
||||
|
||||
[3.0.4 / 2015-01-11](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.3...v3.0.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#314](https://github.com/jakubpawlowicz/clean-css/issues/314) - spaces inside `calc`.
|
||||
|
||||
[3.0.3 / 2015-01-07](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.2...v3.0.3)
|
||||
==================
|
||||
|
||||
* Just a version bump as npm incorrectly things 2.2.23 is the latest one.
|
||||
|
||||
[3.0.2 / 2015-01-04](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.1...v3.0.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#422](https://github.com/jakubpawlowicz/clean-css/issues/422) - handling `calc` as a unit.
|
||||
|
||||
[3.0.1 / 2014-12-19](https://github.com/jakubpawlowicz/clean-css/compare/v3.0.0...v3.0.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#410](https://github.com/jakubpawlowicz/clean-css/issues/410) - advanced merging and comments.
|
||||
* Fixed issue [#411](https://github.com/jakubpawlowicz/clean-css/issues/411) - properties and important comments.
|
||||
|
||||
[3.0.0 / 2014-12-18](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.22...v3.0.0)
|
||||
==================
|
||||
|
||||
* Adds more granular control over compatibility settings.
|
||||
* Adds support for @counter-style at-rule.
|
||||
* Adds `--source-map`/`sourceMap` switch for building input's source map.
|
||||
* Adds `--skip-shorthand-compacting`/`shorthandComacting` option for disabling shorthand compacting.
|
||||
* Allows `target` option to be a path to a folder instead of a file.
|
||||
* Allows disabling rounding precision. By [@superlukas](https://github.com/superlukas).
|
||||
* Breaks 2.x compatibility for using CleanCSS as a function.
|
||||
* Changes `minify` method output to handle multiple outputs.
|
||||
* Reworks minification to tokenize first then minify.
|
||||
See [changes](https://github.com/jakubpawlowicz/clean-css/compare/b06f37d...dd8c14a).
|
||||
* Removes support for node.js 0.8.x.
|
||||
* Renames `noAdvanced` option into `advanced`.
|
||||
* Renames `noAggressiveMerging` option into `aggressiveMerging`.
|
||||
* Renames `noRebase` option into `rebase`.
|
||||
* Speeds up advanced processing by shortening optimize loop.
|
||||
* Fixed issue [#125](https://github.com/jakubpawlowicz/clean-css/issues/125) - source maps!
|
||||
* Fixed issue [#344](https://github.com/jakubpawlowicz/clean-css/issues/344) - merging `background-size` into shorthand.
|
||||
* Fixed issue [#352](https://github.com/jakubpawlowicz/clean-css/issues/352) - honors rebasing in imported stylesheets.
|
||||
* Fixed issue [#360](https://github.com/jakubpawlowicz/clean-css/issues/360) - adds 7 extra CSS colors.
|
||||
* Fixed issue [#363](https://github.com/jakubpawlowicz/clean-css/issues/363) - `rem` units overriding `px`.
|
||||
* Fixed issue [#373](https://github.com/jakubpawlowicz/clean-css/issues/373) - proper `background` shorthand merging.
|
||||
* Fixed issue [#395](https://github.com/jakubpawlowicz/clean-css/issues/395) - unescaped brackets in data URIs.
|
||||
* Fixed issue [#398](https://github.com/jakubpawlowicz/clean-css/issues/398) - restoring important comments.
|
||||
* Fixed issue [#400](https://github.com/jakubpawlowicz/clean-css/issues/400) - API to accept an array of filenames.
|
||||
* Fixed issue [#403](https://github.com/jakubpawlowicz/clean-css/issues/403) - tracking input files in source maps.
|
||||
* Fixed issue [#404](https://github.com/jakubpawlowicz/clean-css/issues/404) - no state sharing in API.
|
||||
* Fixed issue [#405](https://github.com/jakubpawlowicz/clean-css/issues/405) - disables default `background-size` merging.
|
||||
* Refixed issue [#304](https://github.com/jakubpawlowicz/clean-css/issues/304) - `background-position` merging.
|
||||
|
||||
[2.2.22 / 2014-12-13](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.21...v2.2.22)
|
||||
==================
|
||||
|
||||
* Backports fix to issue [#304](https://github.com/jakubpawlowicz/clean-css/issues/304) - `background-position` merging.
|
||||
|
||||
[2.2.21 / 2014-12-10](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.20...v2.2.21)
|
||||
==================
|
||||
|
||||
* Backports fix to issue [#373](https://github.com/jakubpawlowicz/clean-css/issues/373) - `background` shorthand merging.
|
||||
|
||||
[2.2.20 / 2014-12-02](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.19...v2.2.20)
|
||||
==================
|
||||
|
||||
* Backports fix to issue [#390](https://github.com/jakubpawlowicz/clean-css/issues/390) - pseudo-class merging.
|
||||
|
||||
[2.2.19 / 2014-11-20](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.18...v2.2.19)
|
||||
==================
|
||||
|
||||
* Fixed issue [#385](https://github.com/jakubpawlowicz/clean-css/issues/385) - edge cases in processing cut off data.
|
||||
|
||||
[2.2.18 / 2014-11-17](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.17...v2.2.18)
|
||||
==================
|
||||
|
||||
* Fixed issue [#383](https://github.com/jakubpawlowicz/clean-css/issues/383) - rounding fractions once again.
|
||||
|
||||
[2.2.17 / 2014-11-09](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.16...v2.2.17)
|
||||
==================
|
||||
|
||||
* Fixed issue [#380](https://github.com/jakubpawlowicz/clean-css/issues/380) - rounding fractions to a whole number.
|
||||
|
||||
[2.2.16 / 2014-09-16](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.15...v2.2.16)
|
||||
==================
|
||||
|
||||
* Fixed issue [#359](https://github.com/jakubpawlowicz/clean-css/issues/359) - handling escaped double backslash.
|
||||
* Fixed issue [#358](https://github.com/jakubpawlowicz/clean-css/issues/358) - property merging in compatibility mode.
|
||||
* Fixed issue [#356](https://github.com/jakubpawlowicz/clean-css/issues/356) - preserving `*+html` hack.
|
||||
* Fixed issue [#354](https://github.com/jakubpawlowicz/clean-css/issues/354) - `!important` overriding in shorthands.
|
||||
|
||||
[2.2.15 / 2014-09-01](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.14...v2.2.15)
|
||||
==================
|
||||
|
||||
* Fixed issue [#343](https://github.com/jakubpawlowicz/clean-css/issues/343) - too aggressive `rgba`/`hsla` minification.
|
||||
* Fixed issue [#345](https://github.com/jakubpawlowicz/clean-css/issues/345) - URL rebasing for document relative ones.
|
||||
* Fixed issue [#346](https://github.com/jakubpawlowicz/clean-css/issues/346) - overriding `!important` by `!important`.
|
||||
* Fixed issue [#350](https://github.com/jakubpawlowicz/clean-css/issues/350) - edge cases in `@import` processing.
|
||||
|
||||
[2.2.14 / 2014-08-25](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.13...v2.2.14)
|
||||
==================
|
||||
|
||||
* Makes multival operations idempotent.
|
||||
* Fixed issue [#339](https://github.com/jakubpawlowicz/clean-css/issues/339) - skips invalid properties.
|
||||
* Fixed issue [#341](https://github.com/jakubpawlowicz/clean-css/issues/341) - ensure output is shorter than input.
|
||||
|
||||
[2.2.13 / 2014-08-12](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.12...v2.2.13)
|
||||
==================
|
||||
|
||||
* Fixed issue [#337](https://github.com/jakubpawlowicz/clean-css/issues/337) - handling component importance.
|
||||
|
||||
[2.2.12 / 2014-08-02](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.11...v2.2.12)
|
||||
==================
|
||||
|
||||
* Fixed issue with tokenizer removing first selector after an unknown @ rule.
|
||||
* Fixed issue [#329](https://github.com/jakubpawlowicz/clean-css/issues/329) - `font` shorthands incorrectly processed.
|
||||
* Fixed issue [#332](https://github.com/jakubpawlowicz/clean-css/issues/332) - `background` shorthand with colors.
|
||||
* Refixed issue [#325](https://github.com/jakubpawlowicz/clean-css/issues/325) - invalid charset declarations.
|
||||
|
||||
[2.2.11 / 2014-07-28](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.10...v2.2.11)
|
||||
==================
|
||||
|
||||
* Fixed issue [#326](https://github.com/jakubpawlowicz/clean-css/issues/326) - `background-size` regression.
|
||||
|
||||
[2.2.10 / 2014-07-27](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.9...v2.2.10)
|
||||
==================
|
||||
|
||||
* Improved performance of advanced mode validators.
|
||||
* Fixed issue [#307](https://github.com/jakubpawlowicz/clean-css/issues/307) - `background-color` in multiple backgrounds.
|
||||
* Fixed issue [#322](https://github.com/jakubpawlowicz/clean-css/issues/322) - adds `background-size` support.
|
||||
* Fixed issue [#323](https://github.com/jakubpawlowicz/clean-css/issues/323) - stripping variable references.
|
||||
* Fixed issue [#325](https://github.com/jakubpawlowicz/clean-css/issues/325) - removing invalid `@charset` declarations.
|
||||
|
||||
[2.2.9 / 2014-07-23](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.8...v2.2.9)
|
||||
==================
|
||||
|
||||
* Adds `background` normalization according to W3C spec.
|
||||
* Fixed issue [#316](https://github.com/jakubpawlowicz/clean-css/issues/316) - incorrect `background` processing.
|
||||
|
||||
[2.2.8 / 2014-07-14](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.7...v2.2.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#313](https://github.com/jakubpawlowicz/clean-css/issues/313) - processing comment marks in URLs.
|
||||
* Fixed issue [#315](https://github.com/jakubpawlowicz/clean-css/issues/315) - `rgba`/`hsla` -> `transparent` in gradients.
|
||||
|
||||
[2.2.7 / 2014-07-10](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.6...v2.2.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#304](https://github.com/jakubpawlowicz/clean-css/issues/304) - merging multiple backgrounds.
|
||||
* Fixed issue [#312](https://github.com/jakubpawlowicz/clean-css/issues/312) - merging with mixed repeat.
|
||||
|
||||
[2.2.6 / 2014-07-05](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.5...v2.2.6)
|
||||
==================
|
||||
|
||||
* Adds faster quote matching in QuoteScanner.
|
||||
* Improves QuoteScanner to handle comments correctly.
|
||||
* Fixed issue [#308](https://github.com/jakubpawlowicz/clean-css/issues/308) - parsing comments in quoted URLs.
|
||||
* Fixed issue [#311](https://github.com/jakubpawlowicz/clean-css/issues/311) - leading/trailing decimal points.
|
||||
|
||||
[2.2.5 / 2014-06-29](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.4...v2.2.5)
|
||||
==================
|
||||
|
||||
* Adds removing extra spaces around / in border-radius.
|
||||
* Adds replacing same horizontal & vertical value in border-radius.
|
||||
* Fixed issue [#305](https://github.com/jakubpawlowicz/clean-css/issues/305) - allows width keywords in `border-width`.
|
||||
|
||||
[2.2.4 / 2014-06-27](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.3...v2.2.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#301](https://github.com/jakubpawlowicz/clean-css/issues/301) - proper `border-radius` processing.
|
||||
* Fixed issue [#303](https://github.com/jakubpawlowicz/clean-css/issues/303) - correctly preserves viewport units.
|
||||
|
||||
[2.2.3 / 2014-06-24](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.2...v2.2.3)
|
||||
==================
|
||||
|
||||
* Fixed issue [#302](https://github.com/jakubpawlowicz/clean-css/issues/302) - handling of `outline-style: auto`.
|
||||
|
||||
[2.2.2 / 2014-06-18](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.1...v2.2.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#297](https://github.com/jakubpawlowicz/clean-css/issues/297) - `box-shadow` zeros minification.
|
||||
|
||||
[2.2.1 / 2014-06-14](https://github.com/jakubpawlowicz/clean-css/compare/v2.2.0...v2.2.1)
|
||||
==================
|
||||
|
||||
* Fixes new property optimizer for 'none' values.
|
||||
* Fixed issue [#294](https://github.com/jakubpawlowicz/clean-css/issues/294) - space after `rgba`/`hsla` in IE<=11.
|
||||
|
||||
[2.2.0 / 2014-06-11](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.8...v2.2.0)
|
||||
==================
|
||||
|
||||
* Adds a better algorithm for quotation marks' removal.
|
||||
* Adds a better non-adjacent optimizer compatible with the upcoming new property optimizer.
|
||||
* Adds minifying remote files directly from CLI.
|
||||
* Adds `--rounding-precision` to control rounding precision.
|
||||
* Moves quotation matching into a `QuoteScanner` class.
|
||||
* Adds `npm run browserify` for creating embeddable version of clean-css.
|
||||
* Fixed list-style-* advanced processing.
|
||||
* Fixed issue [#134](https://github.com/jakubpawlowicz/clean-css/issues/134) - merges properties into shorthand form.
|
||||
* Fixed issue [#164](https://github.com/jakubpawlowicz/clean-css/issues/164) - removes default values if not needed.
|
||||
* Fixed issue [#168](https://github.com/jakubpawlowicz/clean-css/issues/168) - adds better property merging algorithm.
|
||||
* Fixed issue [#173](https://github.com/jakubpawlowicz/clean-css/issues/173) - merges same properties if grouped.
|
||||
* Fixed issue [#184](https://github.com/jakubpawlowicz/clean-css/issues/184) - uses `!important` for optimization opportunities.
|
||||
* Fixed issue [#190](https://github.com/jakubpawlowicz/clean-css/issues/190) - uses shorthand to override another shorthand.
|
||||
* Fixed issue [#197](https://github.com/jakubpawlowicz/clean-css/issues/197) - adds borders merging by understandability.
|
||||
* Fixed issue [#210](https://github.com/jakubpawlowicz/clean-css/issues/210) - adds temporary workaround for aggressive merging.
|
||||
* Fixed issue [#246](https://github.com/jakubpawlowicz/clean-css/issues/246) - removes IE hacks when not in compatibility mode.
|
||||
* Fixed issue [#247](https://github.com/jakubpawlowicz/clean-css/issues/247) - removes deprecated `selectorsMergeMode` switch.
|
||||
* Refixed issue [#250](https://github.com/jakubpawlowicz/clean-css/issues/250) - based on new quotation marks removal.
|
||||
* Fixed issue [#257](https://github.com/jakubpawlowicz/clean-css/issues/257) - turns `rgba`/`hsla` to `transparent` if possible.
|
||||
* Fixed issue [#265](https://github.com/jakubpawlowicz/clean-css/issues/265) - adds support for multiple input files.
|
||||
* Fixed issue [#275](https://github.com/jakubpawlowicz/clean-css/issues/275) - handling transform properties.
|
||||
* Fixed issue [#276](https://github.com/jakubpawlowicz/clean-css/issues/276) - corrects unicode handling.
|
||||
* Fixed issue [#288](https://github.com/jakubpawlowicz/clean-css/issues/288) - adds smarter expression parsing.
|
||||
* Fixed issue [#293](https://github.com/jakubpawlowicz/clean-css/issues/293) - handles escaped `@` symbols in class names and IDs.
|
||||
|
||||
[2.1.8 / 2014-03-28](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.7...v2.1.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#267](https://github.com/jakubpawlowicz/clean-css/issues/267) - incorrect non-adjacent selector merging.
|
||||
|
||||
[2.1.7 / 2014-03-24](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.6...v2.1.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#264](https://github.com/jakubpawlowicz/clean-css/issues/264) - `@import` statements inside comments.
|
||||
|
||||
[2.1.6 / 2014-03-10](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.5...v2.1.6)
|
||||
==================
|
||||
|
||||
* Fixed issue [#258](https://github.com/jakubpawlowicz/clean-css/issues/258) - wrong `@import` handling in `EmptyRemoval`.
|
||||
|
||||
[2.1.5 / 2014-03-07](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.4...v2.1.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#255](https://github.com/jakubpawlowicz/clean-css/issues/255) - incorrect processing of a trailing `-0`.
|
||||
|
||||
[2.1.4 / 2014-03-01](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.3...v2.1.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#250](https://github.com/jakubpawlowicz/clean-css/issues/250) - correctly handle JSON data in quotations.
|
||||
|
||||
[2.1.3 / 2014-02-26](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.2...v2.1.3)
|
||||
==================
|
||||
|
||||
* Fixed issue [#248](https://github.com/jakubpawlowicz/clean-css/issues/248) - incorrect merging for vendor selectors.
|
||||
|
||||
[2.1.2 / 2014-02-25](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.1...v2.1.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#245](https://github.com/jakubpawlowicz/clean-css/issues/245) - incorrect handling of backslash IE hack.
|
||||
|
||||
[2.1.1 / 2014-02-18](https://github.com/jakubpawlowicz/clean-css/compare/v2.1.0...v2.1.1)
|
||||
==================
|
||||
|
||||
* Adds faster selectors processing in advanced optimizer.
|
||||
* Fixed issue [#241](https://github.com/jakubpawlowicz/clean-css/issues/241) - incorrect handling of `:not()` selectors.
|
||||
|
||||
[2.1.0 / 2014-02-13](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.8...v2.1.0)
|
||||
==================
|
||||
|
||||
* Adds an optional callback to minify method.
|
||||
* Deprecates `--selectors-merge-mode` / `selectorsMergeMode` in favor to `--compatibility` / `compatibility`.
|
||||
* Fixes debug mode stats for stylesheets using `@import` statements.
|
||||
* Skips empty removal if advanced processing is enabled.
|
||||
* Fixed issue [#85](https://github.com/jakubpawlowicz/clean-css/issues/85) - resolving protocol `@import`s.
|
||||
* Fixed issue [#160](https://github.com/jakubpawlowicz/clean-css/issues/160) - re-runs optimizer until a clean pass.
|
||||
* Fixed issue [#161](https://github.com/jakubpawlowicz/clean-css/issues/161) - improves tokenizer performance.
|
||||
* Fixed issue [#163](https://github.com/jakubpawlowicz/clean-css/issues/163) - round pixels to 2nd decimal place.
|
||||
* Fixed issue [#165](https://github.com/jakubpawlowicz/clean-css/issues/165) - extra space after trailing parenthesis.
|
||||
* Fixed issue [#186](https://github.com/jakubpawlowicz/clean-css/issues/186) - strip unit from `0rem`.
|
||||
* Fixed issue [#207](https://github.com/jakubpawlowicz/clean-css/issues/207) - bug in parsing protocol `@import`s.
|
||||
* Fixed issue [#213](https://github.com/jakubpawlowicz/clean-css/issues/213) - faster `rgb` to `hex` transforms.
|
||||
* Fixed issue [#215](https://github.com/jakubpawlowicz/clean-css/issues/215) - leading zeros in numerical values.
|
||||
* Fixed issue [#217](https://github.com/jakubpawlowicz/clean-css/issues/217) - whitespace inside attribute selectors and URLs.
|
||||
* Fixed issue [#218](https://github.com/jakubpawlowicz/clean-css/issues/218) - `@import` statements cleanup.
|
||||
* Fixed issue [#220](https://github.com/jakubpawlowicz/clean-css/issues/220) - selector between comments.
|
||||
* Fixed issue [#223](https://github.com/jakubpawlowicz/clean-css/issues/223) - two-pass adjacent selectors merging.
|
||||
* Fixed issue [#226](https://github.com/jakubpawlowicz/clean-css/issues/226) - don't minify `border:none` to `border:0`.
|
||||
* Fixed issue [#229](https://github.com/jakubpawlowicz/clean-css/issues/229) - improved processing of fraction numbers.
|
||||
* Fixed issue [#230](https://github.com/jakubpawlowicz/clean-css/issues/230) - better handling of zero values.
|
||||
* Fixed issue [#235](https://github.com/jakubpawlowicz/clean-css/issues/235) - IE7 compatibility mode.
|
||||
* Fixed issue [#236](https://github.com/jakubpawlowicz/clean-css/issues/236) - incorrect rebasing with nested `import`s.
|
||||
|
||||
[2.0.8 / 2014-02-07](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.7...v2.0.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#232](https://github.com/jakubpawlowicz/clean-css/issues/232) - edge case in non-adjacent selectors merging.
|
||||
|
||||
[2.0.7 / 2014-01-16](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.6...v2.0.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#208](https://github.com/jakubpawlowicz/clean-css/issues/208) - don't swallow `@page` and `@viewport`.
|
||||
|
||||
[2.0.6 / 2014-01-04](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.5...v2.0.6)
|
||||
==================
|
||||
|
||||
* Fixed issue [#198](https://github.com/jakubpawlowicz/clean-css/issues/198) - process comments and `@import`s correctly.
|
||||
* Fixed issue [#205](https://github.com/jakubpawlowicz/clean-css/issues/205) - freeze on broken `@import` declaration.
|
||||
|
||||
[2.0.5 / 2014-01-03](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.4...v2.0.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#199](https://github.com/jakubpawlowicz/clean-css/issues/199) - keep line breaks with no advanced optimizations.
|
||||
* Fixed issue [#203](https://github.com/jakubpawlowicz/clean-css/issues/203) - Buffer as a first argument to minify method.
|
||||
|
||||
[2.0.4 / 2013-12-19](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.3...v2.0.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#193](https://github.com/jakubpawlowicz/clean-css/issues/193) - HSL color space normalization.
|
||||
|
||||
[2.0.3 / 2013-12-18](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.2...v2.0.3)
|
||||
==================
|
||||
|
||||
* Fixed issue [#191](https://github.com/jakubpawlowicz/clean-css/issues/191) - leading numbers in `font`/`animation` names.
|
||||
* Fixed issue [#192](https://github.com/jakubpawlowicz/clean-css/issues/192) - many `@import`s inside a comment.
|
||||
|
||||
[2.0.2 / 2013-11-18](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.1...v2.0.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#177](https://github.com/jakubpawlowicz/clean-css/issues/177) - process broken content correctly.
|
||||
|
||||
[2.0.1 / 2013-11-14](https://github.com/jakubpawlowicz/clean-css/compare/v2.0.0...v2.0.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#176](https://github.com/jakubpawlowicz/clean-css/issues/176) - hangs on `undefined` keyword.
|
||||
|
||||
[2.0.0 / 2013-11-04](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.7...v2.0.0)
|
||||
==================
|
||||
|
||||
* Adds simplified and more advanced text escaping / restoring via `EscapeStore` class.
|
||||
* Adds simplified and much faster empty elements removal.
|
||||
* Adds missing `@import` processing to our benchmark (run via `npm run bench`).
|
||||
* Adds CSS tokenizer which will make it possible to optimize content by reordering and/or merging selectors.
|
||||
* Adds basic optimizer removing duplicate selectors from a list.
|
||||
* Adds merging duplicate properties within a single selector's body.
|
||||
* Adds merging adjacent selectors within a scope (single and multiple ones).
|
||||
* Changes behavior of `--keep-line-breaks`/`keepBreaks` option to keep breaks after trailing braces only.
|
||||
* Makes all multiple selectors ordered alphabetically (aids merging).
|
||||
* Adds property overriding so more coarse properties override more granular ones.
|
||||
* Adds reducing non-adjacent selectors.
|
||||
* Adds `--skip-advanced`/`noAdvanced` switch to disable advanced optimizations.
|
||||
* Adds reducing non-adjacent selectors when overridden by more complex selectors.
|
||||
* Fixed issue [#138](https://github.com/jakubpawlowicz/clean-css/issues/138) - makes CleanCSS interface OO.
|
||||
* Fixed issue [#139](https://github.com/jakubpawlowicz/clean-css/issues/138) - consistent error & warning handling.
|
||||
* Fixed issue [#145](https://github.com/jakubpawlowicz/clean-css/issues/145) - debug mode in library too.
|
||||
* Fixed issue [#157](https://github.com/jakubpawlowicz/clean-css/issues/157) - gets rid of `removeEmpty` option.
|
||||
* Fixed issue [#159](https://github.com/jakubpawlowicz/clean-css/issues/159) - escaped quotes inside content.
|
||||
* Fixed issue [#162](https://github.com/jakubpawlowicz/clean-css/issues/162) - strip quotes from Base64 encoded URLs.
|
||||
* Fixed issue [#166](https://github.com/jakubpawlowicz/clean-css/issues/166) - `debug` formatting in CLI
|
||||
* Fixed issue [#167](https://github.com/jakubpawlowicz/clean-css/issues/167) - `background:transparent` minification.
|
||||
|
||||
[1.1.7 / 2013-10-28](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.6...v1.1.7)
|
||||
==================
|
||||
|
||||
* Fixed issue [#156](https://github.com/jakubpawlowicz/clean-css/issues/156) - `@import`s inside comments.
|
||||
|
||||
[1.1.6 / 2013-10-26](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.5...v1.1.6)
|
||||
==================
|
||||
|
||||
* Fixed issue [#155](https://github.com/jakubpawlowicz/clean-css/issues/155) - broken irregular CSS content.
|
||||
|
||||
[1.1.5 / 2013-10-24](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.4...v1.1.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#153](https://github.com/jakubpawlowicz/clean-css/issues/153) - `keepSpecialComments` `0`/`1` as a string.
|
||||
|
||||
[1.1.4 / 2013-10-23](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.3...v1.1.4)
|
||||
==================
|
||||
|
||||
* Fixed issue [#152](https://github.com/jakubpawlowicz/clean-css/issues/152) - adds an option to disable rebasing.
|
||||
|
||||
[1.1.3 / 2013-10-04](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.2...v1.1.3)
|
||||
==================
|
||||
|
||||
* Fixed issue [#150](https://github.com/jakubpawlowicz/clean-css/issues/150) - minifying `background:none`.
|
||||
|
||||
[1.1.2 / 2013-09-29](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.1...v1.1.2)
|
||||
==================
|
||||
|
||||
* Fixed issue [#149](https://github.com/jakubpawlowicz/clean-css/issues/149) - shorthand `font` property.
|
||||
|
||||
[1.1.1 / 2013-09-07](https://github.com/jakubpawlowicz/clean-css/compare/v1.1.0...v1.1.1)
|
||||
==================
|
||||
|
||||
* Fixed issue [#144](https://github.com/jakubpawlowicz/clean-css/issues/144) - skip URLs rebasing by default.
|
||||
|
||||
[1.1.0 / 2013-09-06](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.12...v1.1.0)
|
||||
==================
|
||||
|
||||
* Renamed lib's `debug` option to `benchmark` when doing per-minification benchmarking.
|
||||
* Added simplified comments processing & imports.
|
||||
* Fixed issue [#43](https://github.com/jakubpawlowicz/clean-css/issues/43) - `--debug` switch for minification stats.
|
||||
* Fixed issue [#65](https://github.com/jakubpawlowicz/clean-css/issues/65) - full color name / hex shortening.
|
||||
* Fixed issue [#84](https://github.com/jakubpawlowicz/clean-css/issues/84) - support for `@import` with media queries.
|
||||
* Fixed issue [#124](https://github.com/jakubpawlowicz/clean-css/issues/124) - raise error on broken imports.
|
||||
* Fixed issue [#126](https://github.com/jakubpawlowicz/clean-css/issues/126) - proper CSS expressions handling.
|
||||
* Fixed issue [#129](https://github.com/jakubpawlowicz/clean-css/issues/129) - rebasing imported URLs.
|
||||
* Fixed issue [#130](https://github.com/jakubpawlowicz/clean-css/issues/130) - better code modularity.
|
||||
* Fixed issue [#135](https://github.com/jakubpawlowicz/clean-css/issues/135) - require node.js 0.8+.
|
||||
|
||||
[1.0.12 / 2013-07-19](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.11...v1.0.12)
|
||||
===================
|
||||
|
||||
* Fixed issue [#121](https://github.com/jakubpawlowicz/clean-css/issues/121) - ability to skip `@import` processing.
|
||||
|
||||
[1.0.11 / 2013-07-08](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.10...v1.0.11)
|
||||
===================
|
||||
|
||||
* Fixed issue [#117](https://github.com/jakubpawlowicz/clean-css/issues/117) - line break escaping in comments.
|
||||
|
||||
[1.0.10 / 2013-06-13](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.9...v1.0.10)
|
||||
===================
|
||||
|
||||
* Fixed issue [#114](https://github.com/jakubpawlowicz/clean-css/issues/114) - comments in imported stylesheets.
|
||||
|
||||
[1.0.9 / 2013-06-11](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.8...v1.0.9)
|
||||
==================
|
||||
|
||||
* Fixed issue [#113](https://github.com/jakubpawlowicz/clean-css/issues/113) - `@import` in comments.
|
||||
|
||||
[1.0.8 / 2013-06-10](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.7...v1.0.8)
|
||||
==================
|
||||
|
||||
* Fixed issue [#112](https://github.com/jakubpawlowicz/clean-css/issues/112) - reducing `box-shadow` zeros.
|
||||
|
||||
[1.0.7 / 2013-06-05](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.6...v1.0.7)
|
||||
==================
|
||||
|
||||
* Support for `@import` URLs starting with `//`. By [@petetak](https://github.com/petetak).
|
||||
|
||||
[1.0.6 / 2013-06-04](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.5...v1.0.6)
|
||||
==================
|
||||
|
||||
* Fixed issue [#110](https://github.com/jakubpawlowicz/clean-css/issues/110) - data URIs in URLs.
|
||||
|
||||
[1.0.5 / 2013-05-26](https://github.com/jakubpawlowicz/clean-css/compare/v1.0.4...v1.0.5)
|
||||
==================
|
||||
|
||||
* Fixed issue [#107](https://github.com/jakubpawlowicz/clean-css/issues/107) - data URIs in imported stylesheets.
|
||||
|
||||
1.0.4 / 2013-05-23
|
||||
==================
|
||||
|
||||
* Rewrite relative URLs in imported stylesheets. By [@bluej100](https://github.com/bluej100).
|
||||
|
||||
1.0.3 / 2013-05-20
|
||||
==================
|
||||
|
||||
* Support alternative `@import` syntax with file name not wrapped inside `url()` statement.
|
||||
By [@bluej100](https://github.com/bluej100).
|
||||
|
||||
1.0.2 / 2013-04-29
|
||||
==================
|
||||
|
||||
* Fixed issue [#97](https://github.com/jakubpawlowicz/clean-css/issues/97) - `--remove-empty` & FontAwesome.
|
||||
|
||||
1.0.1 / 2013-04-08
|
||||
==================
|
||||
|
||||
* Do not pick up `bench` and `test` while building `npm` package.
|
||||
By [@sindresorhus](https://https://github.com/sindresorhus).
|
||||
|
||||
1.0.0 / 2013-03-30
|
||||
==================
|
||||
|
||||
* Fixed issue [#2](https://github.com/jakubpawlowicz/clean-css/issues/2) - resolving `@import` rules.
|
||||
* Fixed issue [#44](https://github.com/jakubpawlowicz/clean-css/issues/44) - examples in `--help`.
|
||||
* Fixed issue [#46](https://github.com/jakubpawlowicz/clean-css/issues/46) - preserving special characters in URLs and attributes.
|
||||
* Fixed issue [#80](https://github.com/jakubpawlowicz/clean-css/issues/80) - quotation in multi line strings.
|
||||
* Fixed issue [#83](https://github.com/jakubpawlowicz/clean-css/issues/83) - HSL to hex color conversions.
|
||||
* Fixed issue [#86](https://github.com/jakubpawlowicz/clean-css/issues/86) - broken `@charset` replacing.
|
||||
* Fixed issue [#88](https://github.com/jakubpawlowicz/clean-css/issues/88) - removes space in `! important`.
|
||||
* Fixed issue [#92](https://github.com/jakubpawlowicz/clean-css/issues/92) - uppercase hex to short versions.
|
||||
|
||||
0.10.2 / 2013-03-19
|
||||
===================
|
||||
|
||||
* Fixed issue [#79](https://github.com/jakubpawlowicz/clean-css/issues/79) - node.js 0.10.x compatibility.
|
||||
|
||||
0.10.1 / 2013-02-14
|
||||
===================
|
||||
|
||||
* Fixed issue [#66](https://github.com/jakubpawlowicz/clean-css/issues/66) - line breaks without extra spaces should
|
||||
be handled correctly.
|
||||
|
||||
0.10.0 / 2013-02-09
|
||||
===================
|
||||
|
||||
* Switched from [optimist](https://github.com/substack/node-optimist) to
|
||||
[commander](https://github.com/visionmedia/commander.js) for CLI processing.
|
||||
* Changed long options from `--removeempty` to `--remove-empty` and from `--keeplinebreaks` to `--keep-line-breaks`.
|
||||
* Fixed performance issue with replacing multiple `@charset` declarations and issue
|
||||
with line break after `@charset` when using `keepLineBreaks` option. By [@rrjaime](https://github.com/rrjamie).
|
||||
* Removed Makefile in favor to `npm run` commands (e.g. `make check` -> `npm run check`).
|
||||
* Fixed issue [#47](https://github.com/jakubpawlowicz/clean-css/issues/47) - commandline issues on Windows.
|
||||
* Fixed issue [#49](https://github.com/jakubpawlowicz/clean-css/issues/49) - remove empty selectors from media query.
|
||||
* Fixed issue [#52](https://github.com/jakubpawlowicz/clean-css/issues/52) - strip fraction zeros if not needed.
|
||||
* Fixed issue [#58](https://github.com/jakubpawlowicz/clean-css/issues/58) - remove colon where possible.
|
||||
* Fixed issue [#59](https://github.com/jakubpawlowicz/clean-css/issues/59) - content property handling.
|
||||
|
||||
0.9.1 / 2012-12-19
|
||||
==================
|
||||
|
||||
* Fixed issue [#37](https://github.com/jakubpawlowicz/clean-css/issues/37) - converting
|
||||
`white` and other colors in class names (reported by [@malgorithms](https://github.com/malgorithms)).
|
||||
|
||||
0.9.0 / 2012-12-15
|
||||
==================
|
||||
|
||||
* Added stripping quotation from font names (if possible).
|
||||
* Added stripping quotation from `@keyframes` declaration, `animation` and
|
||||
`animation-name` property.
|
||||
* Added stripping quotations from attributes' value (e.g. `[data-target='x']`).
|
||||
* Added better hex->name and name->hex color shortening.
|
||||
* Added `font: normal` and `font: bold` shortening the same way as `font-weight` is.
|
||||
* Refactored shorthand selectors and added `border-radius`, `border-style`
|
||||
and `border-color` shortening.
|
||||
* Added `margin`, `padding` and `border-width` shortening.
|
||||
* Added removing line break after commas.
|
||||
* Fixed removing whitespace inside media query definition.
|
||||
* Added removing line breaks after a comma, so all declarations are one-liners now.
|
||||
* Speed optimizations (~10% despite many new features).
|
||||
* Added [JSHint](https://github.com/jshint/jshint/) validation rules via `make check`.
|
||||
|
||||
0.8.3 / 2012-11-29
|
||||
==================
|
||||
|
||||
* Fixed HSL/HSLA colors processing.
|
||||
|
||||
0.8.2 / 2012-10-31
|
||||
==================
|
||||
|
||||
* Fixed shortening hex colors and their relation to hashes in URLs.
|
||||
* Cleanup by [@XhmikosR](https://github.com/XhmikosR).
|
||||
|
||||
0.8.1 / 2012-10-28
|
||||
==================
|
||||
|
||||
* Added better zeros processing for `rect(...)` syntax (clip property).
|
||||
|
||||
0.8.0 / 2012-10-21
|
||||
==================
|
||||
|
||||
* Added removing URLs quotation if possible.
|
||||
* Rewrote breaks processing.
|
||||
* Added `keepBreaks`/`-b` option to keep line breaks in the minimized file.
|
||||
* Reformatted [lib/clean.js](/lib/clean.js) so it's easier to follow the rules.
|
||||
* Minimized test data is now minimized with line breaks so it's easier to
|
||||
compare the changes line by line.
|
||||
|
||||
0.7.0 / 2012-10-14
|
||||
==================
|
||||
|
||||
* Added stripping special comments to CLI (`--s0` and `--s1` options).
|
||||
* Added stripping special comments to programmatic interface
|
||||
(`keepSpecialComments` option).
|
||||
|
||||
0.6.0 / 2012-08-05
|
||||
==================
|
||||
|
||||
* Full Windows support with tests (./test.bat).
|
||||
|
||||
0.5.0 / 2012-08-02
|
||||
==================
|
||||
|
||||
* Made path to vows local.
|
||||
* Explicit node.js 0.6 requirement.
|
||||
|
||||
0.4.2 / 2012-06-28
|
||||
==================
|
||||
|
||||
* Updated binary `-v` option (version).
|
||||
* Updated binary to output help when no options given (but not in piped mode).
|
||||
* Added binary tests.
|
||||
|
||||
0.4.1 / 2012-06-10
|
||||
==================
|
||||
|
||||
* Fixed stateless mode where calling `CleanCSS#process` directly was giving
|
||||
errors (reported by [@facelessuser](https://github.com/facelessuser)).
|
||||
|
||||
0.4.0 / 2012-06-04
|
||||
==================
|
||||
|
||||
* Speed improvements up to 4x thanks to the rewrite of comments and CSS' content
|
||||
processing.
|
||||
* Stripping empty CSS tags is now optional (see [bin/cleancss](/bin/cleancss) for details).
|
||||
* Improved debugging mode (see [test/bench.js](/test/bench.js))
|
||||
* Added `make bench` for a one-pass benchmark.
|
||||
|
||||
0.3.3 / 2012-05-27
|
||||
==================
|
||||
|
||||
* Fixed tests, [package.json](/package.json) for development, and regex
|
||||
for removing empty declarations (thanks to [@vvo](https://github.com/vvo)).
|
||||
|
||||
0.3.2 / 2012-01-17
|
||||
==================
|
||||
|
||||
* Fixed output method under node.js 0.6 which incorrectly tried to close
|
||||
`process.stdout`.
|
||||
|
||||
0.3.1 / 2011-12-16
|
||||
==================
|
||||
|
||||
* Fixed cleaning up `0 0 0 0` expressions.
|
||||
|
||||
0.3.0 / 2011-11-29
|
||||
==================
|
||||
|
||||
* Clean-css requires node.js 0.4.0+ to run.
|
||||
* Removed node.js's 0.2.x 'sys' package dependency
|
||||
(thanks to [@jmalonzo](https://github.com/jmalonzo) for a patch).
|
||||
|
||||
0.2.6 / 2011-11-27
|
||||
==================
|
||||
|
||||
* Fixed expanding `+` signs in `calc()` when mixed up with adjacent `+` selector.
|
||||
|
||||
0.2.5 / 2011-11-27
|
||||
==================
|
||||
|
||||
* Fixed issue with cleaning up spaces inside `calc`/`-moz-calc` declarations
|
||||
(thanks to [@cvan](https://github.com/cvan) for reporting it).
|
||||
* Fixed converting `#f00` to `red` in borders and gradients.
|
||||
|
||||
0.2.4 / 2011-05-25
|
||||
==================
|
||||
|
||||
* Fixed problem with expanding `none` to `0` in partial/full background
|
||||
declarations.
|
||||
* Fixed including clean-css library from binary (global to local).
|
||||
|
||||
0.2.3 / 2011-04-18
|
||||
==================
|
||||
|
||||
* Fixed problem with optimizing IE filters.
|
||||
|
||||
0.2.2 / 2011-04-17
|
||||
==================
|
||||
|
||||
* Fixed problem with space before color in `border` property.
|
||||
|
||||
0.2.1 / 2011-03-19
|
||||
==================
|
||||
|
||||
* Added stripping space before `!important` keyword.
|
||||
* Updated repository location and author information in [package.json](/package.json).
|
||||
|
||||
0.2.0 / 2011-03-02
|
||||
==================
|
||||
|
||||
* Added options parsing via optimist.
|
||||
* Changed code inclusion (thus the version bump).
|
||||
|
||||
0.1.0 / 2011-02-27
|
||||
==================
|
||||
|
||||
* First version of clean-css library.
|
||||
* Implemented all basic CSS transformations.
|
||||
19
node_modules/jade/node_modules/clean-css/LICENSE
generated
vendored
Normal file
19
node_modules/jade/node_modules/clean-css/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2015 JakubPawlowicz.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
369
node_modules/jade/node_modules/clean-css/README.md
generated
vendored
Normal file
369
node_modules/jade/node_modules/clean-css/README.md
generated
vendored
Normal file
@@ -0,0 +1,369 @@
|
||||
[](https://www.npmjs.com/package/clean-css)
|
||||
[](https://travis-ci.org/jakubpawlowicz/clean-css)
|
||||
[](https://ci.appveyor.com/project/jakubpawlowicz/clean-css/branch/master)
|
||||
[](https://david-dm.org/jakubpawlowicz/clean-css)
|
||||
[](https://david-dm.org/jakubpawlowicz/clean-css#info=devDependencies)
|
||||
|
||||
## What is clean-css?
|
||||
|
||||
Clean-css is a fast and efficient [Node.js](http://nodejs.org/) library for minifying CSS files.
|
||||
|
||||
According to [tests](http://goalsmashers.github.io/css-minification-benchmark/) it is one of the best available.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### What are the requirements?
|
||||
|
||||
```
|
||||
Node.js 0.10+ (tested on CentOS, Ubuntu, OS X 10.6+, and Windows 7+) or io.js 3.0+
|
||||
```
|
||||
|
||||
### How to install clean-css?
|
||||
|
||||
```
|
||||
npm install clean-css
|
||||
```
|
||||
|
||||
### How to use clean-css CLI?
|
||||
|
||||
Clean-css accepts the following command line arguments (please make sure
|
||||
you use `<source-file>` as the very last argument to avoid potential issues):
|
||||
|
||||
```
|
||||
cleancss [options] source-file, [source-file, ...]
|
||||
|
||||
-h, --help output usage information
|
||||
-v, --version output the version number
|
||||
-b, --keep-line-breaks Keep line breaks
|
||||
-c, --compatibility [ie7|ie8] Force compatibility mode (see Readme for advanced examples)
|
||||
-d, --debug Shows debug information (minification time & compression efficiency)
|
||||
-o, --output [output-file] Use [output-file] as output instead of STDOUT
|
||||
-r, --root [root-path] Set a root path to which resolve absolute @import rules
|
||||
-s, --skip-import Disable @import processing
|
||||
-t, --timeout [seconds] Per connection timeout when fetching remote @imports (defaults to 5 seconds)
|
||||
--rounding-precision [n] Rounds to `N` decimal places. Defaults to 2. -1 disables rounding
|
||||
--s0 Remove all special comments, i.e. /*! comment */
|
||||
--s1 Remove all special comments but the first one
|
||||
--semantic-merging Enables unsafe mode by assuming BEM-like semantic stylesheets (warning, this may break your styling!)
|
||||
--skip-advanced Disable advanced optimizations - ruleset reordering & merging
|
||||
--skip-aggressive-merging Disable properties merging based on their order
|
||||
--skip-import-from [rules] Disable @import processing for specified rules
|
||||
--skip-media-merging Disable @media merging
|
||||
--skip-rebase Disable URLs rebasing
|
||||
--skip-restructuring Disable restructuring optimizations
|
||||
--skip-shorthand-compacting Disable shorthand compacting
|
||||
--source-map Enables building input's source map
|
||||
--source-map-inline-sources Enables inlining sources inside source maps
|
||||
```
|
||||
|
||||
#### Examples:
|
||||
|
||||
To minify a **public.css** file into **public-min.css** do:
|
||||
|
||||
```
|
||||
cleancss -o public-min.css public.css
|
||||
```
|
||||
|
||||
To minify the same **public.css** into the standard output skip the `-o` parameter:
|
||||
|
||||
```
|
||||
cleancss public.css
|
||||
```
|
||||
|
||||
More likely you would like to concatenate a couple of files.
|
||||
If you are on a Unix-like system:
|
||||
|
||||
```bash
|
||||
cat one.css two.css three.css | cleancss -o merged-and-minified.css
|
||||
```
|
||||
|
||||
On Windows:
|
||||
|
||||
```bat
|
||||
type one.css two.css three.css | cleancss -o merged-and-minified.css
|
||||
```
|
||||
|
||||
Or even gzip the result at once:
|
||||
|
||||
```bash
|
||||
cat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz
|
||||
```
|
||||
|
||||
### How to use clean-css API?
|
||||
|
||||
```js
|
||||
var CleanCSS = require('clean-css');
|
||||
var source = 'a{font-weight:bold;}';
|
||||
var minified = new CleanCSS().minify(source).styles;
|
||||
```
|
||||
|
||||
CleanCSS constructor accepts a hash as a parameter, i.e.,
|
||||
`new CleanCSS(options)` with the following options available:
|
||||
|
||||
* `advanced` - set to false to disable advanced optimizations - selector & property merging, reduction, etc.
|
||||
* `aggressiveMerging` - set to false to disable aggressive merging of properties.
|
||||
* `benchmark` - turns on benchmarking mode measuring time spent on cleaning up (run `npm run bench` to see example)
|
||||
* `compatibility` - enables compatibility mode, see [below for more examples](#how-to-set-compatibility-mode)
|
||||
* `debug` - set to true to get minification statistics under `stats` property (see `test/custom-test.js` for examples)
|
||||
* `inliner` - a hash of options for `@import` inliner, see [test/protocol-imports-test.js](https://github.com/jakubpawlowicz/clean-css/blob/master/test/protocol-imports-test.js#L372) for examples, or [this comment](https://github.com/jakubpawlowicz/clean-css/issues/612#issuecomment-119594185) for a proxy use case.
|
||||
* `keepBreaks` - whether to keep line breaks (default is false)
|
||||
* `keepSpecialComments` - `*` for keeping all (default), `1` for keeping first one only, `0` for removing all
|
||||
* `mediaMerging` - whether to merge `@media` at-rules (default is true)
|
||||
* `processImport` - whether to process `@import` rules
|
||||
* `processImportFrom` - a list of `@import` rules, can be `['all']` (default), `['local']`, `['remote']`, or a blacklisted path e.g. `['!fonts.googleapis.com']`
|
||||
* `rebase` - set to false to skip URL rebasing
|
||||
* `relativeTo` - path to **resolve** relative `@import` rules and URLs
|
||||
* `restructuring` - set to false to disable restructuring in advanced optimizations
|
||||
* `root` - path to **resolve** absolute `@import` rules and **rebase** relative URLs
|
||||
* `roundingPrecision` - rounding precision; defaults to `2`; `-1` disables rounding
|
||||
* `semanticMerging` - set to true to enable semantic merging mode which assumes BEM-like content (default is false as it's highly likely this will break your stylesheets - **use with caution**!)
|
||||
* `shorthandCompacting` - set to false to skip shorthand compacting (default is true unless sourceMap is set when it's false)
|
||||
* `sourceMap` - exposes source map under `sourceMap` property, e.g. `new CleanCSS().minify(source).sourceMap` (default is false)
|
||||
If input styles are a product of CSS preprocessor (Less, Sass) an input source map can be passed as a string.
|
||||
* `sourceMapInlineSources` - set to true to inline sources inside a source map's `sourcesContent` field (defaults to false)
|
||||
It is also required to process inlined sources from input source maps.
|
||||
* `target` - path to a folder or an output file to which **rebase** all URLs
|
||||
|
||||
The output of `minify` method (or the 2nd argument to passed callback) is a hash containing the following fields:
|
||||
|
||||
* `styles` - optimized output CSS as a string
|
||||
* `sourceMap` - output source map (if requested with `sourceMap` option)
|
||||
* `errors` - a list of errors raised
|
||||
* `warnings` - a list of warnings raised
|
||||
* `stats` - a hash of statistic information (if requested with `debug` option):
|
||||
* `originalSize` - original content size (after import inlining)
|
||||
* `minifiedSize` - optimized content size
|
||||
* `timeSpent` - time spent on optimizations
|
||||
* `efficiency` - a ratio of output size to input size (e.g. 25% if content was reduced from 100 bytes to 75 bytes)
|
||||
|
||||
#### How to make sure remote `@import`s are processed correctly?
|
||||
|
||||
In order to inline remote `@import` statements you need to provide a callback to minify method, e.g.:
|
||||
|
||||
```js
|
||||
var CleanCSS = require('clean-css');
|
||||
var source = '@import url(http://path/to/remote/styles);';
|
||||
new CleanCSS().minify(source, function (errors, minified) {
|
||||
// minified.styles
|
||||
});
|
||||
```
|
||||
|
||||
This is due to a fact, that, while local files can be read synchronously, remote resources can only be processed asynchronously.
|
||||
If you don't provide a callback, then remote `@import`s will be left intact.
|
||||
|
||||
### How to use clean-css with build tools?
|
||||
|
||||
* [Broccoli](https://github.com/broccolijs/broccoli#broccoli): [broccoli-clean-css](https://github.com/shinnn/broccoli-clean-css)
|
||||
* [Brunch](http://brunch.io/): [clean-css-brunch](https://github.com/brunch/clean-css-brunch)
|
||||
* [Grunt](http://gruntjs.com): [grunt-contrib-cssmin](https://github.com/gruntjs/grunt-contrib-cssmin)
|
||||
* [Gulp](http://gulpjs.com/): [gulp-minify-css](https://github.com/jonathanepollack/gulp-minify-css)
|
||||
* [Gulp](http://gulpjs.com/): [using vinyl-map as a wrapper - courtesy of @sogko](https://github.com/jakubpawlowicz/clean-css/issues/342)
|
||||
* [component-builder2](https://github.com/component/builder2.js): [builder-clean-css](https://github.com/poying/builder-clean-css)
|
||||
* [Metalsmith](http://metalsmith.io): [metalsmith-clean-css](https://github.com/aymericbeaumet/metalsmith-clean-css)
|
||||
* [Lasso](https://github.com/lasso-js/lasso): [lasso-clean-css](https://github.com/yomed/lasso-clean-css)
|
||||
|
||||
### What are the clean-css' dev commands?
|
||||
|
||||
First clone the source, then run:
|
||||
|
||||
* `npm run bench` for clean-css benchmarks (see [test/bench.js](https://github.com/jakubpawlowicz/clean-css/blob/master/test/bench.js) for details)
|
||||
* `npm run browserify` to create the browser-ready clean-css version
|
||||
* `npm run check` to check JS sources with [JSHint](https://github.com/jshint/jshint/)
|
||||
* `npm test` for the test suite
|
||||
|
||||
## How to contribute to clean-css?
|
||||
|
||||
See [CONTRIBUTING.md](https://github.com/jakubpawlowicz/clean-css/blob/master/CONTRIBUTING.md).
|
||||
|
||||
## Tips & Tricks
|
||||
|
||||
### How to preserve a comment block?
|
||||
|
||||
Use the `/*!` notation instead of the standard one `/*`:
|
||||
|
||||
```css
|
||||
/*!
|
||||
Important comments included in minified output.
|
||||
*/
|
||||
```
|
||||
|
||||
### How to rebase relative image URLs?
|
||||
|
||||
Clean-css will handle it automatically for you (since version 1.1) in the following cases:
|
||||
|
||||
* When using the CLI:
|
||||
1. Use an output path via `-o`/`--output` to rebase URLs as relative to the output file.
|
||||
2. Use a root path via `-r`/`--root` to rebase URLs as absolute from the given root path.
|
||||
3. If you specify both then `-r`/`--root` takes precendence.
|
||||
* When using clean-css as a library:
|
||||
1. Use a combination of `relativeTo` and `target` options for relative rebase (same as 1 in CLI).
|
||||
2. Use a combination of `relativeTo` and `root` options for absolute rebase (same as 2 in CLI).
|
||||
3. `root` takes precendence over `target` as in CLI.
|
||||
|
||||
### How to generate source maps?
|
||||
|
||||
Source maps are supported since version 3.0.
|
||||
|
||||
Additionally to mapping original CSS files, clean-css also supports input source maps, so minified styles can be mapped into their [Less](http://lesscss.org/) or [Sass](http://sass-lang.com/) sources directly.
|
||||
|
||||
Source maps are generated using [source-map](https://github.com/mozilla/source-map/) module from Mozilla.
|
||||
|
||||
#### Using CLI
|
||||
|
||||
To generate a source map, use `--source-map` switch, e.g.:
|
||||
|
||||
```
|
||||
cleancss --source-map --output styles.min.css styles.css
|
||||
```
|
||||
|
||||
Name of the output file is required, so a map file, named by adding `.map` suffix to output file name, can be created (styles.min.css.map in this case).
|
||||
|
||||
#### Using API
|
||||
|
||||
To generate a source map, use `sourceMap: true` option, e.g.:
|
||||
|
||||
```js
|
||||
new CleanCSS({ sourceMap: true, target: pathToOutputDirectory })
|
||||
.minify(source, function (minified) {
|
||||
// access minified.sourceMap for SourceMapGenerator object
|
||||
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
|
||||
// see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
|
||||
});
|
||||
```
|
||||
|
||||
Using API you can also pass an input source map directly:
|
||||
|
||||
```js
|
||||
new CleanCSS({ sourceMap: inputSourceMapAsString, target: pathToOutputDirectory })
|
||||
.minify(source, function (minified) {
|
||||
// access minified.sourceMap to access SourceMapGenerator object
|
||||
// see https://github.com/mozilla/source-map/#sourcemapgenerator for more details
|
||||
// see https://github.com/jakubpawlowicz/clean-css/blob/master/bin/cleancss#L114 on how it's used in clean-css' CLI
|
||||
});
|
||||
```
|
||||
|
||||
Or even multiple input source maps at once (available since version 3.1):
|
||||
|
||||
```js
|
||||
new CleanCSS({ sourceMap: true, target: pathToOutputDirectory }).minify({
|
||||
'path/to/source/1': {
|
||||
styles: '...styles...',
|
||||
sourceMap: '...source-map...'
|
||||
},
|
||||
'path/to/source/2': {
|
||||
styles: '...styles...',
|
||||
sourceMap: '...source-map...'
|
||||
}
|
||||
}, function (minified) {
|
||||
// access minified.sourceMap as above
|
||||
});
|
||||
```
|
||||
|
||||
### How to minify multiple files with API?
|
||||
|
||||
#### Passing an array
|
||||
|
||||
```js
|
||||
new CleanCSS().minify(['path/to/file/one', 'path/to/file/two']);
|
||||
```
|
||||
|
||||
#### Passing a hash
|
||||
|
||||
```js
|
||||
new CleanCSS().minify({
|
||||
'path/to/file/one': {
|
||||
styles: 'contents of file one'
|
||||
},
|
||||
'path/to/file/two': {
|
||||
styles: 'contents of file two'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### How to set a compatibility mode?
|
||||
|
||||
Compatibility settings are controlled by `--compatibility` switch (CLI) and `compatibility` option (library mode).
|
||||
|
||||
In both modes the following values are allowed:
|
||||
|
||||
* `'ie7'` - Internet Explorer 7 compatibility mode
|
||||
* `'ie8'` - Internet Explorer 8 compatibility mode
|
||||
* `''` or `'*'` (default) - Internet Explorer 9+ compatibility mode
|
||||
|
||||
Since clean-css 3 a fine grained control is available over
|
||||
[those settings](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/utils/compatibility.js),
|
||||
with the following options available:
|
||||
|
||||
* `'[+-]colors.opacity'` - - turn on (+) / off (-) `rgba()` / `hsla()` declarations removal
|
||||
* `'[+-]properties.backgroundClipMerging'` - turn on / off background-clip merging into shorthand
|
||||
* `'[+-]properties.backgroundOriginMerging'` - turn on / off background-origin merging into shorthand
|
||||
* `'[+-]properties.backgroundSizeMerging'` - turn on / off background-size merging into shorthand
|
||||
* `'[+-]properties.colors'` - turn on / off any color optimizations
|
||||
* `'[+-]properties.ieBangHack'` - turn on / off IE bang hack removal
|
||||
* `'[+-]properties.iePrefixHack'` - turn on / off IE prefix hack removal
|
||||
* `'[+-]properties.ieSuffixHack'` - turn on / off IE suffix hack removal
|
||||
* `'[+-]properties.merging'` - turn on / off property merging based on understandability
|
||||
* `'[+-]properties.spaceAfterClosingBrace'` - turn on / off removing space after closing brace - `url() no-repeat` into `url()no-repeat`
|
||||
* `'[+-]properties.urlQuotes'` - turn on / off `url()` quoting
|
||||
* `'[+-]properties.zeroUnits'` - turn on / off units removal after a `0` value
|
||||
* `'[+-]selectors.adjacentSpace'` - turn on / off extra space before `nav` element
|
||||
* `'[+-]selectors.ie7Hack'` - turn on / off IE7 selector hack removal (`*+html...`)
|
||||
* `'[+-]selectors.special'` - a regular expression with all special, unmergeable selectors (leave it empty unless you know what you are doing)
|
||||
* `'[+-]units.ch'` - turn on / off treating `ch` as a proper unit
|
||||
* `'[+-]units.in'` - turn on / off treating `in` as a proper unit
|
||||
* `'[+-]units.pc'` - turn on / off treating `pc` as a proper unit
|
||||
* `'[+-]units.pt'` - turn on / off treating `pt` as a proper unit
|
||||
* `'[+-]units.rem'` - turn on / off treating `rem` as a proper unit
|
||||
* `'[+-]units.vh'` - turn on / off treating `vh` as a proper unit
|
||||
* `'[+-]units.vm'` - turn on / off treating `vm` as a proper unit
|
||||
* `'[+-]units.vmax'` - turn on / off treating `vmax` as a proper unit
|
||||
* `'[+-]units.vmin'` - turn on / off treating `vmin` as a proper unit
|
||||
* `'[+-]units.vm'` - turn on / off treating `vm` as a proper unit
|
||||
|
||||
For example, using `--compatibility 'ie8,+units.rem'` will ensure IE8 compatibility while enabling `rem` units so the following style `margin:0px 0rem` can be shortened to `margin:0`, while in pure IE8 mode it can't be.
|
||||
|
||||
To pass a single off (-) switch in CLI please use the following syntax `--compatibility *,-units.rem`.
|
||||
|
||||
In library mode you can also pass `compatibility` as a hash of options.
|
||||
|
||||
### What advanced optimizations are applied?
|
||||
|
||||
All advanced optimizations are dispatched [here](https://github.com/jakubpawlowicz/clean-css/blob/master/lib/selectors/advanced.js#L59), and this is what they do:
|
||||
|
||||
* `recursivelyOptimizeBlocks` - does all the following operations on a block (think `@media` or `@keyframe` at-rules);
|
||||
* `recursivelyOptimizeProperties` - optimizes properties in rulesets and "flat at-rules" (like @font-face) by splitting them into components (e.g. `margin` into `margin-(*)`), optimizing, and rebuilding them back. You may want to use `shorthandCompacting` option to control whether you want to turn multiple (long-hand) properties into a shorthand ones;
|
||||
* `removeDuplicates` - gets rid of duplicate rulesets with exactly the same set of properties (think of including the same Sass / Less partial twice for no good reason);
|
||||
* `mergeAdjacent` - merges adjacent rulesets with the same selector or rules;
|
||||
* `reduceNonAdjacent` - identifies which properties are overridden in same-selector non-adjacent rulesets, and removes them;
|
||||
* `mergeNonAdjacentBySelector` - identifies same-selector non-adjacent rulesets which can be moved (!) to be merged, requires all intermediate rulesets to not redefine the moved properties, or if redefined to be either more coarse grained (e.g. `margin` vs `margin-top`) or have the same value;
|
||||
* `mergeNonAdjacentByBody` - same as the one above but for same-rules non-adjacent rulesets;
|
||||
* `restructure` - tries to reorganize different-selector different-rules rulesets so they take less space, e.g. `.one{padding:0}.two{margin:0}.one{margin-bottom:3px}` into `.two{margin:0}.one{padding:0;margin-bottom:3px}`;
|
||||
* `removeDuplicateMediaQueries` - removes duplicated `@media` at-rules;
|
||||
* `mergeMediaQueries` - merges non-adjacent `@media` at-rules by same rules as `mergeNonAdjacentBy*` above;
|
||||
|
||||
## Acknowledgments (sorted alphabetically)
|
||||
|
||||
* Anthony Barre ([@abarre](https://github.com/abarre)) for improvements to
|
||||
`@import` processing, namely introducing the `--skip-import` /
|
||||
`processImport` options.
|
||||
* Simon Altschuler ([@altschuler](https://github.com/altschuler)) for fixing
|
||||
`@import` processing inside comments.
|
||||
* Isaac ([@facelessuser](https://github.com/facelessuser)) for pointing out
|
||||
a flaw in clean-css' stateless mode.
|
||||
* Jan Michael Alonzo ([@jmalonzo](https://github.com/jmalonzo)) for a patch
|
||||
removing node.js' old `sys` package.
|
||||
* Luke Page ([@lukeapage](https://github.com/lukeapage)) for suggestions and testing the source maps feature.
|
||||
Plus everyone else involved in [#125](https://github.com/jakubpawlowicz/clean-css/issues/125) for pushing it forward.
|
||||
* Timur Kristóf ([@Venemo](https://github.com/Venemo)) for an outstanding
|
||||
contribution of advanced property optimizer for 2.2 release.
|
||||
* Vincent Voyer ([@vvo](https://github.com/vvo)) for a patch with better
|
||||
empty element regex and for inspiring us to do many performance improvements
|
||||
in 0.4 release.
|
||||
* [@XhmikosR](https://github.com/XhmikosR) for suggesting new features
|
||||
(option to remove special comments and strip out URLs quotation) and
|
||||
pointing out numerous improvements (JSHint, media queries).
|
||||
|
||||
## License
|
||||
|
||||
Clean-css is released under the [MIT License](https://github.com/jakubpawlowicz/clean-css/blob/master/LICENSE).
|
||||
168
node_modules/jade/node_modules/clean-css/bin/cleancss
generated
vendored
Normal file
168
node_modules/jade/node_modules/clean-css/bin/cleancss
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var CleanCSS = require('../index');
|
||||
|
||||
var commands = require('commander');
|
||||
|
||||
var packageConfig = fs.readFileSync(path.join(path.dirname(fs.realpathSync(process.argv[1])), '../package.json'));
|
||||
var buildVersion = JSON.parse(packageConfig).version;
|
||||
|
||||
var isWindows = process.platform == 'win32';
|
||||
|
||||
// Specify commander options to parse command line params correctly
|
||||
commands
|
||||
.version(buildVersion, '-v, --version')
|
||||
.usage('[options] source-file, [source-file, ...]')
|
||||
.option('-b, --keep-line-breaks', 'Keep line breaks')
|
||||
.option('-c, --compatibility [ie7|ie8]', 'Force compatibility mode (see Readme for advanced examples)')
|
||||
.option('-d, --debug', 'Shows debug information (minification time & compression efficiency)')
|
||||
.option('-o, --output [output-file]', 'Use [output-file] as output instead of STDOUT')
|
||||
.option('-r, --root [root-path]', 'Set a root path to which resolve absolute @import rules')
|
||||
.option('-s, --skip-import', 'Disable @import processing')
|
||||
.option('-t, --timeout [seconds]', 'Per connection timeout when fetching remote @imports (defaults to 5 seconds)')
|
||||
.option('--rounding-precision [n]', 'Rounds to `N` decimal places. Defaults to 2. -1 disables rounding', parseInt)
|
||||
.option('--s0', 'Remove all special comments, i.e. /*! comment */')
|
||||
.option('--s1', 'Remove all special comments but the first one')
|
||||
.option('--semantic-merging', 'Enables unsafe mode by assuming BEM-like semantic stylesheets (warning, this may break your styling!)')
|
||||
.option('--skip-advanced', 'Disable advanced optimizations - ruleset reordering & merging')
|
||||
.option('--skip-aggressive-merging', 'Disable properties merging based on their order')
|
||||
.option('--skip-import-from [rules]', 'Disable @import processing for specified rules', function (val) { return val.split(','); }, [])
|
||||
.option('--skip-media-merging', 'Disable @media merging')
|
||||
.option('--skip-rebase', 'Disable URLs rebasing')
|
||||
.option('--skip-restructuring', 'Disable restructuring optimizations')
|
||||
.option('--skip-shorthand-compacting', 'Disable shorthand compacting')
|
||||
.option('--source-map', 'Enables building input\'s source map')
|
||||
.option('--source-map-inline-sources', 'Enables inlining sources inside source maps');
|
||||
|
||||
commands.on('--help', function () {
|
||||
console.log(' Examples:\n');
|
||||
console.log(' %> cleancss one.css');
|
||||
console.log(' %> cleancss -o one-min.css one.css');
|
||||
if (isWindows) {
|
||||
console.log(' %> type one.css two.css three.css | cleancss -o merged-and-minified.css');
|
||||
} else {
|
||||
console.log(' %> cat one.css two.css three.css | cleancss -o merged-and-minified.css');
|
||||
console.log(' %> cat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz');
|
||||
}
|
||||
console.log('');
|
||||
process.exit();
|
||||
});
|
||||
|
||||
commands.parse(process.argv);
|
||||
|
||||
// If no sensible data passed in just print help and exit
|
||||
var fromStdin = !process.env.__DIRECT__ && !process.stdin.isTTY;
|
||||
if (!fromStdin && commands.args.length === 0) {
|
||||
commands.outputHelp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now coerce commands into CleanCSS configuration...
|
||||
var options = {
|
||||
advanced: commands.skipAdvanced ? false : true,
|
||||
aggressiveMerging: commands.skipAggressiveMerging ? false : true,
|
||||
compatibility: commands.compatibility,
|
||||
debug: commands.debug,
|
||||
inliner: commands.timeout ? { timeout: parseFloat(commands.timeout) * 1000 } : undefined,
|
||||
keepBreaks: !!commands.keepLineBreaks,
|
||||
keepSpecialComments: commands.s0 ? 0 : (commands.s1 ? 1 : '*'),
|
||||
mediaMerging: commands.skipMediaMerging ? false : true,
|
||||
processImport: commands.skipImport ? false : true,
|
||||
processImportFrom: processImportFrom(commands.skipImportFrom),
|
||||
rebase: commands.skipRebase ? false : true,
|
||||
restructuring: commands.skipRestructuring ? false : true,
|
||||
root: commands.root,
|
||||
roundingPrecision: commands.roundingPrecision,
|
||||
semanticMerging: commands.semanticMerging ? true : false,
|
||||
shorthandCompacting: commands.skipShorthandCompacting ? false : true,
|
||||
sourceMap: commands.sourceMap,
|
||||
sourceMapInlineSources: commands.sourceMapInlineSources,
|
||||
target: commands.output
|
||||
};
|
||||
|
||||
if (options.root || commands.args.length > 0)
|
||||
options.relativeTo = path.dirname(path.resolve(options.root || commands.args[0]));
|
||||
|
||||
if (options.sourceMap && !options.target) {
|
||||
outputFeedback(['Source maps will not be built because you have not specified an output file.'], true);
|
||||
options.sourceMap = false;
|
||||
}
|
||||
|
||||
// ... and do the magic!
|
||||
if (commands.args.length > 0) {
|
||||
minify(commands.args);
|
||||
} else {
|
||||
var stdin = process.openStdin();
|
||||
stdin.setEncoding('utf-8');
|
||||
var data = '';
|
||||
stdin.on('data', function (chunk) {
|
||||
data += chunk;
|
||||
});
|
||||
stdin.on('end', function () {
|
||||
minify(data);
|
||||
});
|
||||
}
|
||||
|
||||
function processImportFrom(rules) {
|
||||
if (rules.length === 0) {
|
||||
return ['all'];
|
||||
} else if (rules.length == 1 && rules[0] == 'all') {
|
||||
return [];
|
||||
} else {
|
||||
return rules.map(function (rule) {
|
||||
if (rule == 'local')
|
||||
return 'remote';
|
||||
else if (rule == 'remote')
|
||||
return 'local';
|
||||
else
|
||||
return '!' + rule;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function minify(data) {
|
||||
new CleanCSS(options).minify(data, function (errors, minified) {
|
||||
if (options.debug) {
|
||||
console.error('Original: %d bytes', minified.stats.originalSize);
|
||||
console.error('Minified: %d bytes', minified.stats.minifiedSize);
|
||||
console.error('Efficiency: %d%', ~~(minified.stats.efficiency * 10000) / 100.0);
|
||||
console.error('Time spent: %dms', minified.stats.timeSpent);
|
||||
}
|
||||
|
||||
outputFeedback(minified.errors, true);
|
||||
outputFeedback(minified.warnings);
|
||||
|
||||
if (minified.errors.length > 0)
|
||||
process.exit(1);
|
||||
|
||||
if (minified.sourceMap) {
|
||||
var mapFilename = path.basename(options.target) + '.map';
|
||||
output(minified.styles + '/*# sourceMappingURL=' + mapFilename + ' */');
|
||||
outputMap(minified.sourceMap, mapFilename);
|
||||
} else {
|
||||
output(minified.styles);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function output(minified) {
|
||||
if (options.target)
|
||||
fs.writeFileSync(options.target, minified, 'utf8');
|
||||
else
|
||||
process.stdout.write(minified);
|
||||
}
|
||||
|
||||
function outputMap(sourceMap, mapFilename) {
|
||||
var mapPath = path.join(path.dirname(options.target), mapFilename);
|
||||
fs.writeFileSync(mapPath, sourceMap.toString(), 'utf-8');
|
||||
}
|
||||
|
||||
function outputFeedback(messages, isError) {
|
||||
var prefix = isError ? '\x1B[31mERROR\x1B[39m:' : 'WARNING:';
|
||||
|
||||
messages.forEach(function (message) {
|
||||
console.error('%s %s', prefix, message);
|
||||
});
|
||||
}
|
||||
1
node_modules/jade/node_modules/clean-css/index.js
generated
vendored
Normal file
1
node_modules/jade/node_modules/clean-css/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib/clean');
|
||||
231
node_modules/jade/node_modules/clean-css/lib/clean.js
generated
vendored
Normal file
231
node_modules/jade/node_modules/clean-css/lib/clean.js
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Clean-css - https://github.com/jakubpawlowicz/clean-css
|
||||
* Released under the terms of MIT license
|
||||
*
|
||||
* Copyright (C) 2015 JakubPawlowicz.com
|
||||
*/
|
||||
|
||||
var ImportInliner = require('./imports/inliner');
|
||||
var rebaseUrls = require('./urls/rebase');
|
||||
|
||||
var tokenize = require('./tokenizer/tokenize');
|
||||
var simpleOptimize = require('./selectors/simple');
|
||||
var advancedOptimize = require('./selectors/advanced');
|
||||
|
||||
var simpleStringify = require('./stringifier/simple');
|
||||
var sourceMapStringify = require('./stringifier/source-maps');
|
||||
|
||||
var CommentsProcessor = require('./text/comments-processor');
|
||||
var ExpressionsProcessor = require('./text/expressions-processor');
|
||||
var FreeTextProcessor = require('./text/free-text-processor');
|
||||
var UrlsProcessor = require('./text/urls-processor');
|
||||
|
||||
var Compatibility = require('./utils/compatibility');
|
||||
var InputSourceMapTracker = require('./utils/input-source-map-tracker');
|
||||
var SourceTracker = require('./utils/source-tracker');
|
||||
var SourceReader = require('./utils/source-reader');
|
||||
var Validator = require('./properties/validator');
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var url = require('url');
|
||||
|
||||
var override = require('./utils/object').override;
|
||||
|
||||
var DEFAULT_TIMEOUT = 5000;
|
||||
|
||||
var CleanCSS = module.exports = function CleanCSS(options) {
|
||||
options = options || {};
|
||||
|
||||
this.options = {
|
||||
advanced: undefined === options.advanced ? true : !!options.advanced,
|
||||
aggressiveMerging: undefined === options.aggressiveMerging ? true : !!options.aggressiveMerging,
|
||||
benchmark: options.benchmark,
|
||||
compatibility: new Compatibility(options.compatibility).toOptions(),
|
||||
debug: options.debug,
|
||||
explicitRoot: !!options.root,
|
||||
explicitTarget: !!options.target,
|
||||
inliner: options.inliner || {},
|
||||
keepBreaks: options.keepBreaks || false,
|
||||
keepSpecialComments: 'keepSpecialComments' in options ? options.keepSpecialComments : '*',
|
||||
mediaMerging: undefined === options.mediaMerging ? true : !!options.mediaMerging,
|
||||
processImport: undefined === options.processImport ? true : !!options.processImport,
|
||||
processImportFrom: importOptionsFrom(options.processImportFrom),
|
||||
rebase: undefined === options.rebase ? true : !!options.rebase,
|
||||
relativeTo: options.relativeTo,
|
||||
restructuring: undefined === options.restructuring ? true : !!options.restructuring,
|
||||
root: options.root || process.cwd(),
|
||||
roundingPrecision: options.roundingPrecision,
|
||||
semanticMerging: undefined === options.semanticMerging ? false : !!options.semanticMerging,
|
||||
shorthandCompacting: undefined === options.shorthandCompacting ? true : !!options.shorthandCompacting,
|
||||
sourceMap: options.sourceMap,
|
||||
sourceMapInlineSources: !!options.sourceMapInlineSources,
|
||||
target: !options.target || missingDirectory(options.target) || presentDirectory(options.target) ? options.target : path.dirname(options.target)
|
||||
};
|
||||
|
||||
this.options.inliner.timeout = this.options.inliner.timeout || DEFAULT_TIMEOUT;
|
||||
this.options.inliner.request = override(
|
||||
/* jshint camelcase: false */
|
||||
proxyOptionsFrom(process.env.HTTP_PROXY || process.env.http_proxy),
|
||||
this.options.inliner.request || {}
|
||||
);
|
||||
};
|
||||
|
||||
function importOptionsFrom(rules) {
|
||||
return undefined === rules ? ['all'] : rules;
|
||||
}
|
||||
|
||||
function missingDirectory(filepath) {
|
||||
return !fs.existsSync(filepath) && !/\.css$/.test(filepath);
|
||||
}
|
||||
|
||||
function presentDirectory(filepath) {
|
||||
return fs.existsSync(filepath) && fs.statSync(filepath).isDirectory();
|
||||
}
|
||||
|
||||
function proxyOptionsFrom(httpProxy) {
|
||||
return httpProxy ?
|
||||
{
|
||||
hostname: url.parse(httpProxy).hostname,
|
||||
port: parseInt(url.parse(httpProxy).port)
|
||||
} :
|
||||
{};
|
||||
}
|
||||
|
||||
CleanCSS.prototype.minify = function (data, callback) {
|
||||
var context = {
|
||||
stats: {},
|
||||
errors: [],
|
||||
warnings: [],
|
||||
options: this.options,
|
||||
debug: this.options.debug,
|
||||
localOnly: !callback,
|
||||
sourceTracker: new SourceTracker(),
|
||||
validator: new Validator(this.options.compatibility)
|
||||
};
|
||||
|
||||
if (context.options.sourceMap)
|
||||
context.inputSourceMapTracker = new InputSourceMapTracker(context);
|
||||
|
||||
context.sourceReader = new SourceReader(context, data);
|
||||
data = context.sourceReader.toString();
|
||||
|
||||
if (context.options.processImport || data.indexOf('@shallow') > 0) {
|
||||
// inline all imports
|
||||
var runner = callback ?
|
||||
process.nextTick :
|
||||
function (callback) { return callback(); };
|
||||
|
||||
return runner(function () {
|
||||
return new ImportInliner(context).process(data, {
|
||||
localOnly: context.localOnly,
|
||||
imports: context.options.processImportFrom,
|
||||
whenDone: runMinifier(callback, context)
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return runMinifier(callback, context)(data);
|
||||
}
|
||||
};
|
||||
|
||||
function runMinifier(callback, context) {
|
||||
function whenSourceMapReady (data) {
|
||||
data = context.options.debug ?
|
||||
minifyWithDebug(context, data) :
|
||||
minify(context, data);
|
||||
data = withMetadata(context, data);
|
||||
|
||||
return callback ?
|
||||
callback.call(null, context.errors.length > 0 ? context.errors : null, data) :
|
||||
data;
|
||||
}
|
||||
|
||||
return function (data) {
|
||||
if (context.options.sourceMap) {
|
||||
return context.inputSourceMapTracker.track(data, function () {
|
||||
if (context.options.sourceMapInlineSources) {
|
||||
return context.inputSourceMapTracker.resolveSources(function () {
|
||||
return whenSourceMapReady(data);
|
||||
});
|
||||
} else {
|
||||
return whenSourceMapReady(data);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return whenSourceMapReady(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function withMetadata(context, data) {
|
||||
data.stats = context.stats;
|
||||
data.errors = context.errors;
|
||||
data.warnings = context.warnings;
|
||||
return data;
|
||||
}
|
||||
|
||||
function minifyWithDebug(context, data) {
|
||||
var startedAt = process.hrtime();
|
||||
context.stats.originalSize = context.sourceTracker.removeAll(data).length;
|
||||
|
||||
data = minify(context, data);
|
||||
|
||||
var elapsed = process.hrtime(startedAt);
|
||||
context.stats.timeSpent = ~~(elapsed[0] * 1e3 + elapsed[1] / 1e6);
|
||||
context.stats.efficiency = 1 - data.styles.length / context.stats.originalSize;
|
||||
context.stats.minifiedSize = data.styles.length;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function benchmark(runner) {
|
||||
return function (processor, action) {
|
||||
var name = processor.constructor.name + '#' + action;
|
||||
var start = process.hrtime();
|
||||
runner(processor, action);
|
||||
var itTook = process.hrtime(start);
|
||||
console.log('%d ms: ' + name, 1000 * itTook[0] + itTook[1] / 1000000);
|
||||
};
|
||||
}
|
||||
|
||||
function minify(context, data) {
|
||||
var options = context.options;
|
||||
|
||||
var commentsProcessor = new CommentsProcessor(context, options.keepSpecialComments, options.keepBreaks, options.sourceMap);
|
||||
var expressionsProcessor = new ExpressionsProcessor(options.sourceMap);
|
||||
var freeTextProcessor = new FreeTextProcessor(options.sourceMap);
|
||||
var urlsProcessor = new UrlsProcessor(context, options.sourceMap, options.compatibility.properties.urlQuotes);
|
||||
|
||||
var stringify = options.sourceMap ? sourceMapStringify : simpleStringify;
|
||||
|
||||
var run = function (processor, action) {
|
||||
data = typeof processor == 'function' ?
|
||||
processor(data) :
|
||||
processor[action](data);
|
||||
};
|
||||
|
||||
if (options.benchmark)
|
||||
run = benchmark(run);
|
||||
|
||||
run(commentsProcessor, 'escape');
|
||||
run(expressionsProcessor, 'escape');
|
||||
run(urlsProcessor, 'escape');
|
||||
run(freeTextProcessor, 'escape');
|
||||
|
||||
function restoreEscapes(data, prefixContent) {
|
||||
data = freeTextProcessor.restore(data, prefixContent);
|
||||
data = urlsProcessor.restore(data);
|
||||
data = options.rebase ? rebaseUrls(data, context) : data;
|
||||
data = expressionsProcessor.restore(data);
|
||||
return commentsProcessor.restore(data);
|
||||
}
|
||||
|
||||
var tokens = tokenize(data, context);
|
||||
|
||||
simpleOptimize(tokens, options);
|
||||
|
||||
if (options.advanced)
|
||||
advancedOptimize(tokens, options, context.validator, true);
|
||||
|
||||
return stringify(tokens, options, restoreEscapes, context.inputSourceMapTracker);
|
||||
}
|
||||
186
node_modules/jade/node_modules/clean-css/lib/colors/hex-name-shortener.js
generated
vendored
Normal file
186
node_modules/jade/node_modules/clean-css/lib/colors/hex-name-shortener.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
var HexNameShortener = {};
|
||||
|
||||
var COLORS = {
|
||||
aliceblue: '#f0f8ff',
|
||||
antiquewhite: '#faebd7',
|
||||
aqua: '#0ff',
|
||||
aquamarine: '#7fffd4',
|
||||
azure: '#f0ffff',
|
||||
beige: '#f5f5dc',
|
||||
bisque: '#ffe4c4',
|
||||
black: '#000',
|
||||
blanchedalmond: '#ffebcd',
|
||||
blue: '#00f',
|
||||
blueviolet: '#8a2be2',
|
||||
brown: '#a52a2a',
|
||||
burlywood: '#deb887',
|
||||
cadetblue: '#5f9ea0',
|
||||
chartreuse: '#7fff00',
|
||||
chocolate: '#d2691e',
|
||||
coral: '#ff7f50',
|
||||
cornflowerblue: '#6495ed',
|
||||
cornsilk: '#fff8dc',
|
||||
crimson: '#dc143c',
|
||||
cyan: '#0ff',
|
||||
darkblue: '#00008b',
|
||||
darkcyan: '#008b8b',
|
||||
darkgoldenrod: '#b8860b',
|
||||
darkgray: '#a9a9a9',
|
||||
darkgreen: '#006400',
|
||||
darkgrey: '#a9a9a9',
|
||||
darkkhaki: '#bdb76b',
|
||||
darkmagenta: '#8b008b',
|
||||
darkolivegreen: '#556b2f',
|
||||
darkorange: '#ff8c00',
|
||||
darkorchid: '#9932cc',
|
||||
darkred: '#8b0000',
|
||||
darksalmon: '#e9967a',
|
||||
darkseagreen: '#8fbc8f',
|
||||
darkslateblue: '#483d8b',
|
||||
darkslategray: '#2f4f4f',
|
||||
darkslategrey: '#2f4f4f',
|
||||
darkturquoise: '#00ced1',
|
||||
darkviolet: '#9400d3',
|
||||
deeppink: '#ff1493',
|
||||
deepskyblue: '#00bfff',
|
||||
dimgray: '#696969',
|
||||
dimgrey: '#696969',
|
||||
dodgerblue: '#1e90ff',
|
||||
firebrick: '#b22222',
|
||||
floralwhite: '#fffaf0',
|
||||
forestgreen: '#228b22',
|
||||
fuchsia: '#f0f',
|
||||
gainsboro: '#dcdcdc',
|
||||
ghostwhite: '#f8f8ff',
|
||||
gold: '#ffd700',
|
||||
goldenrod: '#daa520',
|
||||
gray: '#808080',
|
||||
green: '#008000',
|
||||
greenyellow: '#adff2f',
|
||||
grey: '#808080',
|
||||
honeydew: '#f0fff0',
|
||||
hotpink: '#ff69b4',
|
||||
indianred: '#cd5c5c',
|
||||
indigo: '#4b0082',
|
||||
ivory: '#fffff0',
|
||||
khaki: '#f0e68c',
|
||||
lavender: '#e6e6fa',
|
||||
lavenderblush: '#fff0f5',
|
||||
lawngreen: '#7cfc00',
|
||||
lemonchiffon: '#fffacd',
|
||||
lightblue: '#add8e6',
|
||||
lightcoral: '#f08080',
|
||||
lightcyan: '#e0ffff',
|
||||
lightgoldenrodyellow: '#fafad2',
|
||||
lightgray: '#d3d3d3',
|
||||
lightgreen: '#90ee90',
|
||||
lightgrey: '#d3d3d3',
|
||||
lightpink: '#ffb6c1',
|
||||
lightsalmon: '#ffa07a',
|
||||
lightseagreen: '#20b2aa',
|
||||
lightskyblue: '#87cefa',
|
||||
lightslategray: '#778899',
|
||||
lightslategrey: '#778899',
|
||||
lightsteelblue: '#b0c4de',
|
||||
lightyellow: '#ffffe0',
|
||||
lime: '#0f0',
|
||||
limegreen: '#32cd32',
|
||||
linen: '#faf0e6',
|
||||
magenta: '#ff00ff',
|
||||
maroon: '#800000',
|
||||
mediumaquamarine: '#66cdaa',
|
||||
mediumblue: '#0000cd',
|
||||
mediumorchid: '#ba55d3',
|
||||
mediumpurple: '#9370db',
|
||||
mediumseagreen: '#3cb371',
|
||||
mediumslateblue: '#7b68ee',
|
||||
mediumspringgreen: '#00fa9a',
|
||||
mediumturquoise: '#48d1cc',
|
||||
mediumvioletred: '#c71585',
|
||||
midnightblue: '#191970',
|
||||
mintcream: '#f5fffa',
|
||||
mistyrose: '#ffe4e1',
|
||||
moccasin: '#ffe4b5',
|
||||
navajowhite: '#ffdead',
|
||||
navy: '#000080',
|
||||
oldlace: '#fdf5e6',
|
||||
olive: '#808000',
|
||||
olivedrab: '#6b8e23',
|
||||
orange: '#ffa500',
|
||||
orangered: '#ff4500',
|
||||
orchid: '#da70d6',
|
||||
palegoldenrod: '#eee8aa',
|
||||
palegreen: '#98fb98',
|
||||
paleturquoise: '#afeeee',
|
||||
palevioletred: '#db7093',
|
||||
papayawhip: '#ffefd5',
|
||||
peachpuff: '#ffdab9',
|
||||
peru: '#cd853f',
|
||||
pink: '#ffc0cb',
|
||||
plum: '#dda0dd',
|
||||
powderblue: '#b0e0e6',
|
||||
purple: '#800080',
|
||||
rebeccapurple: '#663399',
|
||||
red: '#f00',
|
||||
rosybrown: '#bc8f8f',
|
||||
royalblue: '#4169e1',
|
||||
saddlebrown: '#8b4513',
|
||||
salmon: '#fa8072',
|
||||
sandybrown: '#f4a460',
|
||||
seagreen: '#2e8b57',
|
||||
seashell: '#fff5ee',
|
||||
sienna: '#a0522d',
|
||||
silver: '#c0c0c0',
|
||||
skyblue: '#87ceeb',
|
||||
slateblue: '#6a5acd',
|
||||
slategray: '#708090',
|
||||
slategrey: '#708090',
|
||||
snow: '#fffafa',
|
||||
springgreen: '#00ff7f',
|
||||
steelblue: '#4682b4',
|
||||
tan: '#d2b48c',
|
||||
teal: '#008080',
|
||||
thistle: '#d8bfd8',
|
||||
tomato: '#ff6347',
|
||||
turquoise: '#40e0d0',
|
||||
violet: '#ee82ee',
|
||||
wheat: '#f5deb3',
|
||||
white: '#fff',
|
||||
whitesmoke: '#f5f5f5',
|
||||
yellow: '#ff0',
|
||||
yellowgreen: '#9acd32'
|
||||
};
|
||||
|
||||
var toHex = {};
|
||||
var toName = {};
|
||||
|
||||
for (var name in COLORS) {
|
||||
var hex = COLORS[name];
|
||||
if (name.length < hex.length)
|
||||
toName[hex] = name;
|
||||
else
|
||||
toHex[name] = hex;
|
||||
}
|
||||
|
||||
var toHexPattern = new RegExp('(^| |,|\\))(' + Object.keys(toHex).join('|') + ')( |,|\\)|$)', 'ig');
|
||||
var toNamePattern = new RegExp('(' + Object.keys(toName).join('|') + ')([^a-f0-9]|$)', 'ig');
|
||||
|
||||
function hexConverter(match, prefix, colorValue, suffix) {
|
||||
return prefix + toHex[colorValue.toLowerCase()] + suffix;
|
||||
}
|
||||
|
||||
function nameConverter(match, colorValue, suffix) {
|
||||
return toName[colorValue.toLowerCase()] + suffix;
|
||||
}
|
||||
|
||||
HexNameShortener.shorten = function (value) {
|
||||
var hasHex = value.indexOf('#') > -1;
|
||||
var shortened = value.replace(toHexPattern, hexConverter);
|
||||
|
||||
if (shortened != value)
|
||||
shortened = shortened.replace(toHexPattern, hexConverter);
|
||||
|
||||
return hasHex ? shortened.replace(toNamePattern, nameConverter) : shortened;
|
||||
};
|
||||
|
||||
module.exports = HexNameShortener;
|
||||
67
node_modules/jade/node_modules/clean-css/lib/colors/hsl.js
generated
vendored
Normal file
67
node_modules/jade/node_modules/clean-css/lib/colors/hsl.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// HSL to RGB converter. Both methods adapted from:
|
||||
// http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
|
||||
|
||||
function HSLColor(hue, saturation, lightness) {
|
||||
this.hue = hue;
|
||||
this.saturation = saturation;
|
||||
this.lightness = lightness;
|
||||
}
|
||||
|
||||
function hslToRgb(h, s, l) {
|
||||
var r, g, b;
|
||||
|
||||
// normalize hue orientation b/w 0 and 360 degrees
|
||||
h = h % 360;
|
||||
if (h < 0)
|
||||
h += 360;
|
||||
h = ~~h / 360;
|
||||
|
||||
if (s < 0)
|
||||
s = 0;
|
||||
else if (s > 100)
|
||||
s = 100;
|
||||
s = ~~s / 100;
|
||||
|
||||
if (l < 0)
|
||||
l = 0;
|
||||
else if (l > 100)
|
||||
l = 100;
|
||||
l = ~~l / 100;
|
||||
|
||||
if (s === 0) {
|
||||
r = g = b = l; // achromatic
|
||||
} else {
|
||||
var q = l < 0.5 ?
|
||||
l * (1 + s) :
|
||||
l + s - l * s;
|
||||
var p = 2 * l - q;
|
||||
r = hueToRgb(p, q, h + 1/3);
|
||||
g = hueToRgb(p, q, h);
|
||||
b = hueToRgb(p, q, h - 1/3);
|
||||
}
|
||||
|
||||
return [~~(r * 255), ~~(g * 255), ~~(b * 255)];
|
||||
}
|
||||
|
||||
function hueToRgb(p, q, t) {
|
||||
if (t < 0) t += 1;
|
||||
if (t > 1) t -= 1;
|
||||
if (t < 1/6) return p + (q - p) * 6 * t;
|
||||
if (t < 1/2) return q;
|
||||
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
||||
return p;
|
||||
}
|
||||
|
||||
HSLColor.prototype.toHex = function () {
|
||||
var asRgb = hslToRgb(this.hue, this.saturation, this.lightness);
|
||||
var redAsHex = asRgb[0].toString(16);
|
||||
var greenAsHex = asRgb[1].toString(16);
|
||||
var blueAsHex = asRgb[2].toString(16);
|
||||
|
||||
return '#' +
|
||||
((redAsHex.length == 1 ? '0' : '') + redAsHex) +
|
||||
((greenAsHex.length == 1 ? '0' : '') + greenAsHex) +
|
||||
((blueAsHex.length == 1 ? '0' : '') + blueAsHex);
|
||||
};
|
||||
|
||||
module.exports = HSLColor;
|
||||
16
node_modules/jade/node_modules/clean-css/lib/colors/rgb.js
generated
vendored
Normal file
16
node_modules/jade/node_modules/clean-css/lib/colors/rgb.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
function RGB(red, green, blue) {
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
RGB.prototype.toHex = function () {
|
||||
var red = Math.max(0, Math.min(~~this.red, 255));
|
||||
var green = Math.max(0, Math.min(~~this.green, 255));
|
||||
var blue = Math.max(0, Math.min(~~this.blue, 255));
|
||||
|
||||
// Credit: Asen http://jsbin.com/UPUmaGOc/2/edit?js,console
|
||||
return '#' + ('00000' + (red << 16 | green << 8 | blue).toString(16)).slice(-6);
|
||||
};
|
||||
|
||||
module.exports = RGB;
|
||||
393
node_modules/jade/node_modules/clean-css/lib/imports/inliner.js
generated
vendored
Normal file
393
node_modules/jade/node_modules/clean-css/lib/imports/inliner.js
generated
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
var url = require('url');
|
||||
|
||||
var rewriteUrls = require('../urls/rewrite');
|
||||
var split = require('../utils/split');
|
||||
var override = require('../utils/object.js').override;
|
||||
|
||||
var MAP_MARKER = /\/\*# sourceMappingURL=(\S+) \*\//;
|
||||
var REMOTE_RESOURCE = /^(https?:)?\/\//;
|
||||
var NO_PROTOCOL_RESOURCE = /^\/\//;
|
||||
|
||||
function ImportInliner (context) {
|
||||
this.outerContext = context;
|
||||
}
|
||||
|
||||
ImportInliner.prototype.process = function (data, context) {
|
||||
var root = this.outerContext.options.root;
|
||||
|
||||
context = override(context, {
|
||||
baseRelativeTo: this.outerContext.options.relativeTo || root,
|
||||
debug: this.outerContext.options.debug,
|
||||
done: [],
|
||||
errors: this.outerContext.errors,
|
||||
left: [],
|
||||
inliner: this.outerContext.options.inliner,
|
||||
rebase: this.outerContext.options.rebase,
|
||||
relativeTo: this.outerContext.options.relativeTo || root,
|
||||
root: root,
|
||||
sourceReader: this.outerContext.sourceReader,
|
||||
sourceTracker: this.outerContext.sourceTracker,
|
||||
warnings: this.outerContext.warnings,
|
||||
visited: []
|
||||
});
|
||||
|
||||
return importFrom(data, context);
|
||||
};
|
||||
|
||||
function importFrom(data, context) {
|
||||
if (context.shallow) {
|
||||
context.shallow = false;
|
||||
context.done.push(data);
|
||||
return processNext(context);
|
||||
}
|
||||
|
||||
var nextStart = 0;
|
||||
var nextEnd = 0;
|
||||
var cursor = 0;
|
||||
var isComment = commentScanner(data);
|
||||
|
||||
for (; nextEnd < data.length;) {
|
||||
nextStart = nextImportAt(data, cursor);
|
||||
if (nextStart == -1)
|
||||
break;
|
||||
|
||||
if (isComment(nextStart)) {
|
||||
cursor = nextStart + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
nextEnd = data.indexOf(';', nextStart);
|
||||
if (nextEnd == -1) {
|
||||
cursor = data.length;
|
||||
data = '';
|
||||
break;
|
||||
}
|
||||
|
||||
var noImportPart = data.substring(0, nextStart);
|
||||
context.done.push(noImportPart);
|
||||
context.left.unshift([data.substring(nextEnd + 1), context]);
|
||||
context.afterContent = hasContent(noImportPart);
|
||||
return inline(data, nextStart, nextEnd, context);
|
||||
}
|
||||
|
||||
// no @import matched in current data
|
||||
context.done.push(data);
|
||||
return processNext(context);
|
||||
}
|
||||
|
||||
function rebaseMap(data, source) {
|
||||
return data.replace(MAP_MARKER, function (match, sourceMapUrl) {
|
||||
return REMOTE_RESOURCE.test(sourceMapUrl) ?
|
||||
match :
|
||||
match.replace(sourceMapUrl, url.resolve(source, sourceMapUrl));
|
||||
});
|
||||
}
|
||||
|
||||
function nextImportAt(data, cursor) {
|
||||
var nextLowerCase = data.indexOf('@import', cursor);
|
||||
var nextUpperCase = data.indexOf('@IMPORT', cursor);
|
||||
|
||||
if (nextLowerCase > -1 && nextUpperCase == -1)
|
||||
return nextLowerCase;
|
||||
else if (nextLowerCase == -1 && nextUpperCase > -1)
|
||||
return nextUpperCase;
|
||||
else
|
||||
return Math.min(nextLowerCase, nextUpperCase);
|
||||
}
|
||||
|
||||
function processNext(context) {
|
||||
return context.left.length > 0 ?
|
||||
importFrom.apply(null, context.left.shift()) :
|
||||
context.whenDone(context.done.join(''));
|
||||
}
|
||||
|
||||
function commentScanner(data) {
|
||||
var commentRegex = /(\/\*(?!\*\/)[\s\S]*?\*\/)/;
|
||||
var lastStartIndex = 0;
|
||||
var lastEndIndex = 0;
|
||||
var noComments = false;
|
||||
|
||||
// test whether an index is located within a comment
|
||||
return function scanner(idx) {
|
||||
var comment;
|
||||
var localStartIndex = 0;
|
||||
var localEndIndex = 0;
|
||||
var globalStartIndex = 0;
|
||||
var globalEndIndex = 0;
|
||||
|
||||
// return if we know there are no more comments
|
||||
if (noComments)
|
||||
return false;
|
||||
|
||||
// idx can be still within last matched comment (many @import statements inside one comment)
|
||||
if (idx > lastStartIndex && idx < lastEndIndex)
|
||||
return true;
|
||||
|
||||
comment = data.match(commentRegex);
|
||||
|
||||
if (!comment) {
|
||||
noComments = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the indexes relative to the current data chunk
|
||||
lastStartIndex = localStartIndex = comment.index;
|
||||
localEndIndex = localStartIndex + comment[0].length;
|
||||
|
||||
// calculate the indexes relative to the full original data
|
||||
globalEndIndex = localEndIndex + lastEndIndex;
|
||||
globalStartIndex = globalEndIndex - comment[0].length;
|
||||
|
||||
// chop off data up to and including current comment block
|
||||
data = data.substring(localEndIndex);
|
||||
lastEndIndex = globalEndIndex;
|
||||
|
||||
// re-run scan if comment ended before the idx
|
||||
if (globalEndIndex < idx)
|
||||
return scanner(idx);
|
||||
|
||||
return globalEndIndex > idx && idx > globalStartIndex;
|
||||
};
|
||||
}
|
||||
|
||||
function hasContent(data) {
|
||||
var isComment = commentScanner(data);
|
||||
var firstContentIdx = -1;
|
||||
while (true) {
|
||||
firstContentIdx = data.indexOf('{', firstContentIdx + 1);
|
||||
if (firstContentIdx == -1 || !isComment(firstContentIdx))
|
||||
break;
|
||||
}
|
||||
|
||||
return firstContentIdx > -1;
|
||||
}
|
||||
|
||||
function inline(data, nextStart, nextEnd, context) {
|
||||
context.shallow = data.indexOf('@shallow') > 0;
|
||||
|
||||
var importDeclaration = data
|
||||
.substring(nextImportAt(data, nextStart) + '@import'.length + 1, nextEnd)
|
||||
.replace(/@shallow\)$/, ')')
|
||||
.trim();
|
||||
|
||||
var viaUrl = importDeclaration.indexOf('url(') === 0;
|
||||
var urlStartsAt = viaUrl ? 4 : 0;
|
||||
var isQuoted = /^['"]/.exec(importDeclaration.substring(urlStartsAt, urlStartsAt + 2));
|
||||
var urlEndsAt = isQuoted ?
|
||||
importDeclaration.indexOf(isQuoted[0], urlStartsAt + 1) :
|
||||
split(importDeclaration, ' ')[0].length - (viaUrl ? 1 : 0);
|
||||
|
||||
var importedFile = importDeclaration
|
||||
.substring(urlStartsAt, urlEndsAt)
|
||||
.replace(/['"]/g, '')
|
||||
.replace(/\)$/, '')
|
||||
.trim();
|
||||
|
||||
var mediaQuery = importDeclaration
|
||||
.substring(urlEndsAt + 1)
|
||||
.replace(/^\)/, '')
|
||||
.trim();
|
||||
|
||||
var isRemote = context.isRemote || REMOTE_RESOURCE.test(importedFile);
|
||||
|
||||
if (isRemote && (context.localOnly || !allowedResource(importedFile, true, context.imports))) {
|
||||
if (context.afterContent || hasContent(context.done.join('')))
|
||||
context.warnings.push('Ignoring remote @import of "' + importedFile + '" as no callback given.');
|
||||
else
|
||||
restoreImport(importedFile, mediaQuery, context);
|
||||
|
||||
return processNext(context);
|
||||
}
|
||||
|
||||
if (!isRemote && !allowedResource(importedFile, false, context.imports)) {
|
||||
if (context.afterImport)
|
||||
context.warnings.push('Ignoring local @import of "' + importedFile + '" as after other inlined content.');
|
||||
else
|
||||
restoreImport(importedFile, mediaQuery, context);
|
||||
return processNext(context);
|
||||
}
|
||||
|
||||
if (!isRemote && context.afterContent) {
|
||||
context.warnings.push('Ignoring local @import of "' + importedFile + '" as after other CSS content.');
|
||||
return processNext(context);
|
||||
}
|
||||
|
||||
var method = isRemote ? inlineRemoteResource : inlineLocalResource;
|
||||
return method(importedFile, mediaQuery, context);
|
||||
}
|
||||
|
||||
function allowedResource(importedFile, isRemote, rules) {
|
||||
if (rules.length === 0)
|
||||
return false;
|
||||
|
||||
if (isRemote && NO_PROTOCOL_RESOURCE.test(importedFile))
|
||||
importedFile = 'http:' + importedFile;
|
||||
|
||||
var match = isRemote ?
|
||||
url.parse(importedFile).host :
|
||||
importedFile;
|
||||
var allowed = true;
|
||||
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
var rule = rules[i];
|
||||
|
||||
if (rule == 'all')
|
||||
allowed = true;
|
||||
else if (isRemote && rule == 'local')
|
||||
allowed = false;
|
||||
else if (isRemote && rule == 'remote')
|
||||
allowed = true;
|
||||
else if (!isRemote && rule == 'remote')
|
||||
allowed = false;
|
||||
else if (!isRemote && rule == 'local')
|
||||
allowed = true;
|
||||
else if (rule[0] == '!' && rule.substring(1) === match)
|
||||
allowed = false;
|
||||
}
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
function inlineRemoteResource(importedFile, mediaQuery, context) {
|
||||
var importedUrl = REMOTE_RESOURCE.test(importedFile) ?
|
||||
importedFile :
|
||||
url.resolve(context.relativeTo, importedFile);
|
||||
var originalUrl = importedUrl;
|
||||
|
||||
if (NO_PROTOCOL_RESOURCE.test(importedUrl))
|
||||
importedUrl = 'http:' + importedUrl;
|
||||
|
||||
if (context.visited.indexOf(importedUrl) > -1)
|
||||
return processNext(context);
|
||||
|
||||
|
||||
if (context.debug)
|
||||
console.error('Inlining remote stylesheet: ' + importedUrl);
|
||||
|
||||
context.visited.push(importedUrl);
|
||||
|
||||
var get = importedUrl.indexOf('http://') === 0 ?
|
||||
http.get :
|
||||
https.get;
|
||||
|
||||
var errorHandled = false;
|
||||
function handleError(message) {
|
||||
if (errorHandled)
|
||||
return;
|
||||
|
||||
errorHandled = true;
|
||||
context.errors.push('Broken @import declaration of "' + importedUrl + '" - ' + message);
|
||||
restoreImport(importedUrl, mediaQuery, context);
|
||||
|
||||
process.nextTick(function () {
|
||||
processNext(context);
|
||||
});
|
||||
}
|
||||
|
||||
var requestOptions = override(url.parse(importedUrl), context.inliner.request);
|
||||
if (context.inliner.request.hostname !== undefined)
|
||||
requestOptions.path = requestOptions.href;
|
||||
|
||||
get(requestOptions, function (res) {
|
||||
if (res.statusCode < 200 || res.statusCode > 399) {
|
||||
return handleError('error ' + res.statusCode);
|
||||
} else if (res.statusCode > 299) {
|
||||
var movedUrl = url.resolve(importedUrl, res.headers.location);
|
||||
return inlineRemoteResource(movedUrl, mediaQuery, context);
|
||||
}
|
||||
|
||||
var chunks = [];
|
||||
var parsedUrl = url.parse(importedUrl);
|
||||
res.on('data', function (chunk) {
|
||||
chunks.push(chunk.toString());
|
||||
});
|
||||
res.on('end', function () {
|
||||
var importedData = chunks.join('');
|
||||
if (context.rebase)
|
||||
importedData = rewriteUrls(importedData, { toBase: originalUrl }, context);
|
||||
context.sourceReader.trackSource(importedUrl, importedData);
|
||||
importedData = context.sourceTracker.store(importedUrl, importedData);
|
||||
importedData = rebaseMap(importedData, importedUrl);
|
||||
|
||||
if (mediaQuery.length > 0)
|
||||
importedData = '@media ' + mediaQuery + '{' + importedData + '}';
|
||||
|
||||
context.afterImport = true;
|
||||
|
||||
var newContext = override(context, {
|
||||
isRemote: true,
|
||||
relativeTo: parsedUrl.protocol + '//' + parsedUrl.host + parsedUrl.pathname
|
||||
});
|
||||
|
||||
process.nextTick(function () {
|
||||
importFrom(importedData, newContext);
|
||||
});
|
||||
});
|
||||
})
|
||||
.on('error', function (res) {
|
||||
handleError(res.message);
|
||||
})
|
||||
.on('timeout', function () {
|
||||
handleError('timeout');
|
||||
})
|
||||
.setTimeout(context.inliner.timeout);
|
||||
}
|
||||
|
||||
function inlineLocalResource(importedFile, mediaQuery, context) {
|
||||
var relativeTo = importedFile[0] == '/' ?
|
||||
context.root :
|
||||
context.relativeTo;
|
||||
|
||||
var fullPath = path.resolve(path.join(relativeTo, importedFile));
|
||||
|
||||
if (!fs.existsSync(fullPath) || !fs.statSync(fullPath).isFile()) {
|
||||
context.errors.push('Broken @import declaration of "' + importedFile + '"');
|
||||
return processNext(context);
|
||||
}
|
||||
|
||||
if (context.visited.indexOf(fullPath) > -1)
|
||||
return processNext(context);
|
||||
|
||||
|
||||
if (context.debug)
|
||||
console.error('Inlining local stylesheet: ' + fullPath);
|
||||
|
||||
context.visited.push(fullPath);
|
||||
|
||||
var importRelativeTo = path.dirname(fullPath);
|
||||
var importedData = fs.readFileSync(fullPath, 'utf8');
|
||||
if (context.rebase) {
|
||||
var rewriteOptions = {
|
||||
relative: true,
|
||||
fromBase: importRelativeTo,
|
||||
toBase: context.baseRelativeTo
|
||||
};
|
||||
importedData = rewriteUrls(importedData, rewriteOptions, context);
|
||||
}
|
||||
|
||||
var relativePath = path.relative(context.root, fullPath);
|
||||
context.sourceReader.trackSource(relativePath, importedData);
|
||||
importedData = context.sourceTracker.store(relativePath, importedData);
|
||||
|
||||
if (mediaQuery.length > 0)
|
||||
importedData = '@media ' + mediaQuery + '{' + importedData + '}';
|
||||
|
||||
context.afterImport = true;
|
||||
|
||||
var newContext = override(context, {
|
||||
relativeTo: importRelativeTo
|
||||
});
|
||||
|
||||
return importFrom(importedData, newContext);
|
||||
}
|
||||
|
||||
function restoreImport(importedUrl, mediaQuery, context) {
|
||||
var restoredImport = '@import url(' + importedUrl + ')' + (mediaQuery.length > 0 ? ' ' + mediaQuery : '') + ';';
|
||||
context.done.push(restoredImport);
|
||||
}
|
||||
|
||||
module.exports = ImportInliner;
|
||||
329
node_modules/jade/node_modules/clean-css/lib/properties/break-up.js
generated
vendored
Normal file
329
node_modules/jade/node_modules/clean-css/lib/properties/break-up.js
generated
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
var wrapSingle = require('./wrap-for-optimizing').single;
|
||||
|
||||
var split = require('../utils/split');
|
||||
var MULTIPLEX_SEPARATOR = ',';
|
||||
|
||||
function _colorFilter(validator) {
|
||||
return function (value) {
|
||||
return value[0] == 'invert' || validator.isValidColor(value[0]);
|
||||
};
|
||||
}
|
||||
|
||||
function _styleFilter(validator) {
|
||||
return function (value) {
|
||||
return value[0] != 'inherit' && validator.isValidStyle(value[0]);
|
||||
};
|
||||
}
|
||||
|
||||
function _wrapDefault(name, property, compactable) {
|
||||
var descriptor = compactable[name];
|
||||
if (descriptor.doubleValues && descriptor.defaultValue.length == 2)
|
||||
return wrapSingle([[name, property.important], [descriptor.defaultValue[0]], [descriptor.defaultValue[1]]]);
|
||||
else if (descriptor.doubleValues && descriptor.defaultValue.length == 1)
|
||||
return wrapSingle([[name, property.important], [descriptor.defaultValue[0]]]);
|
||||
else
|
||||
return wrapSingle([[name, property.important], [descriptor.defaultValue]]);
|
||||
}
|
||||
|
||||
function _widthFilter(validator) {
|
||||
return function (value) {
|
||||
return value[0] != 'inherit' && validator.isValidWidth(value[0]);
|
||||
};
|
||||
}
|
||||
|
||||
function background(property, compactable, validator) {
|
||||
var image = _wrapDefault('background-image', property, compactable);
|
||||
var position = _wrapDefault('background-position', property, compactable);
|
||||
var size = _wrapDefault('background-size', property, compactable);
|
||||
var repeat = _wrapDefault('background-repeat', property, compactable);
|
||||
var attachment = _wrapDefault('background-attachment', property, compactable);
|
||||
var origin = _wrapDefault('background-origin', property, compactable);
|
||||
var clip = _wrapDefault('background-clip', property, compactable);
|
||||
var color = _wrapDefault('background-color', property, compactable);
|
||||
var components = [image, position, size, repeat, attachment, origin, clip, color];
|
||||
var values = property.value;
|
||||
|
||||
var positionSet = false;
|
||||
var clipSet = false;
|
||||
var originSet = false;
|
||||
var repeatSet = false;
|
||||
|
||||
if (property.value.length == 1 && property.value[0][0] == 'inherit') {
|
||||
// NOTE: 'inherit' is not a valid value for background-attachment
|
||||
color.value = image.value = repeat.value = position.value = size.value = origin.value = clip.value = property.value;
|
||||
return components;
|
||||
}
|
||||
|
||||
for (var i = values.length - 1; i >= 0; i--) {
|
||||
var value = values[i];
|
||||
|
||||
if (validator.isValidBackgroundAttachment(value[0])) {
|
||||
attachment.value = [value];
|
||||
} else if (validator.isValidBackgroundBox(value[0])) {
|
||||
if (clipSet) {
|
||||
origin.value = [value];
|
||||
originSet = true;
|
||||
} else {
|
||||
clip.value = [value];
|
||||
clipSet = true;
|
||||
}
|
||||
} else if (validator.isValidBackgroundRepeat(value[0])) {
|
||||
if (repeatSet) {
|
||||
repeat.value.unshift(value);
|
||||
} else {
|
||||
repeat.value = [value];
|
||||
repeatSet = true;
|
||||
}
|
||||
} else if (validator.isValidBackgroundPositionPart(value[0]) || validator.isValidBackgroundSizePart(value[0])) {
|
||||
if (i > 0) {
|
||||
var previousValue = values[i - 1];
|
||||
|
||||
if (previousValue[0].indexOf('/') > 0) {
|
||||
var twoParts = split(previousValue[0], '/');
|
||||
// NOTE: we do this slicing as value may contain metadata too, like for source maps
|
||||
size.value = [[twoParts.pop()].concat(previousValue.slice(1)), value];
|
||||
values[i - 1] = [twoParts.pop()].concat(previousValue.slice(1));
|
||||
} else if (i > 1 && values[i - 2] == '/') {
|
||||
size.value = [previousValue, value];
|
||||
i -= 2;
|
||||
} else if (previousValue[0] == '/') {
|
||||
size.value = [value];
|
||||
} else {
|
||||
if (!positionSet)
|
||||
position.value = [];
|
||||
|
||||
position.value.unshift(value);
|
||||
positionSet = true;
|
||||
}
|
||||
} else {
|
||||
if (!positionSet)
|
||||
position.value = [];
|
||||
|
||||
position.value.unshift(value);
|
||||
positionSet = true;
|
||||
}
|
||||
} else if (validator.isValidBackgroundPositionAndSize(value[0])) {
|
||||
var sizeValue = split(value[0], '/');
|
||||
// NOTE: we do this slicing as value may contain metadata too, like for source maps
|
||||
size.value = [[sizeValue.pop()].concat(value.slice(1))];
|
||||
position.value = [[sizeValue.pop()].concat(value.slice(1))];
|
||||
} else if ((color.value[0][0] == compactable[color.name].defaultValue || color.value[0][0] == 'none') && validator.isValidColor(value[0])) {
|
||||
color.value = [value];
|
||||
} else if (validator.isValidUrl(value[0]) || validator.isValidFunction(value[0])) {
|
||||
image.value = [value];
|
||||
}
|
||||
}
|
||||
|
||||
if (clipSet && !originSet)
|
||||
origin.value = clip.value.slice(0);
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
function borderRadius(property, compactable) {
|
||||
var values = property.value;
|
||||
var splitAt = -1;
|
||||
|
||||
for (var i = 0, l = values.length; i < l; i++) {
|
||||
if (values[i][0] == '/') {
|
||||
splitAt = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (splitAt == -1)
|
||||
return fourValues(property, compactable);
|
||||
|
||||
var target = _wrapDefault(property.name, property, compactable);
|
||||
target.value = values.slice(0, splitAt);
|
||||
target.components = fourValues(target, compactable);
|
||||
|
||||
var remainder = _wrapDefault(property.name, property, compactable);
|
||||
remainder.value = values.slice(splitAt + 1);
|
||||
remainder.components = fourValues(remainder, compactable);
|
||||
|
||||
for (var j = 0; j < 4; j++) {
|
||||
target.components[j].multiplex = true;
|
||||
target.components[j].value = target.components[j].value.concat([['/']]).concat(remainder.components[j].value);
|
||||
}
|
||||
|
||||
return target.components;
|
||||
}
|
||||
|
||||
function fourValues(property, compactable) {
|
||||
var componentNames = compactable[property.name].components;
|
||||
var components = [];
|
||||
var value = property.value;
|
||||
|
||||
if (value.length < 1)
|
||||
return [];
|
||||
|
||||
if (value.length < 2)
|
||||
value[1] = value[0].slice(0);
|
||||
if (value.length < 3)
|
||||
value[2] = value[0].slice(0);
|
||||
if (value.length < 4)
|
||||
value[3] = value[1].slice(0);
|
||||
|
||||
for (var i = componentNames.length - 1; i >= 0; i--) {
|
||||
var component = wrapSingle([[componentNames[i], property.important]]);
|
||||
component.value = [value[i]];
|
||||
components.unshift(component);
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
function multiplex(splitWith) {
|
||||
return function (property, compactable, validator) {
|
||||
var splitsAt = [];
|
||||
var values = property.value;
|
||||
var i, j, l, m;
|
||||
|
||||
// find split commas
|
||||
for (i = 0, l = values.length; i < l; i++) {
|
||||
if (values[i][0] == ',')
|
||||
splitsAt.push(i);
|
||||
}
|
||||
|
||||
if (splitsAt.length === 0)
|
||||
return splitWith(property, compactable, validator);
|
||||
|
||||
var splitComponents = [];
|
||||
|
||||
// split over commas, and into components
|
||||
for (i = 0, l = splitsAt.length; i <= l; i++) {
|
||||
var from = i === 0 ? 0 : splitsAt[i - 1] + 1;
|
||||
var to = i < l ? splitsAt[i] : values.length;
|
||||
|
||||
var _property = _wrapDefault(property.name, property, compactable);
|
||||
_property.value = values.slice(from, to);
|
||||
|
||||
splitComponents.push(splitWith(_property, compactable, validator));
|
||||
}
|
||||
|
||||
var components = splitComponents[0];
|
||||
|
||||
// group component values from each split
|
||||
for (i = 0, l = components.length; i < l; i++) {
|
||||
components[i].multiplex = true;
|
||||
|
||||
for (j = 1, m = splitComponents.length; j < m; j++) {
|
||||
components[i].value.push([MULTIPLEX_SEPARATOR]);
|
||||
Array.prototype.push.apply(components[i].value, splitComponents[j][i].value);
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
};
|
||||
}
|
||||
|
||||
function listStyle(property, compactable, validator) {
|
||||
var type = _wrapDefault('list-style-type', property, compactable);
|
||||
var position = _wrapDefault('list-style-position', property, compactable);
|
||||
var image = _wrapDefault('list-style-image', property, compactable);
|
||||
var components = [type, position, image];
|
||||
|
||||
if (property.value.length == 1 && property.value[0][0] == 'inherit') {
|
||||
type.value = position.value = image.value = [property.value[0]];
|
||||
return components;
|
||||
}
|
||||
|
||||
var values = property.value.slice(0);
|
||||
var total = values.length;
|
||||
var index = 0;
|
||||
|
||||
// `image` first...
|
||||
for (index = 0, total = values.length; index < total; index++) {
|
||||
if (validator.isValidUrl(values[index][0]) || values[index][0] == '0') {
|
||||
image.value = [values[index]];
|
||||
values.splice(index, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ... then `type`...
|
||||
for (index = 0, total = values.length; index < total; index++) {
|
||||
if (validator.isValidListStyleType(values[index][0])) {
|
||||
type.value = [values[index]];
|
||||
values.splice(index, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ... and what's left is a `position`
|
||||
if (values.length > 0 && validator.isValidListStylePosition(values[0][0]))
|
||||
position.value = [values[0]];
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
function widthStyleColor(property, compactable, validator) {
|
||||
var descriptor = compactable[property.name];
|
||||
var components = [
|
||||
_wrapDefault(descriptor.components[0], property, compactable),
|
||||
_wrapDefault(descriptor.components[1], property, compactable),
|
||||
_wrapDefault(descriptor.components[2], property, compactable)
|
||||
];
|
||||
var color, style, width;
|
||||
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var component = components[i];
|
||||
|
||||
if (component.name.indexOf('color') > 0)
|
||||
color = component;
|
||||
else if (component.name.indexOf('style') > 0)
|
||||
style = component;
|
||||
else
|
||||
width = component;
|
||||
}
|
||||
|
||||
if ((property.value.length == 1 && property.value[0][0] == 'inherit') ||
|
||||
(property.value.length == 3 && property.value[0][0] == 'inherit' && property.value[1][0] == 'inherit' && property.value[2][0] == 'inherit')) {
|
||||
color.value = style.value = width.value = [property.value[0]];
|
||||
return components;
|
||||
}
|
||||
|
||||
var values = property.value.slice(0);
|
||||
var match, matches;
|
||||
|
||||
// NOTE: usually users don't follow the required order of parts in this shorthand,
|
||||
// so we'll try to parse it caring as little about order as possible
|
||||
|
||||
if (values.length > 0) {
|
||||
matches = values.filter(_widthFilter(validator));
|
||||
match = matches.length > 1 && (matches[0][0] == 'none' || matches[0][0] == 'auto') ? matches[1] : matches[0];
|
||||
if (match) {
|
||||
width.value = [match];
|
||||
values.splice(values.indexOf(match), 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (values.length > 0) {
|
||||
match = values.filter(_styleFilter(validator))[0];
|
||||
if (match) {
|
||||
style.value = [match];
|
||||
values.splice(values.indexOf(match), 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (values.length > 0) {
|
||||
match = values.filter(_colorFilter(validator))[0];
|
||||
if (match) {
|
||||
color.value = [match];
|
||||
values.splice(values.indexOf(match), 1);
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
background: background,
|
||||
border: widthStyleColor,
|
||||
borderRadius: borderRadius,
|
||||
fourValues: fourValues,
|
||||
listStyle: listStyle,
|
||||
multiplex: multiplex,
|
||||
outline: widthStyleColor
|
||||
};
|
||||
120
node_modules/jade/node_modules/clean-css/lib/properties/can-override.js
generated
vendored
Normal file
120
node_modules/jade/node_modules/clean-css/lib/properties/can-override.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
// Functions that decide what value can override what.
|
||||
// The main purpose is to disallow removing CSS fallbacks.
|
||||
// A separate implementation is needed for every different kind of CSS property.
|
||||
// -----
|
||||
// The generic idea is that properties that have wider browser support are 'more understandable'
|
||||
// than others and that 'less understandable' values can't override more understandable ones.
|
||||
|
||||
// Use when two tokens of the same property can always be merged
|
||||
function always() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function backgroundImage(property1, property2, validator) {
|
||||
// The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
|
||||
// Understandability: (none | url | inherit) > (same function) > (same value)
|
||||
|
||||
// (none | url)
|
||||
var image1 = property1.value[0][0];
|
||||
var image2 = property2.value[0][0];
|
||||
|
||||
if (image2 == 'none' || image2 == 'inherit' || validator.isValidUrl(image2))
|
||||
return true;
|
||||
if (image1 == 'none' || image1 == 'inherit' || validator.isValidUrl(image1))
|
||||
return false;
|
||||
|
||||
// Functions with the same name can override each other; same values can override each other
|
||||
return sameFunctionOrValue(property1, property2, validator);
|
||||
}
|
||||
|
||||
function border(property1, property2, validator) {
|
||||
return color(property1.components[2], property2.components[2], validator);
|
||||
}
|
||||
|
||||
// Use for color properties (color, background-color, border-color, etc.)
|
||||
function color(property1, property2, validator) {
|
||||
// The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
|
||||
// Understandability: (hex | named) > (rgba | hsla) > (same function name) > anything else
|
||||
// NOTE: at this point rgb and hsl are replaced by hex values by clean-css
|
||||
|
||||
var color1 = property1.value[0][0];
|
||||
var color2 = property2.value[0][0];
|
||||
|
||||
// (hex | named)
|
||||
if (validator.isValidNamedColor(color2) || validator.isValidHexColor(color2))
|
||||
return true;
|
||||
if (validator.isValidNamedColor(color1) || validator.isValidHexColor(color1))
|
||||
return false;
|
||||
|
||||
// (rgba|hsla)
|
||||
if (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2))
|
||||
return true;
|
||||
if (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1))
|
||||
return false;
|
||||
|
||||
// Functions with the same name can override each other; same values can override each other
|
||||
return sameFunctionOrValue(property1, property2, validator);
|
||||
}
|
||||
|
||||
function twoOptionalFunctions(property1, property2, validator) {
|
||||
var value1 = property1.value[0][0];
|
||||
var value2 = property2.value[0][0];
|
||||
|
||||
return !(validator.isValidFunction(value1) ^ validator.isValidFunction(value2));
|
||||
}
|
||||
|
||||
function sameValue(property1, property2) {
|
||||
var value1 = property1.value[0][0];
|
||||
var value2 = property2.value[0][0];
|
||||
|
||||
return value1 === value2;
|
||||
}
|
||||
|
||||
function sameFunctionOrValue(property1, property2, validator) {
|
||||
var value1 = property1.value[0][0];
|
||||
var value2 = property2.value[0][0];
|
||||
|
||||
// Functions with the same name can override each other
|
||||
if (validator.areSameFunction(value1, value2))
|
||||
return true;
|
||||
|
||||
return value1 === value2;
|
||||
}
|
||||
|
||||
// Use for properties containing CSS units (margin-top, padding-left, etc.)
|
||||
function unit(property1, property2, validator) {
|
||||
// The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
|
||||
// Understandability: (unit without functions) > (same functions | standard functions) > anything else
|
||||
// NOTE: there is no point in having different vendor-specific functions override each other or standard functions,
|
||||
// or having standard functions override vendor-specific functions, but standard functions can override each other
|
||||
// NOTE: vendor-specific property values are not taken into consideration here at the moment
|
||||
var value1 = property1.value[0][0];
|
||||
var value2 = property2.value[0][0];
|
||||
|
||||
if (validator.isValidAndCompatibleUnitWithoutFunction(value1) && !validator.isValidAndCompatibleUnitWithoutFunction(value2))
|
||||
return false;
|
||||
|
||||
if (validator.isValidUnitWithoutFunction(value2))
|
||||
return true;
|
||||
if (validator.isValidUnitWithoutFunction(value1))
|
||||
return false;
|
||||
|
||||
// Standard non-vendor-prefixed functions can override each other
|
||||
if (validator.isValidFunctionWithoutVendorPrefix(value2) && validator.isValidFunctionWithoutVendorPrefix(value1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Functions with the same name can override each other; same values can override each other
|
||||
return sameFunctionOrValue(property1, property2, validator);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
always: always,
|
||||
backgroundImage: backgroundImage,
|
||||
border: border,
|
||||
color: color,
|
||||
sameValue: sameValue,
|
||||
sameFunctionOrValue: sameFunctionOrValue,
|
||||
twoOptionalFunctions: twoOptionalFunctions,
|
||||
unit: unit
|
||||
};
|
||||
26
node_modules/jade/node_modules/clean-css/lib/properties/clone.js
generated
vendored
Normal file
26
node_modules/jade/node_modules/clean-css/lib/properties/clone.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
var wrapSingle = require('./wrap-for-optimizing').single;
|
||||
|
||||
function deep(property) {
|
||||
var cloned = shallow(property);
|
||||
for (var i = property.components.length - 1; i >= 0; i--) {
|
||||
var component = shallow(property.components[i]);
|
||||
component.value = property.components[i].value.slice(0);
|
||||
cloned.components.unshift(component);
|
||||
}
|
||||
|
||||
cloned.dirty = true;
|
||||
cloned.value = property.value.slice(0);
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
function shallow(property) {
|
||||
var cloned = wrapSingle([[property.name, property.important, property.hack]]);
|
||||
cloned.unused = false;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
deep: deep,
|
||||
shallow: shallow
|
||||
};
|
||||
285
node_modules/jade/node_modules/clean-css/lib/properties/compactable.js
generated
vendored
Normal file
285
node_modules/jade/node_modules/clean-css/lib/properties/compactable.js
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
// Contains the interpretation of CSS properties, as used by the property optimizer
|
||||
|
||||
var breakUp = require('./break-up');
|
||||
var canOverride = require('./can-override');
|
||||
var restore = require('./restore');
|
||||
|
||||
// Properties to process
|
||||
// Extend this object in order to add support for more properties in the optimizer.
|
||||
//
|
||||
// Each key in this object represents a CSS property and should be an object.
|
||||
// Such an object contains properties that describe how the represented CSS property should be handled.
|
||||
// Possible options:
|
||||
//
|
||||
// * components: array (Only specify for shorthand properties.)
|
||||
// Contains the names of the granular properties this shorthand compacts.
|
||||
//
|
||||
// * canOverride: function (Default is canOverride.sameValue - meaning that they'll only be merged if they have the same value.)
|
||||
// Returns whether two tokens of this property can be merged with each other.
|
||||
// This property has no meaning for shorthands.
|
||||
//
|
||||
// * defaultValue: string
|
||||
// Specifies the default value of the property according to the CSS standard.
|
||||
// For shorthand, this is used when every component is set to its default value, therefore it should be the shortest possible default value of all the components.
|
||||
//
|
||||
// * shortestValue: string
|
||||
// Specifies the shortest possible value the property can possibly have.
|
||||
// (Falls back to defaultValue if unspecified.)
|
||||
//
|
||||
// * breakUp: function (Only specify for shorthand properties.)
|
||||
// Breaks the shorthand up to its components.
|
||||
//
|
||||
// * restore: function (Only specify for shorthand properties.)
|
||||
// Puts the shorthand together from its components.
|
||||
//
|
||||
var compactable = {
|
||||
'color': {
|
||||
canOverride: canOverride.color,
|
||||
defaultValue: 'transparent',
|
||||
shortestValue: 'red'
|
||||
},
|
||||
'background': {
|
||||
components: [
|
||||
'background-image',
|
||||
'background-position',
|
||||
'background-size',
|
||||
'background-repeat',
|
||||
'background-attachment',
|
||||
'background-origin',
|
||||
'background-clip',
|
||||
'background-color'
|
||||
],
|
||||
breakUp: breakUp.multiplex(breakUp.background),
|
||||
defaultValue: '0 0',
|
||||
restore: restore.multiplex(restore.background),
|
||||
shortestValue: '0',
|
||||
shorthand: true
|
||||
},
|
||||
'background-clip': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'border-box',
|
||||
shortestValue: 'border-box'
|
||||
},
|
||||
'background-color': {
|
||||
canOverride: canOverride.color,
|
||||
defaultValue: 'transparent',
|
||||
multiplexLastOnly: true,
|
||||
nonMergeableValue: 'none',
|
||||
shortestValue: 'red'
|
||||
},
|
||||
'background-image': {
|
||||
canOverride: canOverride.backgroundImage,
|
||||
defaultValue: 'none'
|
||||
},
|
||||
'background-origin': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'padding-box',
|
||||
shortestValue: 'border-box'
|
||||
},
|
||||
'background-repeat': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: ['repeat'],
|
||||
doubleValues: true
|
||||
},
|
||||
'background-position': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: ['0', '0'],
|
||||
doubleValues: true,
|
||||
shortestValue: '0'
|
||||
},
|
||||
'background-size': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: ['auto'],
|
||||
doubleValues: true,
|
||||
shortestValue: '0 0'
|
||||
},
|
||||
'background-attachment': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'scroll'
|
||||
},
|
||||
'border': {
|
||||
breakUp: breakUp.border,
|
||||
canOverride: canOverride.border,
|
||||
components: [
|
||||
'border-width',
|
||||
'border-style',
|
||||
'border-color'
|
||||
],
|
||||
defaultValue: 'none',
|
||||
restore: restore.withoutDefaults,
|
||||
shorthand: true
|
||||
},
|
||||
'border-color': {
|
||||
canOverride: canOverride.color,
|
||||
defaultValue: 'none',
|
||||
shorthand: true
|
||||
},
|
||||
'border-style': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'none',
|
||||
shorthand: true
|
||||
},
|
||||
'border-width': {
|
||||
canOverride: canOverride.unit,
|
||||
defaultValue: 'medium',
|
||||
shortestValue: '0',
|
||||
shorthand: true
|
||||
},
|
||||
'list-style': {
|
||||
components: [
|
||||
'list-style-type',
|
||||
'list-style-position',
|
||||
'list-style-image'
|
||||
],
|
||||
canOverride: canOverride.always,
|
||||
breakUp: breakUp.listStyle,
|
||||
restore: restore.withoutDefaults,
|
||||
defaultValue: 'outside', // can't use 'disc' because that'd override default 'decimal' for <ol>
|
||||
shortestValue: 'none',
|
||||
shorthand: true
|
||||
},
|
||||
'list-style-type' : {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: '__hack',
|
||||
// NOTE: we can't tell the real default value here, it's 'disc' for <ul> and 'decimal' for <ol>
|
||||
// -- this is a hack, but it doesn't matter because this value will be either overridden or it will disappear at the final step anyway
|
||||
shortestValue: 'none'
|
||||
},
|
||||
'list-style-position' : {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'outside',
|
||||
shortestValue: 'inside'
|
||||
},
|
||||
'list-style-image' : {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'none'
|
||||
},
|
||||
'outline': {
|
||||
components: [
|
||||
'outline-color',
|
||||
'outline-style',
|
||||
'outline-width'
|
||||
],
|
||||
breakUp: breakUp.outline,
|
||||
restore: restore.withoutDefaults,
|
||||
defaultValue: '0',
|
||||
shorthand: true
|
||||
},
|
||||
'outline-color': {
|
||||
canOverride: canOverride.color,
|
||||
defaultValue: 'invert',
|
||||
shortestValue: 'red'
|
||||
},
|
||||
'outline-style': {
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'none'
|
||||
},
|
||||
'outline-width': {
|
||||
canOverride: canOverride.unit,
|
||||
defaultValue: 'medium',
|
||||
shortestValue: '0'
|
||||
},
|
||||
'-moz-transform': {
|
||||
canOverride: canOverride.sameFunctionOrValue
|
||||
},
|
||||
'-ms-transform': {
|
||||
canOverride: canOverride.sameFunctionOrValue
|
||||
},
|
||||
'-webkit-transform': {
|
||||
canOverride: canOverride.sameFunctionOrValue
|
||||
},
|
||||
'transform': {
|
||||
canOverride: canOverride.sameFunctionOrValue
|
||||
}
|
||||
};
|
||||
|
||||
var addFourValueShorthand = function (prop, components, options) {
|
||||
options = options || {};
|
||||
compactable[prop] = {
|
||||
canOverride: options.canOverride,
|
||||
components: components,
|
||||
breakUp: options.breakUp || breakUp.fourValues,
|
||||
defaultValue: options.defaultValue || '0',
|
||||
restore: options.restore || restore.fourValues,
|
||||
shortestValue: options.shortestValue,
|
||||
shorthand: true
|
||||
};
|
||||
for (var i = 0; i < components.length; i++) {
|
||||
compactable[components[i]] = {
|
||||
breakUp: options.breakUp || breakUp.fourValues,
|
||||
canOverride: options.canOverride || canOverride.unit,
|
||||
defaultValue: options.defaultValue || '0',
|
||||
shortestValue: options.shortestValue
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
['', '-moz-', '-o-', '-webkit-'].forEach(function (prefix) {
|
||||
addFourValueShorthand(prefix + 'border-radius', [
|
||||
prefix + 'border-top-left-radius',
|
||||
prefix + 'border-top-right-radius',
|
||||
prefix + 'border-bottom-right-radius',
|
||||
prefix + 'border-bottom-left-radius'
|
||||
], {
|
||||
breakUp: breakUp.borderRadius,
|
||||
restore: restore.borderRadius
|
||||
});
|
||||
});
|
||||
|
||||
addFourValueShorthand('border-color', [
|
||||
'border-top-color',
|
||||
'border-right-color',
|
||||
'border-bottom-color',
|
||||
'border-left-color'
|
||||
], {
|
||||
breakUp: breakUp.fourValues,
|
||||
canOverride: canOverride.color,
|
||||
defaultValue: 'none',
|
||||
shortestValue: 'red'
|
||||
});
|
||||
|
||||
addFourValueShorthand('border-style', [
|
||||
'border-top-style',
|
||||
'border-right-style',
|
||||
'border-bottom-style',
|
||||
'border-left-style'
|
||||
], {
|
||||
breakUp: breakUp.fourValues,
|
||||
canOverride: canOverride.always,
|
||||
defaultValue: 'none'
|
||||
});
|
||||
|
||||
addFourValueShorthand('border-width', [
|
||||
'border-top-width',
|
||||
'border-right-width',
|
||||
'border-bottom-width',
|
||||
'border-left-width'
|
||||
], {
|
||||
defaultValue: 'medium',
|
||||
shortestValue: '0'
|
||||
});
|
||||
|
||||
addFourValueShorthand('padding', [
|
||||
'padding-top',
|
||||
'padding-right',
|
||||
'padding-bottom',
|
||||
'padding-left'
|
||||
]);
|
||||
|
||||
addFourValueShorthand('margin', [
|
||||
'margin-top',
|
||||
'margin-right',
|
||||
'margin-bottom',
|
||||
'margin-left'
|
||||
]);
|
||||
|
||||
// Adds `componentOf` field to all longhands
|
||||
for (var property in compactable) {
|
||||
if (compactable[property].shorthand) {
|
||||
for (var i = 0, l = compactable[property].components.length; i < l; i++) {
|
||||
compactable[compactable[property].components[i]].componentOf = property;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = compactable;
|
||||
24
node_modules/jade/node_modules/clean-css/lib/properties/every-combination.js
generated
vendored
Normal file
24
node_modules/jade/node_modules/clean-css/lib/properties/every-combination.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
var shallowClone = require('./clone').shallow;
|
||||
|
||||
var MULTIPLEX_SEPARATOR = ',';
|
||||
|
||||
function everyCombination(fn, left, right, validator) {
|
||||
var _left = shallowClone(left);
|
||||
var _right = shallowClone(right);
|
||||
|
||||
for (var i = 0, l = left.value.length; i < l; i++) {
|
||||
for (var j = 0, m = right.value.length; j < m; j++) {
|
||||
if (left.value[i][0] == MULTIPLEX_SEPARATOR || right.value[j][0] == MULTIPLEX_SEPARATOR)
|
||||
continue;
|
||||
|
||||
_left.value = [left.value[i]];
|
||||
_right.value = [right.value[j]];
|
||||
if (!fn(_left, _right, validator))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = everyCombination;
|
||||
10
node_modules/jade/node_modules/clean-css/lib/properties/has-inherit.js
generated
vendored
Normal file
10
node_modules/jade/node_modules/clean-css/lib/properties/has-inherit.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
function hasInherit(property) {
|
||||
for (var i = property.value.length - 1; i >= 0; i--) {
|
||||
if (property.value[i][0] == 'inherit')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = hasInherit;
|
||||
206
node_modules/jade/node_modules/clean-css/lib/properties/optimizer.js
generated
vendored
Normal file
206
node_modules/jade/node_modules/clean-css/lib/properties/optimizer.js
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
var compactable = require('./compactable');
|
||||
var wrapForOptimizing = require('./wrap-for-optimizing').all;
|
||||
var populateComponents = require('./populate-components');
|
||||
var compactOverrides = require('./override-compactor');
|
||||
var compactShorthands = require('./shorthand-compactor');
|
||||
var removeUnused = require('./remove-unused');
|
||||
var restoreFromOptimizing = require('./restore-from-optimizing');
|
||||
var stringifyProperty = require('../stringifier/one-time').property;
|
||||
|
||||
var shorthands = {
|
||||
'animation-delay': ['animation'],
|
||||
'animation-direction': ['animation'],
|
||||
'animation-duration': ['animation'],
|
||||
'animation-fill-mode': ['animation'],
|
||||
'animation-iteration-count': ['animation'],
|
||||
'animation-name': ['animation'],
|
||||
'animation-play-state': ['animation'],
|
||||
'animation-timing-function': ['animation'],
|
||||
'-moz-animation-delay': ['-moz-animation'],
|
||||
'-moz-animation-direction': ['-moz-animation'],
|
||||
'-moz-animation-duration': ['-moz-animation'],
|
||||
'-moz-animation-fill-mode': ['-moz-animation'],
|
||||
'-moz-animation-iteration-count': ['-moz-animation'],
|
||||
'-moz-animation-name': ['-moz-animation'],
|
||||
'-moz-animation-play-state': ['-moz-animation'],
|
||||
'-moz-animation-timing-function': ['-moz-animation'],
|
||||
'-o-animation-delay': ['-o-animation'],
|
||||
'-o-animation-direction': ['-o-animation'],
|
||||
'-o-animation-duration': ['-o-animation'],
|
||||
'-o-animation-fill-mode': ['-o-animation'],
|
||||
'-o-animation-iteration-count': ['-o-animation'],
|
||||
'-o-animation-name': ['-o-animation'],
|
||||
'-o-animation-play-state': ['-o-animation'],
|
||||
'-o-animation-timing-function': ['-o-animation'],
|
||||
'-webkit-animation-delay': ['-webkit-animation'],
|
||||
'-webkit-animation-direction': ['-webkit-animation'],
|
||||
'-webkit-animation-duration': ['-webkit-animation'],
|
||||
'-webkit-animation-fill-mode': ['-webkit-animation'],
|
||||
'-webkit-animation-iteration-count': ['-webkit-animation'],
|
||||
'-webkit-animation-name': ['-webkit-animation'],
|
||||
'-webkit-animation-play-state': ['-webkit-animation'],
|
||||
'-webkit-animation-timing-function': ['-webkit-animation'],
|
||||
'border-color': ['border'],
|
||||
'border-style': ['border'],
|
||||
'border-width': ['border'],
|
||||
'border-bottom': ['border'],
|
||||
'border-bottom-color': ['border-bottom', 'border-color', 'border'],
|
||||
'border-bottom-style': ['border-bottom', 'border-style', 'border'],
|
||||
'border-bottom-width': ['border-bottom', 'border-width', 'border'],
|
||||
'border-left': ['border'],
|
||||
'border-left-color': ['border-left', 'border-color', 'border'],
|
||||
'border-left-style': ['border-left', 'border-style', 'border'],
|
||||
'border-left-width': ['border-left', 'border-width', 'border'],
|
||||
'border-right': ['border'],
|
||||
'border-right-color': ['border-right', 'border-color', 'border'],
|
||||
'border-right-style': ['border-right', 'border-style', 'border'],
|
||||
'border-right-width': ['border-right', 'border-width', 'border'],
|
||||
'border-top': ['border'],
|
||||
'border-top-color': ['border-top', 'border-color', 'border'],
|
||||
'border-top-style': ['border-top', 'border-style', 'border'],
|
||||
'border-top-width': ['border-top', 'border-width', 'border'],
|
||||
'font-family': ['font'],
|
||||
'font-size': ['font'],
|
||||
'font-style': ['font'],
|
||||
'font-variant': ['font'],
|
||||
'font-weight': ['font'],
|
||||
'transition-delay': ['transition'],
|
||||
'transition-duration': ['transition'],
|
||||
'transition-property': ['transition'],
|
||||
'transition-timing-function': ['transition'],
|
||||
'-moz-transition-delay': ['-moz-transition'],
|
||||
'-moz-transition-duration': ['-moz-transition'],
|
||||
'-moz-transition-property': ['-moz-transition'],
|
||||
'-moz-transition-timing-function': ['-moz-transition'],
|
||||
'-o-transition-delay': ['-o-transition'],
|
||||
'-o-transition-duration': ['-o-transition'],
|
||||
'-o-transition-property': ['-o-transition'],
|
||||
'-o-transition-timing-function': ['-o-transition'],
|
||||
'-webkit-transition-delay': ['-webkit-transition'],
|
||||
'-webkit-transition-duration': ['-webkit-transition'],
|
||||
'-webkit-transition-property': ['-webkit-transition'],
|
||||
'-webkit-transition-timing-function': ['-webkit-transition']
|
||||
};
|
||||
|
||||
function _optimize(properties, mergeAdjacent, aggressiveMerging, validator) {
|
||||
var overrideMapping = {};
|
||||
var lastName = null;
|
||||
var j;
|
||||
|
||||
function mergeablePosition(position) {
|
||||
if (mergeAdjacent === false || mergeAdjacent === true)
|
||||
return mergeAdjacent;
|
||||
|
||||
return mergeAdjacent.indexOf(position) > -1;
|
||||
}
|
||||
|
||||
function sameValue(position) {
|
||||
var left = properties[position - 1];
|
||||
var right = properties[position];
|
||||
|
||||
return stringifyProperty(left.all, left.position) == stringifyProperty(right.all, right.position);
|
||||
}
|
||||
|
||||
propertyLoop:
|
||||
for (var position = 0, total = properties.length; position < total; position++) {
|
||||
var property = properties[position];
|
||||
var _name = (property.name == '-ms-filter' || property.name == 'filter') ?
|
||||
(lastName == 'background' || lastName == 'background-image' ? lastName : property.name) :
|
||||
property.name;
|
||||
var isImportant = property.important;
|
||||
var isHack = property.hack;
|
||||
|
||||
if (property.unused)
|
||||
continue;
|
||||
|
||||
if (position > 0 && _name == lastName && sameValue(position)) {
|
||||
property.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// comment is necessary - we assume that if two properties are one after another
|
||||
// then it is intentional way of redefining property which may not be widely supported
|
||||
// e.g. a{display:inline-block;display:-moz-inline-box}
|
||||
// however if `mergeablePosition` yields true then the rule does not apply
|
||||
// (e.g merging two adjacent selectors: `a{display:block}a{display:block}`)
|
||||
if (_name in overrideMapping && (aggressiveMerging && _name != lastName || mergeablePosition(position))) {
|
||||
var toOverridePositions = overrideMapping[_name];
|
||||
var canOverride = compactable[_name] && compactable[_name].canOverride;
|
||||
var anyRemoved = false;
|
||||
|
||||
for (j = toOverridePositions.length - 1; j >= 0; j--) {
|
||||
var toRemove = properties[toOverridePositions[j]];
|
||||
var longhandToShorthand = toRemove.name != _name;
|
||||
var wasImportant = toRemove.important;
|
||||
var wasHack = toRemove.hack;
|
||||
|
||||
if (toRemove.unused)
|
||||
continue;
|
||||
|
||||
if (longhandToShorthand && wasImportant)
|
||||
continue;
|
||||
|
||||
if (!wasImportant && (wasHack && !isHack || !wasHack && isHack))
|
||||
continue;
|
||||
|
||||
if (wasImportant && (isHack == 'star' || isHack == 'underscore'))
|
||||
continue;
|
||||
|
||||
if (!wasHack && !isHack && !longhandToShorthand && canOverride && !canOverride(toRemove, property, validator))
|
||||
continue;
|
||||
|
||||
if (wasImportant && !isImportant || wasImportant && isHack) {
|
||||
property.unused = true;
|
||||
continue propertyLoop;
|
||||
} else {
|
||||
anyRemoved = true;
|
||||
toRemove.unused = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyRemoved) {
|
||||
position = -1;
|
||||
overrideMapping = {};
|
||||
}
|
||||
} else {
|
||||
overrideMapping[_name] = overrideMapping[_name] || [];
|
||||
overrideMapping[_name].push(position);
|
||||
|
||||
// TODO: to be removed with
|
||||
// certain shorthand (see values of `shorthands`) should trigger removal of
|
||||
// longhand properties (see keys of `shorthands`)
|
||||
var _shorthands = shorthands[_name];
|
||||
if (_shorthands) {
|
||||
for (j = _shorthands.length - 1; j >= 0; j--) {
|
||||
var shorthand = _shorthands[j];
|
||||
overrideMapping[shorthand] = overrideMapping[shorthand] || [];
|
||||
overrideMapping[shorthand].push(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastName = _name;
|
||||
}
|
||||
}
|
||||
|
||||
function optimize(selector, properties, mergeAdjacent, withCompacting, options, validator) {
|
||||
var _properties = wrapForOptimizing(properties);
|
||||
populateComponents(_properties, validator);
|
||||
_optimize(_properties, mergeAdjacent, options.aggressiveMerging, validator);
|
||||
|
||||
for (var i = 0, l = _properties.length; i < l; i++) {
|
||||
var _property = _properties[i];
|
||||
if (_property.variable && _property.block)
|
||||
optimize(selector, _property.value[0], mergeAdjacent, withCompacting, options, validator);
|
||||
}
|
||||
|
||||
if (withCompacting && options.shorthandCompacting) {
|
||||
compactOverrides(_properties, options.compatibility, validator);
|
||||
compactShorthands(_properties, options.sourceMap, validator);
|
||||
}
|
||||
|
||||
restoreFromOptimizing(_properties);
|
||||
removeUnused(_properties);
|
||||
}
|
||||
|
||||
module.exports = optimize;
|
||||
376
node_modules/jade/node_modules/clean-css/lib/properties/override-compactor.js
generated
vendored
Normal file
376
node_modules/jade/node_modules/clean-css/lib/properties/override-compactor.js
generated
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
var canOverride = require('./can-override');
|
||||
var compactable = require('./compactable');
|
||||
var deepClone = require('./clone').deep;
|
||||
var shallowClone = require('./clone').shallow;
|
||||
var hasInherit = require('./has-inherit');
|
||||
var restoreFromOptimizing = require('./restore-from-optimizing');
|
||||
var everyCombination = require('./every-combination');
|
||||
var sameVendorPrefixesIn = require('./vendor-prefixes').same;
|
||||
|
||||
var stringifyProperty = require('../stringifier/one-time').property;
|
||||
|
||||
var MULTIPLEX_SEPARATOR = ',';
|
||||
|
||||
// Used when searching for a component that matches property
|
||||
function nameMatchFilter(to) {
|
||||
return function (property) {
|
||||
return to.name === property.name;
|
||||
};
|
||||
}
|
||||
|
||||
function wouldBreakCompatibility(property, validator) {
|
||||
for (var i = 0; i < property.components.length; i++) {
|
||||
var component = property.components[i];
|
||||
var descriptor = compactable[component.name];
|
||||
var canOverride = descriptor && descriptor.canOverride || canOverride.sameValue;
|
||||
|
||||
var _component = shallowClone(component);
|
||||
_component.value = [[descriptor.defaultValue]];
|
||||
|
||||
if (!canOverride(_component, component, validator))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isComponentOf(shorthand, longhand) {
|
||||
return compactable[shorthand.name].components.indexOf(longhand.name) > -1;
|
||||
}
|
||||
|
||||
function overrideIntoMultiplex(property, by) {
|
||||
by.unused = true;
|
||||
|
||||
turnIntoMultiplex(by, multiplexSize(property));
|
||||
property.value = by.value;
|
||||
}
|
||||
|
||||
function overrideByMultiplex(property, by) {
|
||||
by.unused = true;
|
||||
property.multiplex = true;
|
||||
property.value = by.value;
|
||||
}
|
||||
|
||||
function overrideSimple(property, by) {
|
||||
by.unused = true;
|
||||
property.value = by.value;
|
||||
}
|
||||
|
||||
function override(property, by) {
|
||||
if (by.multiplex)
|
||||
overrideByMultiplex(property, by);
|
||||
else if (property.multiplex)
|
||||
overrideIntoMultiplex(property, by);
|
||||
else
|
||||
overrideSimple(property, by);
|
||||
}
|
||||
|
||||
function overrideShorthand(property, by) {
|
||||
by.unused = true;
|
||||
|
||||
for (var i = 0, l = property.components.length; i < l; i++) {
|
||||
override(property.components[i], by.components[i], property.multiplex);
|
||||
}
|
||||
}
|
||||
|
||||
function turnIntoMultiplex(property, size) {
|
||||
property.multiplex = true;
|
||||
|
||||
for (var i = 0, l = property.components.length; i < l; i++) {
|
||||
var component = property.components[i];
|
||||
if (component.multiplex)
|
||||
continue;
|
||||
|
||||
var value = component.value.slice(0);
|
||||
|
||||
for (var j = 1; j < size; j++) {
|
||||
component.value.push([MULTIPLEX_SEPARATOR]);
|
||||
Array.prototype.push.apply(component.value, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function multiplexSize(component) {
|
||||
var size = 0;
|
||||
|
||||
for (var i = 0, l = component.value.length; i < l; i++) {
|
||||
if (component.value[i][0] == MULTIPLEX_SEPARATOR)
|
||||
size++;
|
||||
}
|
||||
|
||||
return size + 1;
|
||||
}
|
||||
|
||||
function lengthOf(property) {
|
||||
var fakeAsArray = [[property.name]].concat(property.value);
|
||||
return stringifyProperty([fakeAsArray], 0).length;
|
||||
}
|
||||
|
||||
function moreSameShorthands(properties, startAt, name) {
|
||||
// Since we run the main loop in `compactOverrides` backwards, at this point some
|
||||
// properties may not be marked as unused.
|
||||
// We should consider reverting the order if possible
|
||||
var count = 0;
|
||||
|
||||
for (var i = startAt; i >= 0; i--) {
|
||||
if (properties[i].name == name && !properties[i].unused)
|
||||
count++;
|
||||
if (count > 1)
|
||||
break;
|
||||
}
|
||||
|
||||
return count > 1;
|
||||
}
|
||||
|
||||
function mergingIntoFunction(left, right, validator) {
|
||||
for (var i = 0, l = left.components.length; i < l; i++) {
|
||||
if (anyValue(validator.isValidFunction, left.components[i]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function anyValue(fn, property) {
|
||||
for (var i = 0, l = property.value.length; i < l; i++) {
|
||||
if (property.value[i][0] == MULTIPLEX_SEPARATOR)
|
||||
continue;
|
||||
|
||||
if (fn(property.value[i][0]))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function wouldResultInLongerValue(left, right) {
|
||||
if (!left.multiplex && !right.multiplex || left.multiplex && right.multiplex)
|
||||
return false;
|
||||
|
||||
var multiplex = left.multiplex ? left : right;
|
||||
var simple = left.multiplex ? right : left;
|
||||
var component;
|
||||
|
||||
var multiplexClone = deepClone(multiplex);
|
||||
restoreFromOptimizing([multiplexClone]);
|
||||
|
||||
var simpleClone = deepClone(simple);
|
||||
restoreFromOptimizing([simpleClone]);
|
||||
|
||||
var lengthBefore = lengthOf(multiplexClone) + 1 + lengthOf(simpleClone);
|
||||
|
||||
if (left.multiplex) {
|
||||
component = multiplexClone.components.filter(nameMatchFilter(simpleClone))[0];
|
||||
overrideIntoMultiplex(component, simpleClone);
|
||||
} else {
|
||||
component = simpleClone.components.filter(nameMatchFilter(multiplexClone))[0];
|
||||
turnIntoMultiplex(simpleClone, multiplexSize(multiplexClone));
|
||||
overrideByMultiplex(component, multiplexClone);
|
||||
}
|
||||
|
||||
restoreFromOptimizing([simpleClone]);
|
||||
|
||||
var lengthAfter = lengthOf(simpleClone);
|
||||
|
||||
return lengthBefore < lengthAfter;
|
||||
}
|
||||
|
||||
function isCompactable(property) {
|
||||
return property.name in compactable;
|
||||
}
|
||||
|
||||
function noneOverrideHack(left, right) {
|
||||
return !left.multiplex &&
|
||||
(left.name == 'background' || left.name == 'background-image') &&
|
||||
right.multiplex &&
|
||||
(right.name == 'background' || right.name == 'background-image') &&
|
||||
anyLayerIsNone(right.value);
|
||||
}
|
||||
|
||||
function anyLayerIsNone(values) {
|
||||
var layers = intoLayers(values);
|
||||
|
||||
for (var i = 0, l = layers.length; i < l; i++) {
|
||||
if (layers[i].length == 1 && layers[i][0][0] == 'none')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function intoLayers(values) {
|
||||
var layers = [];
|
||||
|
||||
for (var i = 0, layer = [], l = values.length; i < l; i++) {
|
||||
var value = values[i];
|
||||
if (value[0] == MULTIPLEX_SEPARATOR) {
|
||||
layers.push(layer);
|
||||
layer = [];
|
||||
} else {
|
||||
layer.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
layers.push(layer);
|
||||
return layers;
|
||||
}
|
||||
|
||||
function compactOverrides(properties, compatibility, validator) {
|
||||
var mayOverride, right, left, component;
|
||||
var i, j, k;
|
||||
|
||||
propertyLoop:
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
right = properties[i];
|
||||
|
||||
if (!isCompactable(right))
|
||||
continue;
|
||||
|
||||
if (right.variable)
|
||||
continue;
|
||||
|
||||
mayOverride = compactable[right.name].canOverride || canOverride.sameValue;
|
||||
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
left = properties[j];
|
||||
|
||||
if (!isCompactable(left))
|
||||
continue;
|
||||
|
||||
if (left.variable)
|
||||
continue;
|
||||
|
||||
if (left.unused || right.unused)
|
||||
continue;
|
||||
|
||||
if (left.hack && !right.hack || !left.hack && right.hack)
|
||||
continue;
|
||||
|
||||
if (hasInherit(right))
|
||||
continue;
|
||||
|
||||
if (noneOverrideHack(left, right))
|
||||
continue;
|
||||
|
||||
if (!left.shorthand && right.shorthand && isComponentOf(right, left)) {
|
||||
// maybe `left` can be overridden by `right` which is a shorthand?
|
||||
if (!right.important && left.important)
|
||||
continue;
|
||||
|
||||
if (!sameVendorPrefixesIn([left], right.components))
|
||||
continue;
|
||||
|
||||
component = right.components.filter(nameMatchFilter(left))[0];
|
||||
mayOverride = (compactable[left.name] && compactable[left.name].canOverride) || canOverride.sameValue;
|
||||
if (everyCombination(mayOverride, left, component, validator)) {
|
||||
left.unused = true;
|
||||
}
|
||||
} else if (left.shorthand && !right.shorthand && isComponentOf(left, right)) {
|
||||
// maybe `right` can be pulled into `left` which is a shorthand?
|
||||
if (right.important && !left.important)
|
||||
continue;
|
||||
|
||||
// Pending more clever algorithm in #527
|
||||
if (moreSameShorthands(properties, i - 1, left.name))
|
||||
continue;
|
||||
|
||||
if (mergingIntoFunction(left, right, validator))
|
||||
continue;
|
||||
|
||||
component = left.components.filter(nameMatchFilter(right))[0];
|
||||
if (everyCombination(mayOverride, component, right, validator)) {
|
||||
var disabledBackgroundMerging =
|
||||
!compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1 ||
|
||||
!compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1 ||
|
||||
!compatibility.properties.backgroundSizeMerging && component.name.indexOf('background-size') > -1;
|
||||
var nonMergeableValue = compactable[right.name].nonMergeableValue === right.value[0][0];
|
||||
|
||||
if (disabledBackgroundMerging || nonMergeableValue)
|
||||
continue;
|
||||
|
||||
if (!compatibility.properties.merging && wouldBreakCompatibility(left, validator))
|
||||
continue;
|
||||
|
||||
if (component.value[0][0] != right.value[0][0] && (hasInherit(left) || hasInherit(right)))
|
||||
continue;
|
||||
|
||||
if (wouldResultInLongerValue(left, right))
|
||||
continue;
|
||||
|
||||
if (!left.multiplex && right.multiplex)
|
||||
turnIntoMultiplex(left, multiplexSize(right));
|
||||
|
||||
override(component, right);
|
||||
left.dirty = true;
|
||||
}
|
||||
} else if (left.shorthand && right.shorthand && left.name == right.name) {
|
||||
// merge if all components can be merged
|
||||
|
||||
if (!left.multiplex && right.multiplex)
|
||||
continue;
|
||||
|
||||
if (!right.important && left.important) {
|
||||
right.unused = true;
|
||||
continue propertyLoop;
|
||||
}
|
||||
|
||||
if (right.important && !left.important) {
|
||||
left.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (k = left.components.length - 1; k >= 0; k--) {
|
||||
var leftComponent = left.components[k];
|
||||
var rightComponent = right.components[k];
|
||||
|
||||
mayOverride = compactable[leftComponent.name].canOverride || canOverride.sameValue;
|
||||
if (!everyCombination(mayOverride, leftComponent, rightComponent, validator))
|
||||
continue propertyLoop;
|
||||
if (!everyCombination(canOverride.twoOptionalFunctions, leftComponent, rightComponent, validator) && validator.isValidFunction(rightComponent))
|
||||
continue propertyLoop;
|
||||
}
|
||||
|
||||
overrideShorthand(left, right);
|
||||
left.dirty = true;
|
||||
} else if (left.shorthand && right.shorthand && isComponentOf(left, right)) {
|
||||
// border is a shorthand but any of its components is a shorthand too
|
||||
|
||||
if (!left.important && right.important)
|
||||
continue;
|
||||
|
||||
component = left.components.filter(nameMatchFilter(right))[0];
|
||||
mayOverride = compactable[right.name].canOverride || canOverride.sameValue;
|
||||
if (!everyCombination(mayOverride, component, right, validator))
|
||||
continue;
|
||||
|
||||
if (left.important && !right.important) {
|
||||
right.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
var rightRestored = compactable[right.name].restore(right, compactable);
|
||||
if (rightRestored.length > 1)
|
||||
continue;
|
||||
|
||||
component = left.components.filter(nameMatchFilter(right))[0];
|
||||
override(component, right);
|
||||
right.dirty = true;
|
||||
} else if (left.name == right.name) {
|
||||
// two non-shorthands should be merged based on understandability
|
||||
|
||||
if (left.important && !right.important) {
|
||||
right.unused = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
mayOverride = compactable[right.name].canOverride || canOverride.sameValue;
|
||||
if (!everyCombination(mayOverride, left, right, validator))
|
||||
continue;
|
||||
|
||||
left.unused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = compactOverrides;
|
||||
21
node_modules/jade/node_modules/clean-css/lib/properties/populate-components.js
generated
vendored
Normal file
21
node_modules/jade/node_modules/clean-css/lib/properties/populate-components.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var compactable = require('./compactable');
|
||||
|
||||
function populateComponents(properties, validator) {
|
||||
for (var i = properties.length - 1; i >= 0; i--) {
|
||||
var property = properties[i];
|
||||
var descriptor = compactable[property.name];
|
||||
|
||||
if (descriptor && descriptor.shorthand) {
|
||||
property.shorthand = true;
|
||||
property.dirty = true;
|
||||
property.components = descriptor.breakUp(property, compactable, validator);
|
||||
|
||||
if (property.components.length > 0)
|
||||
property.multiplex = property.components[0].multiplex;
|
||||
else
|
||||
property.unused = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = populateComponents;
|
||||
10
node_modules/jade/node_modules/clean-css/lib/properties/remove-unused.js
generated
vendored
Normal file
10
node_modules/jade/node_modules/clean-css/lib/properties/remove-unused.js
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
function removeUnused(properties) {
|
||||
for (var i = properties.length - 1; i >= 0; i--) {
|
||||
var property = properties[i];
|
||||
|
||||
if (property.unused)
|
||||
property.all.splice(property.position, 1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeUnused;
|
||||
60
node_modules/jade/node_modules/clean-css/lib/properties/restore-from-optimizing.js
generated
vendored
Normal file
60
node_modules/jade/node_modules/clean-css/lib/properties/restore-from-optimizing.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
var compactable = require('./compactable');
|
||||
|
||||
var BACKSLASH_HACK = '\\9';
|
||||
var IMPORTANT_TOKEN = '!important';
|
||||
var STAR_HACK = '*';
|
||||
var UNDERSCORE_HACK = '_';
|
||||
var BANG_HACK = '!ie';
|
||||
|
||||
function restoreImportant(property) {
|
||||
property.value[property.value.length - 1][0] += IMPORTANT_TOKEN;
|
||||
}
|
||||
|
||||
function restoreHack(property) {
|
||||
if (property.hack == 'underscore')
|
||||
property.name = UNDERSCORE_HACK + property.name;
|
||||
else if (property.hack == 'star')
|
||||
property.name = STAR_HACK + property.name;
|
||||
else if (property.hack == 'backslash')
|
||||
property.value[property.value.length - 1][0] += BACKSLASH_HACK;
|
||||
else if (property.hack == 'bang')
|
||||
property.value[property.value.length - 1][0] += ' ' + BANG_HACK;
|
||||
}
|
||||
|
||||
function restoreFromOptimizing(properties, simpleMode) {
|
||||
for (var i = properties.length - 1; i >= 0; i--) {
|
||||
var property = properties[i];
|
||||
var descriptor = compactable[property.name];
|
||||
var restored;
|
||||
|
||||
if (property.unused)
|
||||
continue;
|
||||
|
||||
if (!property.dirty && !property.important && !property.hack)
|
||||
continue;
|
||||
|
||||
if (!simpleMode && descriptor && descriptor.shorthand) {
|
||||
restored = descriptor.restore(property, compactable);
|
||||
property.value = restored;
|
||||
} else {
|
||||
restored = property.value;
|
||||
}
|
||||
|
||||
if (property.important)
|
||||
restoreImportant(property);
|
||||
|
||||
if (property.hack)
|
||||
restoreHack(property);
|
||||
|
||||
if (!('all' in property))
|
||||
continue;
|
||||
|
||||
var current = property.all[property.position];
|
||||
current[0][0] = property.name;
|
||||
|
||||
current.splice(1, current.length - 1);
|
||||
Array.prototype.push.apply(current, restored);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = restoreFromOptimizing;
|
||||
229
node_modules/jade/node_modules/clean-css/lib/properties/restore.js
generated
vendored
Normal file
229
node_modules/jade/node_modules/clean-css/lib/properties/restore.js
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
var shallowClone = require('./clone').shallow;
|
||||
var MULTIPLEX_SEPARATOR = ',';
|
||||
var SIZE_POSITION_SEPARATOR = '/';
|
||||
|
||||
function isInheritOnly(values) {
|
||||
for (var i = 0, l = values.length; i < l; i++) {
|
||||
var value = values[i][0];
|
||||
|
||||
if (value != 'inherit' && value != MULTIPLEX_SEPARATOR && value != SIZE_POSITION_SEPARATOR)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function background(property, compactable, lastInMultiplex) {
|
||||
var components = property.components;
|
||||
var restored = [];
|
||||
var needsOne, needsBoth;
|
||||
|
||||
function restoreValue(component) {
|
||||
Array.prototype.unshift.apply(restored, component.value);
|
||||
}
|
||||
|
||||
function isDefaultValue(component) {
|
||||
var descriptor = compactable[component.name];
|
||||
if (descriptor.doubleValues) {
|
||||
if (descriptor.defaultValue.length == 1)
|
||||
return component.value[0][0] == descriptor.defaultValue[0] && (component.value[1] ? component.value[1][0] == descriptor.defaultValue[0] : true);
|
||||
else
|
||||
return component.value[0][0] == descriptor.defaultValue[0] && (component.value[1] ? component.value[1][0] : component.value[0][0]) == descriptor.defaultValue[1];
|
||||
} else {
|
||||
return component.value[0][0] == descriptor.defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = components.length - 1; i >= 0; i--) {
|
||||
var component = components[i];
|
||||
var isDefault = isDefaultValue(component);
|
||||
|
||||
if (component.name == 'background-clip') {
|
||||
var originComponent = components[i - 1];
|
||||
var isOriginDefault = isDefaultValue(originComponent);
|
||||
|
||||
needsOne = component.value[0][0] == originComponent.value[0][0];
|
||||
|
||||
needsBoth = !needsOne && (
|
||||
(isOriginDefault && !isDefault) ||
|
||||
(!isOriginDefault && !isDefault) ||
|
||||
(!isOriginDefault && isDefault && component.value[0][0] != originComponent.value[0][0]));
|
||||
|
||||
if (needsOne) {
|
||||
restoreValue(originComponent);
|
||||
} else if (needsBoth) {
|
||||
restoreValue(component);
|
||||
restoreValue(originComponent);
|
||||
}
|
||||
|
||||
i--;
|
||||
} else if (component.name == 'background-size') {
|
||||
var positionComponent = components[i - 1];
|
||||
var isPositionDefault = isDefaultValue(positionComponent);
|
||||
|
||||
needsOne = !isPositionDefault && isDefault;
|
||||
|
||||
needsBoth = !needsOne &&
|
||||
(isPositionDefault && !isDefault || !isPositionDefault && !isDefault);
|
||||
|
||||
if (needsOne) {
|
||||
restoreValue(positionComponent);
|
||||
} else if (needsBoth) {
|
||||
restoreValue(component);
|
||||
restored.unshift([SIZE_POSITION_SEPARATOR]);
|
||||
restoreValue(positionComponent);
|
||||
} else if (positionComponent.value.length == 1) {
|
||||
restoreValue(positionComponent);
|
||||
}
|
||||
|
||||
i--;
|
||||
} else {
|
||||
if (isDefault || compactable[component.name].multiplexLastOnly && !lastInMultiplex)
|
||||
continue;
|
||||
|
||||
restoreValue(component);
|
||||
}
|
||||
}
|
||||
|
||||
if (restored.length === 0 && property.value.length == 1 && property.value[0][0] == '0')
|
||||
restored.push(property.value[0]);
|
||||
|
||||
if (restored.length === 0)
|
||||
restored.push([compactable[property.name].defaultValue]);
|
||||
|
||||
if (isInheritOnly(restored))
|
||||
return [restored[0]];
|
||||
|
||||
return restored;
|
||||
}
|
||||
|
||||
function borderRadius(property, compactable) {
|
||||
if (property.multiplex) {
|
||||
var horizontal = shallowClone(property);
|
||||
var vertical = shallowClone(property);
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var component = property.components[i];
|
||||
|
||||
var horizontalComponent = shallowClone(property);
|
||||
horizontalComponent.value = [component.value[0]];
|
||||
horizontal.components.push(horizontalComponent);
|
||||
|
||||
var verticalComponent = shallowClone(property);
|
||||
verticalComponent.value = [component.value[2]];
|
||||
vertical.components.push(verticalComponent);
|
||||
}
|
||||
|
||||
var horizontalValues = fourValues(horizontal, compactable);
|
||||
var verticalValues = fourValues(vertical, compactable);
|
||||
|
||||
if (horizontalValues.length == verticalValues.length &&
|
||||
horizontalValues[0][0] == verticalValues[0][0] &&
|
||||
(horizontalValues.length > 1 ? horizontalValues[1][0] == verticalValues[1][0] : true) &&
|
||||
(horizontalValues.length > 2 ? horizontalValues[2][0] == verticalValues[2][0] : true) &&
|
||||
(horizontalValues.length > 3 ? horizontalValues[3][0] == verticalValues[3][0] : true)) {
|
||||
return horizontalValues;
|
||||
} else {
|
||||
return horizontalValues.concat([['/']]).concat(verticalValues);
|
||||
}
|
||||
} else {
|
||||
return fourValues(property, compactable);
|
||||
}
|
||||
}
|
||||
|
||||
function fourValues(property) {
|
||||
var components = property.components;
|
||||
var value1 = components[0].value[0];
|
||||
var value2 = components[1].value[0];
|
||||
var value3 = components[2].value[0];
|
||||
var value4 = components[3].value[0];
|
||||
|
||||
if (value1[0] == value2[0] && value1[0] == value3[0] && value1[0] == value4[0]) {
|
||||
return [value1];
|
||||
} else if (value1[0] == value3[0] && value2[0] == value4[0]) {
|
||||
return [value1, value2];
|
||||
} else if (value2[0] == value4[0]) {
|
||||
return [value1, value2, value3];
|
||||
} else {
|
||||
return [value1, value2, value3, value4];
|
||||
}
|
||||
}
|
||||
|
||||
function multiplex(restoreWith) {
|
||||
return function (property, compactable) {
|
||||
if (!property.multiplex)
|
||||
return restoreWith(property, compactable, true);
|
||||
|
||||
var multiplexSize = 0;
|
||||
var restored = [];
|
||||
var componentMultiplexSoFar = {};
|
||||
var i, l;
|
||||
|
||||
// At this point we don't know what's the multiplex size, e.g. how many background layers are there
|
||||
for (i = 0, l = property.components[0].value.length; i < l; i++) {
|
||||
if (property.components[0].value[i][0] == MULTIPLEX_SEPARATOR)
|
||||
multiplexSize++;
|
||||
}
|
||||
|
||||
for (i = 0; i <= multiplexSize; i++) {
|
||||
var _property = shallowClone(property);
|
||||
|
||||
// We split multiplex into parts and restore them one by one
|
||||
for (var j = 0, m = property.components.length; j < m; j++) {
|
||||
var componentToClone = property.components[j];
|
||||
var _component = shallowClone(componentToClone);
|
||||
_property.components.push(_component);
|
||||
|
||||
// The trick is some properties has more than one value, so we iterate over values looking for
|
||||
// a multiplex separator - a comma
|
||||
for (var k = componentMultiplexSoFar[_component.name] || 0, n = componentToClone.value.length; k < n; k++) {
|
||||
if (componentToClone.value[k][0] == MULTIPLEX_SEPARATOR) {
|
||||
componentMultiplexSoFar[_component.name] = k + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
_component.value.push(componentToClone.value[k]);
|
||||
}
|
||||
}
|
||||
|
||||
// No we can restore shorthand value
|
||||
var lastInMultiplex = i == multiplexSize;
|
||||
var _restored = restoreWith(_property, compactable, lastInMultiplex);
|
||||
Array.prototype.push.apply(restored, _restored);
|
||||
|
||||
if (i < multiplexSize)
|
||||
restored.push([',']);
|
||||
}
|
||||
|
||||
return restored;
|
||||
};
|
||||
}
|
||||
|
||||
function withoutDefaults(property, compactable) {
|
||||
var components = property.components;
|
||||
var restored = [];
|
||||
|
||||
for (var i = components.length - 1; i >= 0; i--) {
|
||||
var component = components[i];
|
||||
var descriptor = compactable[component.name];
|
||||
|
||||
if (component.value[0][0] != descriptor.defaultValue)
|
||||
restored.unshift(component.value[0]);
|
||||
}
|
||||
|
||||
if (restored.length === 0)
|
||||
restored.push([compactable[property.name].defaultValue]);
|
||||
|
||||
if (isInheritOnly(restored))
|
||||
return [restored[0]];
|
||||
|
||||
return restored;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
background: background,
|
||||
borderRadius: borderRadius,
|
||||
fourValues: fourValues,
|
||||
multiplex: multiplex,
|
||||
withoutDefaults: withoutDefaults
|
||||
};
|
||||
134
node_modules/jade/node_modules/clean-css/lib/properties/shorthand-compactor.js
generated
vendored
Normal file
134
node_modules/jade/node_modules/clean-css/lib/properties/shorthand-compactor.js
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
var compactable = require('./compactable');
|
||||
var deepClone = require('./clone').deep;
|
||||
var hasInherit = require('./has-inherit');
|
||||
var populateComponents = require('./populate-components');
|
||||
var wrapSingle = require('./wrap-for-optimizing').single;
|
||||
var everyCombination = require('./every-combination');
|
||||
|
||||
function mixedImportance(components) {
|
||||
var important;
|
||||
|
||||
for (var name in components) {
|
||||
if (undefined !== important && components[name].important != important)
|
||||
return true;
|
||||
|
||||
important = components[name].important;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function componentSourceMaps(components) {
|
||||
var sourceMapping = [];
|
||||
|
||||
for (var name in components) {
|
||||
var component = components[name];
|
||||
var originalValue = component.all[component.position];
|
||||
var mapping = originalValue[0][originalValue[0].length - 1];
|
||||
|
||||
if (Array.isArray(mapping))
|
||||
Array.prototype.push.apply(sourceMapping, mapping);
|
||||
}
|
||||
|
||||
return sourceMapping;
|
||||
}
|
||||
|
||||
function replaceWithShorthand(properties, candidateComponents, name, sourceMaps, validator) {
|
||||
var descriptor = compactable[name];
|
||||
var newValuePlaceholder = [[name], [descriptor.defaultValue]];
|
||||
var all;
|
||||
|
||||
var newProperty = wrapSingle(newValuePlaceholder);
|
||||
newProperty.shorthand = true;
|
||||
newProperty.dirty = true;
|
||||
|
||||
populateComponents([newProperty], validator);
|
||||
|
||||
for (var i = 0, l = descriptor.components.length; i < l; i++) {
|
||||
var component = candidateComponents[descriptor.components[i]];
|
||||
var canOverride = compactable[component.name].canOverride;
|
||||
|
||||
if (hasInherit(component))
|
||||
return;
|
||||
|
||||
if (!everyCombination(canOverride, newProperty.components[i], component, validator))
|
||||
return;
|
||||
|
||||
newProperty.components[i] = deepClone(component);
|
||||
newProperty.important = component.important;
|
||||
|
||||
all = component.all;
|
||||
}
|
||||
|
||||
for (var componentName in candidateComponents) {
|
||||
candidateComponents[componentName].unused = true;
|
||||
}
|
||||
|
||||
if (sourceMaps) {
|
||||
var sourceMapping = componentSourceMaps(candidateComponents);
|
||||
if (sourceMapping.length > 0)
|
||||
newValuePlaceholder[0].push(sourceMapping);
|
||||
}
|
||||
|
||||
newProperty.position = all.length;
|
||||
newProperty.all = all;
|
||||
newProperty.all.push(newValuePlaceholder);
|
||||
|
||||
properties.push(newProperty);
|
||||
}
|
||||
|
||||
function invalidateOrCompact(properties, position, candidates, sourceMaps, validator) {
|
||||
var property = properties[position];
|
||||
|
||||
for (var name in candidates) {
|
||||
if (undefined !== property && name == property.name)
|
||||
continue;
|
||||
|
||||
var descriptor = compactable[name];
|
||||
var candidateComponents = candidates[name];
|
||||
if (descriptor.components.length > Object.keys(candidateComponents).length) {
|
||||
delete candidates[name];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mixedImportance(candidateComponents))
|
||||
continue;
|
||||
|
||||
replaceWithShorthand(properties, candidateComponents, name, sourceMaps, validator);
|
||||
}
|
||||
}
|
||||
|
||||
function compactShortands(properties, sourceMaps, validator) {
|
||||
var candidates = {};
|
||||
|
||||
if (properties.length < 3)
|
||||
return;
|
||||
|
||||
for (var i = 0, l = properties.length; i < l; i++) {
|
||||
var property = properties[i];
|
||||
if (property.unused)
|
||||
continue;
|
||||
|
||||
if (property.hack)
|
||||
continue;
|
||||
|
||||
if (property.variable)
|
||||
continue;
|
||||
|
||||
var descriptor = compactable[property.name];
|
||||
if (!descriptor || !descriptor.componentOf)
|
||||
continue;
|
||||
|
||||
if (property.shorthand) {
|
||||
invalidateOrCompact(properties, i, candidates, sourceMaps, validator);
|
||||
} else {
|
||||
var componentOf = descriptor.componentOf;
|
||||
candidates[componentOf] = candidates[componentOf] || {};
|
||||
candidates[componentOf][property.name] = property;
|
||||
}
|
||||
}
|
||||
|
||||
invalidateOrCompact(properties, i, candidates, sourceMaps, validator);
|
||||
}
|
||||
|
||||
module.exports = compactShortands;
|
||||
183
node_modules/jade/node_modules/clean-css/lib/properties/validator.js
generated
vendored
Normal file
183
node_modules/jade/node_modules/clean-css/lib/properties/validator.js
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// Validates various CSS property values
|
||||
|
||||
var split = require('../utils/split');
|
||||
|
||||
var widthKeywords = ['thin', 'thick', 'medium', 'inherit', 'initial'];
|
||||
var allUnits = ['px', '%', 'em', 'in', 'cm', 'mm', 'ex', 'pt', 'pc', 'ch', 'rem', 'vh', 'vm', 'vmin', 'vmax', 'vw'];
|
||||
var cssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + allUnits.join('|') + '|)|auto|inherit)';
|
||||
var cssCalcRegexStr = '(\\-moz\\-|\\-webkit\\-)?calc\\([^\\)]+\\)';
|
||||
var cssFunctionNoVendorRegexStr = '[A-Z]+(\\-|[A-Z]|[0-9])+\\(.*?\\)';
|
||||
var cssFunctionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(.*?\\)';
|
||||
var cssVariableRegexStr = 'var\\(\\-\\-[^\\)]+\\)';
|
||||
var cssFunctionAnyRegexStr = '(' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')';
|
||||
var cssUnitOrCalcRegexStr = '(' + cssUnitRegexStr + '|' + cssCalcRegexStr + ')';
|
||||
var cssUnitAnyRegexStr = '(none|' + widthKeywords.join('|') + '|' + cssUnitRegexStr + '|' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')';
|
||||
|
||||
var cssFunctionNoVendorRegex = new RegExp('^' + cssFunctionNoVendorRegexStr + '$', 'i');
|
||||
var cssFunctionVendorRegex = new RegExp('^' + cssFunctionVendorRegexStr + '$', 'i');
|
||||
var cssVariableRegex = new RegExp('^' + cssVariableRegexStr + '$', 'i');
|
||||
var cssFunctionAnyRegex = new RegExp('^' + cssFunctionAnyRegexStr + '$', 'i');
|
||||
var cssUnitRegex = new RegExp('^' + cssUnitRegexStr + '$', 'i');
|
||||
var cssUnitOrCalcRegex = new RegExp('^' + cssUnitOrCalcRegexStr + '$', 'i');
|
||||
var cssUnitAnyRegex = new RegExp('^' + cssUnitAnyRegexStr + '$', 'i');
|
||||
|
||||
var backgroundRepeatKeywords = ['repeat', 'no-repeat', 'repeat-x', 'repeat-y', 'inherit'];
|
||||
var backgroundAttachmentKeywords = ['inherit', 'scroll', 'fixed', 'local'];
|
||||
var backgroundPositionKeywords = ['center', 'top', 'bottom', 'left', 'right'];
|
||||
var backgroundSizeKeywords = ['contain', 'cover'];
|
||||
var backgroundBoxKeywords = ['border-box', 'content-box', 'padding-box'];
|
||||
var styleKeywords = ['auto', 'inherit', 'hidden', 'none', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'];
|
||||
var listStyleTypeKeywords = ['armenian', 'circle', 'cjk-ideographic', 'decimal', 'decimal-leading-zero', 'disc', 'georgian', 'hebrew', 'hiragana', 'hiragana-iroha', 'inherit', 'katakana', 'katakana-iroha', 'lower-alpha', 'lower-greek', 'lower-latin', 'lower-roman', 'none', 'square', 'upper-alpha', 'upper-latin', 'upper-roman'];
|
||||
var listStylePositionKeywords = ['inside', 'outside', 'inherit'];
|
||||
|
||||
function Validator(compatibility) {
|
||||
var validUnits = allUnits.slice(0).filter(function (value) {
|
||||
return !(value in compatibility.units) || compatibility.units[value] === true;
|
||||
});
|
||||
|
||||
var compatibleCssUnitRegexStr = '(\\-?\\.?\\d+\\.?\\d*(' + validUnits.join('|') + '|)|auto|inherit)';
|
||||
this.compatibleCssUnitRegex = new RegExp('^' + compatibleCssUnitRegexStr + '$', 'i');
|
||||
this.compatibleCssUnitAnyRegex = new RegExp('^(none|' + widthKeywords.join('|') + '|' + compatibleCssUnitRegexStr + '|' + cssVariableRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')$', 'i');
|
||||
}
|
||||
|
||||
Validator.prototype.isValidHexColor = function (s) {
|
||||
return (s.length === 4 || s.length === 7) && s[0] === '#';
|
||||
};
|
||||
|
||||
Validator.prototype.isValidRgbaColor = function (s) {
|
||||
s = s.split(' ').join('');
|
||||
return s.length > 0 && s.indexOf('rgba(') === 0 && s.indexOf(')') === s.length - 1;
|
||||
};
|
||||
|
||||
Validator.prototype.isValidHslaColor = function (s) {
|
||||
s = s.split(' ').join('');
|
||||
return s.length > 0 && s.indexOf('hsla(') === 0 && s.indexOf(')') === s.length - 1;
|
||||
};
|
||||
|
||||
Validator.prototype.isValidNamedColor = function (s) {
|
||||
// We don't really check if it's a valid color value, but allow any letters in it
|
||||
return s !== 'auto' && (s === 'transparent' || s === 'inherit' || /^[a-zA-Z]+$/.test(s));
|
||||
};
|
||||
|
||||
Validator.prototype.isValidVariable = function (s) {
|
||||
return cssVariableRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidColor = function (s) {
|
||||
return this.isValidNamedColor(s) ||
|
||||
this.isValidHexColor(s) ||
|
||||
this.isValidRgbaColor(s) ||
|
||||
this.isValidHslaColor(s) ||
|
||||
this.isValidVariable(s) ||
|
||||
this.isValidVendorPrefixedValue(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidUrl = function (s) {
|
||||
// NOTE: at this point all URLs are replaced with placeholders by clean-css, so we check for those placeholders
|
||||
return s.indexOf('__ESCAPED_URL_CLEAN_CSS') === 0;
|
||||
};
|
||||
|
||||
Validator.prototype.isValidUnit = function (s) {
|
||||
return cssUnitAnyRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidUnitWithoutFunction = function (s) {
|
||||
return cssUnitRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidAndCompatibleUnit = function (s) {
|
||||
return this.compatibleCssUnitAnyRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidAndCompatibleUnitWithoutFunction = function (s) {
|
||||
return this.compatibleCssUnitRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidFunctionWithoutVendorPrefix = function (s) {
|
||||
return cssFunctionNoVendorRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidFunctionWithVendorPrefix = function (s) {
|
||||
return cssFunctionVendorRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidFunction = function (s) {
|
||||
return cssFunctionAnyRegex.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundRepeat = function (s) {
|
||||
return backgroundRepeatKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundAttachment = function (s) {
|
||||
return backgroundAttachmentKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundBox = function (s) {
|
||||
return backgroundBoxKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundPositionPart = function (s) {
|
||||
return backgroundPositionKeywords.indexOf(s) >= 0 || cssUnitOrCalcRegex.test(s) || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundPosition = function (s) {
|
||||
if (s === 'inherit')
|
||||
return true;
|
||||
|
||||
var parts = s.split(' ');
|
||||
for (var i = 0, l = parts.length; i < l; i++) {
|
||||
if (parts[i] === '')
|
||||
continue;
|
||||
if (this.isValidBackgroundPositionPart(parts[i]) || this.isValidVariable(parts[i]))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundSizePart = function (s) {
|
||||
return backgroundSizeKeywords.indexOf(s) >= 0 || cssUnitRegex.test(s) || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidBackgroundPositionAndSize = function (s) {
|
||||
if (s.indexOf('/') < 0)
|
||||
return false;
|
||||
|
||||
var twoParts = split(s, '/');
|
||||
return this.isValidBackgroundSizePart(twoParts.pop()) && this.isValidBackgroundPositionPart(twoParts.pop());
|
||||
};
|
||||
|
||||
Validator.prototype.isValidListStyleType = function (s) {
|
||||
return listStyleTypeKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidListStylePosition = function (s) {
|
||||
return listStylePositionKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidStyle = function (s) {
|
||||
return styleKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidWidth = function (s) {
|
||||
return this.isValidUnit(s) || widthKeywords.indexOf(s) >= 0 || this.isValidVariable(s);
|
||||
};
|
||||
|
||||
Validator.prototype.isValidVendorPrefixedValue = function (s) {
|
||||
return /^-([A-Za-z0-9]|-)*$/gi.test(s);
|
||||
};
|
||||
|
||||
Validator.prototype.areSameFunction = function (a, b) {
|
||||
if (!this.isValidFunction(a) || !this.isValidFunction(b))
|
||||
return false;
|
||||
|
||||
var f1name = a.substring(0, a.indexOf('('));
|
||||
var f2name = b.substring(0, b.indexOf('('));
|
||||
|
||||
return f1name === f2name;
|
||||
};
|
||||
|
||||
module.exports = Validator;
|
||||
26
node_modules/jade/node_modules/clean-css/lib/properties/vendor-prefixes.js
generated
vendored
Normal file
26
node_modules/jade/node_modules/clean-css/lib/properties/vendor-prefixes.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
var VENDOR_PREFIX_PATTERN = /$\-moz\-|\-ms\-|\-o\-|\-webkit\-/;
|
||||
|
||||
function prefixesIn(tokens) {
|
||||
var prefixes = [];
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
for (var j = 0, m = token.value.length; j < m; j++) {
|
||||
var match = VENDOR_PREFIX_PATTERN.exec(token.value[j][0]);
|
||||
|
||||
if (match && prefixes.indexOf(match[0]) == -1)
|
||||
prefixes.push(match[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return prefixes;
|
||||
}
|
||||
|
||||
function same(left, right) {
|
||||
return prefixesIn(left).sort().join(',') == prefixesIn(right).sort().join(',');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
same: same
|
||||
};
|
||||
111
node_modules/jade/node_modules/clean-css/lib/properties/wrap-for-optimizing.js
generated
vendored
Normal file
111
node_modules/jade/node_modules/clean-css/lib/properties/wrap-for-optimizing.js
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
var BACKSLASH_HACK = '\\';
|
||||
var IMPORTANT_TOKEN = '!important';
|
||||
var STAR_HACK = '*';
|
||||
var UNDERSCORE_HACK = '_';
|
||||
var BANG_HACK = '!';
|
||||
|
||||
function wrapAll(properties) {
|
||||
var wrapped = [];
|
||||
|
||||
for (var i = properties.length - 1; i >= 0; i--) {
|
||||
if (typeof properties[i][0] == 'string')
|
||||
continue;
|
||||
|
||||
var single = wrapSingle(properties[i]);
|
||||
single.all = properties;
|
||||
single.position = i;
|
||||
wrapped.unshift(single);
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
function isMultiplex(property) {
|
||||
for (var i = 1, l = property.length; i < l; i++) {
|
||||
if (property[i][0] == ',' || property[i][0] == '/')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function hackType(property) {
|
||||
var type = false;
|
||||
var name = property[0][0];
|
||||
var lastValue = property[property.length - 1];
|
||||
|
||||
if (name[0] == UNDERSCORE_HACK) {
|
||||
type = 'underscore';
|
||||
} else if (name[0] == STAR_HACK) {
|
||||
type = 'star';
|
||||
} else if (lastValue[0][0] == BANG_HACK && lastValue[0].indexOf('important') == -1) {
|
||||
type = 'bang';
|
||||
} else if (lastValue[0].indexOf(BANG_HACK) > 0 && lastValue[0].indexOf('important') == -1) {
|
||||
type = 'bang';
|
||||
} else if (lastValue[0].indexOf(BACKSLASH_HACK) > 0 && lastValue[0].indexOf(BACKSLASH_HACK) == lastValue[0].length - BACKSLASH_HACK.length - 1) {
|
||||
type = 'backslash';
|
||||
} else if (lastValue[0].indexOf(BACKSLASH_HACK) === 0 && lastValue[0].length == 2) {
|
||||
type = 'backslash';
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
function isImportant(property) {
|
||||
return property.length > 1 ?
|
||||
property[property.length - 1][0].indexOf(IMPORTANT_TOKEN) > 0 :
|
||||
false;
|
||||
}
|
||||
|
||||
function stripImportant(property) {
|
||||
if (property.length > 0)
|
||||
property[property.length - 1][0] = property[property.length - 1][0].replace(IMPORTANT_TOKEN, '');
|
||||
}
|
||||
|
||||
function stripPrefixHack(property) {
|
||||
property[0][0] = property[0][0].substring(1);
|
||||
}
|
||||
|
||||
function stripSuffixHack(property, hackType) {
|
||||
var lastValue = property[property.length - 1];
|
||||
lastValue[0] = lastValue[0]
|
||||
.substring(0, lastValue[0].indexOf(hackType == 'backslash' ? BACKSLASH_HACK : BANG_HACK))
|
||||
.trim();
|
||||
|
||||
if (lastValue[0].length === 0)
|
||||
property.pop();
|
||||
}
|
||||
|
||||
function wrapSingle(property) {
|
||||
var _isImportant = isImportant(property);
|
||||
if (_isImportant)
|
||||
stripImportant(property);
|
||||
|
||||
var _hackType = hackType(property);
|
||||
if (_hackType == 'star' || _hackType == 'underscore')
|
||||
stripPrefixHack(property);
|
||||
else if (_hackType == 'backslash' || _hackType == 'bang')
|
||||
stripSuffixHack(property, _hackType);
|
||||
|
||||
var isVariable = property[0][0].indexOf('--') === 0;
|
||||
|
||||
return {
|
||||
block: isVariable && property[1] && Array.isArray(property[1][0][0]),
|
||||
components: [],
|
||||
dirty: false,
|
||||
hack: _hackType,
|
||||
important: _isImportant,
|
||||
name: property[0][0],
|
||||
multiplex: property.length > 2 ? isMultiplex(property) : false,
|
||||
position: 0,
|
||||
shorthand: false,
|
||||
unused: property.length < 2,
|
||||
value: property.slice(1),
|
||||
variable: isVariable
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
all: wrapAll,
|
||||
single: wrapSingle
|
||||
};
|
||||
86
node_modules/jade/node_modules/clean-css/lib/selectors/advanced.js
generated
vendored
Normal file
86
node_modules/jade/node_modules/clean-css/lib/selectors/advanced.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
|
||||
var removeDuplicates = require('./remove-duplicates');
|
||||
var mergeAdjacent = require('./merge-adjacent');
|
||||
var reduceNonAdjacent = require('./reduce-non-adjacent');
|
||||
var mergeNonAdjacentBySelector = require('./merge-non-adjacent-by-selector');
|
||||
var mergeNonAdjacentByBody = require('./merge-non-adjacent-by-body');
|
||||
var restructure = require('./restructure');
|
||||
var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
|
||||
var mergeMediaQueries = require('./merge-media-queries');
|
||||
|
||||
function removeEmpty(tokens) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
var isEmpty = false;
|
||||
|
||||
switch (token[0]) {
|
||||
case 'selector':
|
||||
isEmpty = token[1].length === 0 || token[2].length === 0;
|
||||
break;
|
||||
case 'block':
|
||||
removeEmpty(token[2]);
|
||||
isEmpty = token[2].length === 0;
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recursivelyOptimizeBlocks(tokens, options, validator) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] == 'block') {
|
||||
var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0]);
|
||||
optimize(token[2], options, validator, !isKeyframes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recursivelyOptimizeProperties(tokens, options, validator) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
switch (token[0]) {
|
||||
case 'selector':
|
||||
optimizeProperties(token[1], token[2], false, true, options, validator);
|
||||
break;
|
||||
case 'block':
|
||||
recursivelyOptimizeProperties(token[2], options, validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function optimize(tokens, options, validator, withRestructuring) {
|
||||
recursivelyOptimizeBlocks(tokens, options, validator);
|
||||
recursivelyOptimizeProperties(tokens, options, validator);
|
||||
|
||||
removeDuplicates(tokens);
|
||||
mergeAdjacent(tokens, options, validator);
|
||||
reduceNonAdjacent(tokens, options, validator);
|
||||
|
||||
mergeNonAdjacentBySelector(tokens, options, validator);
|
||||
mergeNonAdjacentByBody(tokens, options);
|
||||
|
||||
if (options.restructuring && withRestructuring) {
|
||||
restructure(tokens, options);
|
||||
mergeAdjacent(tokens, options, validator);
|
||||
}
|
||||
|
||||
if (options.mediaMerging) {
|
||||
removeDuplicateMediaQueries(tokens);
|
||||
var reduced = mergeMediaQueries(tokens);
|
||||
for (var i = reduced.length - 1; i >= 0; i--) {
|
||||
optimize(reduced[i][2], options, validator, false);
|
||||
}
|
||||
}
|
||||
|
||||
removeEmpty(tokens);
|
||||
}
|
||||
|
||||
module.exports = optimize;
|
||||
80
node_modules/jade/node_modules/clean-css/lib/selectors/clean-up.js
generated
vendored
Normal file
80
node_modules/jade/node_modules/clean-css/lib/selectors/clean-up.js
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
function removeWhitespace(match, value) {
|
||||
return '[' + value.replace(/ /g, '') + ']';
|
||||
}
|
||||
|
||||
function selectorSorter(s1, s2) {
|
||||
return s1[0] > s2[0] ? 1 : -1;
|
||||
}
|
||||
|
||||
var CleanUp = {
|
||||
selectors: function (selectors, removeUnsupported, adjacentSpace) {
|
||||
var list = [];
|
||||
var repeated = [];
|
||||
|
||||
for (var i = 0, l = selectors.length; i < l; i++) {
|
||||
var selector = selectors[i];
|
||||
var reduced = selector[0]
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/ ?, ?/g, ',')
|
||||
.replace(/\s*([>\+\~])\s*/g, '$1')
|
||||
.trim();
|
||||
|
||||
if (adjacentSpace && reduced.indexOf('nav') > 0)
|
||||
reduced = reduced.replace(/\+nav(\S|$)/, '+ nav$1');
|
||||
|
||||
if (removeUnsupported && (reduced.indexOf('*+html ') != -1 || reduced.indexOf('*:first-child+html ') != -1))
|
||||
continue;
|
||||
|
||||
if (reduced.indexOf('*') > -1) {
|
||||
reduced = reduced
|
||||
.replace(/\*([:#\.\[])/g, '$1')
|
||||
.replace(/^(\:first\-child)?\+html/, '*$1+html');
|
||||
}
|
||||
|
||||
if (reduced.indexOf('[') > -1)
|
||||
reduced = reduced.replace(/\[([^\]]+)\]/g, removeWhitespace);
|
||||
|
||||
if (repeated.indexOf(reduced) == -1) {
|
||||
selector[0] = reduced;
|
||||
repeated.push(reduced);
|
||||
list.push(selector);
|
||||
}
|
||||
}
|
||||
|
||||
return list.sort(selectorSorter);
|
||||
},
|
||||
|
||||
selectorDuplicates: function (selectors) {
|
||||
var list = [];
|
||||
var repeated = [];
|
||||
|
||||
for (var i = 0, l = selectors.length; i < l; i++) {
|
||||
var selector = selectors[i];
|
||||
|
||||
if (repeated.indexOf(selector[0]) == -1) {
|
||||
repeated.push(selector[0]);
|
||||
list.push(selector);
|
||||
}
|
||||
}
|
||||
|
||||
return list.sort(selectorSorter);
|
||||
},
|
||||
|
||||
block: function (values, spaceAfterClosingBrace) {
|
||||
values[0] = values[0]
|
||||
.replace(/\s+/g, ' ')
|
||||
.replace(/(,|:|\() /g, '$1')
|
||||
.replace(/ \)/g, ')');
|
||||
|
||||
if (!spaceAfterClosingBrace)
|
||||
values[0] = values[0].replace(/\) /g, ')');
|
||||
},
|
||||
|
||||
atRule: function (values) {
|
||||
values[0] = values[0]
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CleanUp;
|
||||
69
node_modules/jade/node_modules/clean-css/lib/selectors/extractor.js
generated
vendored
Normal file
69
node_modules/jade/node_modules/clean-css/lib/selectors/extractor.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// This extractor is used in advanced optimizations
|
||||
// IMPORTANT: Mind Token class and this code is not related!
|
||||
// Properties will be tokenized in one step, see #429
|
||||
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var stringifyValue = require('../stringifier/one-time').value;
|
||||
|
||||
var AT_RULE = 'at-rule';
|
||||
|
||||
function extract(token) {
|
||||
var properties = [];
|
||||
|
||||
if (token[0] == 'selector') {
|
||||
var inSpecificSelector = !/[\.\+>~]/.test(stringifySelectors(token[1]));
|
||||
for (var i = 0, l = token[2].length; i < l; i++) {
|
||||
var property = token[2][i];
|
||||
|
||||
if (property.indexOf('__ESCAPED') === 0)
|
||||
continue;
|
||||
|
||||
if (property[0] == AT_RULE)
|
||||
continue;
|
||||
|
||||
var name = token[2][i][0][0];
|
||||
if (name.length === 0)
|
||||
continue;
|
||||
|
||||
if (name.indexOf('--') === 0)
|
||||
continue;
|
||||
|
||||
var value = stringifyValue(token[2], i);
|
||||
|
||||
properties.push([
|
||||
name,
|
||||
value,
|
||||
findNameRoot(name),
|
||||
token[2][i],
|
||||
name + ':' + value,
|
||||
token[1],
|
||||
inSpecificSelector
|
||||
]);
|
||||
}
|
||||
} else if (token[0] == 'block') {
|
||||
for (var j = 0, k = token[2].length; j < k; j++) {
|
||||
properties = properties.concat(extract(token[2][j]));
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
function findNameRoot(name) {
|
||||
if (name == 'list-style')
|
||||
return name;
|
||||
if (name.indexOf('-radius') > 0)
|
||||
return 'border-radius';
|
||||
if (name == 'border-collapse' || name == 'border-spacing' || name == 'border-image')
|
||||
return name;
|
||||
if (name.indexOf('border-') === 0 && /^border\-\w+\-\w+$/.test(name))
|
||||
return name.match(/border\-\w+/)[0];
|
||||
if (name.indexOf('border-') === 0 && /^border\-\w+$/.test(name))
|
||||
return 'border';
|
||||
if (name.indexOf('text-') === 0)
|
||||
return name;
|
||||
|
||||
return name.replace(/^\-\w+\-/, '').match(/([a-zA-Z]+)/)[0].toLowerCase();
|
||||
}
|
||||
|
||||
module.exports = extract;
|
||||
5
node_modules/jade/node_modules/clean-css/lib/selectors/is-special.js
generated
vendored
Normal file
5
node_modules/jade/node_modules/clean-css/lib/selectors/is-special.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
function isSpecial(options, selector) {
|
||||
return options.compatibility.selectors.special.test(selector);
|
||||
}
|
||||
|
||||
module.exports = isSpecial;
|
||||
35
node_modules/jade/node_modules/clean-css/lib/selectors/merge-adjacent.js
generated
vendored
Normal file
35
node_modules/jade/node_modules/clean-css/lib/selectors/merge-adjacent.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var cleanUpSelectors = require('./clean-up').selectors;
|
||||
var isSpecial = require('./is-special');
|
||||
|
||||
function mergeAdjacent(tokens, options, validator) {
|
||||
var lastToken = [null, [], []];
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != 'selector') {
|
||||
lastToken = [null, [], []];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastToken[0] == 'selector' && stringifySelectors(token[1]) == stringifySelectors(lastToken[1])) {
|
||||
var joinAt = [lastToken[2].length];
|
||||
Array.prototype.push.apply(lastToken[2], token[2]);
|
||||
optimizeProperties(token[1], lastToken[2], joinAt, true, options, validator);
|
||||
token[2] = [];
|
||||
} else if (lastToken[0] == 'selector' && stringifyBody(token[2]) == stringifyBody(lastToken[2]) &&
|
||||
!isSpecial(options, stringifySelectors(token[1])) && !isSpecial(options, stringifySelectors(lastToken[1]))) {
|
||||
lastToken[1] = cleanUpSelectors(lastToken[1].concat(token[1]), false, adjacentSpace);
|
||||
token[2] = [];
|
||||
} else {
|
||||
lastToken = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeAdjacent;
|
||||
64
node_modules/jade/node_modules/clean-css/lib/selectors/merge-media-queries.js
generated
vendored
Normal file
64
node_modules/jade/node_modules/clean-css/lib/selectors/merge-media-queries.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
var canReorder = require('./reorderable').canReorder;
|
||||
var extractProperties = require('./extractor');
|
||||
|
||||
function mergeMediaQueries(tokens) {
|
||||
var candidates = {};
|
||||
var reduced = [];
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != 'block')
|
||||
continue;
|
||||
|
||||
var candidate = candidates[token[1][0]];
|
||||
if (!candidate) {
|
||||
candidate = [];
|
||||
candidates[token[1][0]] = candidate;
|
||||
}
|
||||
|
||||
candidate.push(i);
|
||||
}
|
||||
|
||||
for (var name in candidates) {
|
||||
var positions = candidates[name];
|
||||
|
||||
positionLoop:
|
||||
for (var j = positions.length - 1; j > 0; j--) {
|
||||
var positionOne = positions[j];
|
||||
var tokenOne = tokens[positionOne];
|
||||
var positionTwo = positions[j - 1];
|
||||
var tokenTwo = tokens[positionTwo];
|
||||
|
||||
directionLoop:
|
||||
for (var direction = 1; direction >= -1; direction -= 2) {
|
||||
var topToBottom = direction == 1;
|
||||
var from = topToBottom ? positionOne + 1 : positionTwo - 1;
|
||||
var to = topToBottom ? positionTwo : positionOne;
|
||||
var delta = topToBottom ? 1 : -1;
|
||||
var source = topToBottom ? tokenOne : tokenTwo;
|
||||
var target = topToBottom ? tokenTwo : tokenOne;
|
||||
var movedProperties = extractProperties(source);
|
||||
|
||||
while (from != to) {
|
||||
var traversedProperties = extractProperties(tokens[from]);
|
||||
from += delta;
|
||||
|
||||
if (!canReorder(movedProperties, traversedProperties))
|
||||
continue directionLoop;
|
||||
}
|
||||
|
||||
target[2] = topToBottom ?
|
||||
source[2].concat(target[2]) :
|
||||
target[2].concat(source[2]);
|
||||
source[2] = [];
|
||||
|
||||
reduced.push(target);
|
||||
continue positionLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return reduced;
|
||||
}
|
||||
|
||||
module.exports = mergeMediaQueries;
|
||||
58
node_modules/jade/node_modules/clean-css/lib/selectors/merge-non-adjacent-by-body.js
generated
vendored
Normal file
58
node_modules/jade/node_modules/clean-css/lib/selectors/merge-non-adjacent-by-body.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var cleanUpSelectors = require('./clean-up').selectors;
|
||||
var isSpecial = require('./is-special');
|
||||
|
||||
function unsafeSelector(value) {
|
||||
return /\.|\*| :/.test(value);
|
||||
}
|
||||
|
||||
function isBemElement(token) {
|
||||
var asString = stringifySelectors(token[1]);
|
||||
return asString.indexOf('__') > -1 || asString.indexOf('--') > -1;
|
||||
}
|
||||
|
||||
function withoutModifier(selector) {
|
||||
return selector.replace(/--[^ ,>\+~:]+/g, '');
|
||||
}
|
||||
|
||||
function removeAnyUnsafeElements(left, candidates) {
|
||||
var leftSelector = withoutModifier(stringifySelectors(left[1]));
|
||||
|
||||
for (var body in candidates) {
|
||||
var right = candidates[body];
|
||||
var rightSelector = withoutModifier(stringifySelectors(right[1]));
|
||||
|
||||
if (rightSelector.indexOf(leftSelector) > -1 || leftSelector.indexOf(rightSelector) > -1)
|
||||
delete candidates[body];
|
||||
}
|
||||
}
|
||||
|
||||
function mergeNonAdjacentByBody(tokens, options) {
|
||||
var candidates = {};
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != 'selector')
|
||||
continue;
|
||||
|
||||
if (token[2].length > 0 && (!options.semanticMerging && unsafeSelector(stringifySelectors(token[1]))))
|
||||
candidates = {};
|
||||
|
||||
if (token[2].length > 0 && options.semanticMerging && isBemElement(token))
|
||||
removeAnyUnsafeElements(token, candidates);
|
||||
|
||||
var oldToken = candidates[stringifyBody(token[2])];
|
||||
if (oldToken && !isSpecial(options, stringifySelectors(token[1])) && !isSpecial(options, stringifySelectors(oldToken[1]))) {
|
||||
token[1] = cleanUpSelectors(oldToken[1].concat(token[1]), false, adjacentSpace);
|
||||
|
||||
oldToken[2] = [];
|
||||
candidates[stringifyBody(token[2])] = null;
|
||||
}
|
||||
|
||||
candidates[stringifyBody(token[2])] = token;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeNonAdjacentByBody;
|
||||
76
node_modules/jade/node_modules/clean-css/lib/selectors/merge-non-adjacent-by-selector.js
generated
vendored
Normal file
76
node_modules/jade/node_modules/clean-css/lib/selectors/merge-non-adjacent-by-selector.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var extractProperties = require('./extractor');
|
||||
var canReorder = require('./reorderable').canReorder;
|
||||
|
||||
function mergeNonAdjacentBySelector(tokens, options, validator) {
|
||||
var allSelectors = {};
|
||||
var repeatedSelectors = [];
|
||||
var i;
|
||||
|
||||
for (i = tokens.length - 1; i >= 0; i--) {
|
||||
if (tokens[i][0] != 'selector')
|
||||
continue;
|
||||
if (tokens[i][2].length === 0)
|
||||
continue;
|
||||
|
||||
var selector = stringifySelectors(tokens[i][1]);
|
||||
allSelectors[selector] = [i].concat(allSelectors[selector] || []);
|
||||
|
||||
if (allSelectors[selector].length == 2)
|
||||
repeatedSelectors.push(selector);
|
||||
}
|
||||
|
||||
for (i = repeatedSelectors.length - 1; i >= 0; i--) {
|
||||
var positions = allSelectors[repeatedSelectors[i]];
|
||||
|
||||
selectorIterator:
|
||||
for (var j = positions.length - 1; j > 0; j--) {
|
||||
var positionOne = positions[j - 1];
|
||||
var tokenOne = tokens[positionOne];
|
||||
var positionTwo = positions[j];
|
||||
var tokenTwo = tokens[positionTwo];
|
||||
|
||||
directionIterator:
|
||||
for (var direction = 1; direction >= -1; direction -= 2) {
|
||||
var topToBottom = direction == 1;
|
||||
var from = topToBottom ? positionOne + 1 : positionTwo - 1;
|
||||
var to = topToBottom ? positionTwo : positionOne;
|
||||
var delta = topToBottom ? 1 : -1;
|
||||
var moved = topToBottom ? tokenOne : tokenTwo;
|
||||
var target = topToBottom ? tokenTwo : tokenOne;
|
||||
var movedProperties = extractProperties(moved);
|
||||
var joinAt;
|
||||
|
||||
while (from != to) {
|
||||
var traversedProperties = extractProperties(tokens[from]);
|
||||
from += delta;
|
||||
|
||||
// traversed then moved as we move selectors towards the start
|
||||
var reorderable = topToBottom ?
|
||||
canReorder(movedProperties, traversedProperties) :
|
||||
canReorder(traversedProperties, movedProperties);
|
||||
|
||||
if (!reorderable && !topToBottom)
|
||||
continue selectorIterator;
|
||||
if (!reorderable && topToBottom)
|
||||
continue directionIterator;
|
||||
}
|
||||
|
||||
if (topToBottom) {
|
||||
joinAt = [moved[2].length];
|
||||
Array.prototype.push.apply(moved[2], target[2]);
|
||||
target[2] = moved[2];
|
||||
} else {
|
||||
joinAt = [target[2].length];
|
||||
Array.prototype.push.apply(target[2], moved[2]);
|
||||
}
|
||||
|
||||
optimizeProperties(target[1], target[2], joinAt, true, options, validator);
|
||||
moved[2] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = mergeNonAdjacentBySelector;
|
||||
172
node_modules/jade/node_modules/clean-css/lib/selectors/reduce-non-adjacent.js
generated
vendored
Normal file
172
node_modules/jade/node_modules/clean-css/lib/selectors/reduce-non-adjacent.js
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
var optimizeProperties = require('../properties/optimizer');
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var isSpecial = require('./is-special');
|
||||
var cloneArray = require('../utils/clone-array');
|
||||
|
||||
function reduceNonAdjacent(tokens, options, validator) {
|
||||
var candidates = {};
|
||||
var repeated = [];
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != 'selector')
|
||||
continue;
|
||||
if (token[2].length === 0)
|
||||
continue;
|
||||
|
||||
var selectorAsString = stringifySelectors(token[1]);
|
||||
var isComplexAndNotSpecial = token[1].length > 1 && !isSpecial(options, selectorAsString);
|
||||
var wrappedSelectors = options.sourceMap ? wrappedSelectorsFrom(token[1]) : token[1];
|
||||
var selectors = isComplexAndNotSpecial ?
|
||||
[selectorAsString].concat(wrappedSelectors) :
|
||||
[selectorAsString];
|
||||
|
||||
for (var j = 0, m = selectors.length; j < m; j++) {
|
||||
var selector = selectors[j];
|
||||
|
||||
if (!candidates[selector])
|
||||
candidates[selector] = [];
|
||||
else
|
||||
repeated.push(selector);
|
||||
|
||||
candidates[selector].push({
|
||||
where: i,
|
||||
list: wrappedSelectors,
|
||||
isPartial: isComplexAndNotSpecial && j > 0,
|
||||
isComplex: isComplexAndNotSpecial && j === 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, validator);
|
||||
reduceComplexNonAdjacentCases(tokens, candidates, options, validator);
|
||||
}
|
||||
|
||||
function wrappedSelectorsFrom(list) {
|
||||
var wrapped = [];
|
||||
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
wrapped.push([list[i][0]]);
|
||||
}
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
function reduceSimpleNonAdjacentCases(tokens, repeated, candidates, options, validator) {
|
||||
function filterOut(idx, bodies) {
|
||||
return data[idx].isPartial && bodies.length === 0;
|
||||
}
|
||||
|
||||
function reduceBody(token, newBody, processedCount, tokenIdx) {
|
||||
if (!data[processedCount - tokenIdx - 1].isPartial)
|
||||
token[2] = newBody;
|
||||
}
|
||||
|
||||
for (var i = 0, l = repeated.length; i < l; i++) {
|
||||
var selector = repeated[i];
|
||||
var data = candidates[selector];
|
||||
|
||||
reduceSelector(tokens, selector, data, {
|
||||
filterOut: filterOut,
|
||||
callback: reduceBody
|
||||
}, options, validator);
|
||||
}
|
||||
}
|
||||
|
||||
function reduceComplexNonAdjacentCases(tokens, candidates, options, validator) {
|
||||
var localContext = {};
|
||||
|
||||
function filterOut(idx) {
|
||||
return localContext.data[idx].where < localContext.intoPosition;
|
||||
}
|
||||
|
||||
function collectReducedBodies(token, newBody, processedCount, tokenIdx) {
|
||||
if (tokenIdx === 0)
|
||||
localContext.reducedBodies.push(newBody);
|
||||
}
|
||||
|
||||
allSelectors:
|
||||
for (var complexSelector in candidates) {
|
||||
var into = candidates[complexSelector];
|
||||
if (!into[0].isComplex)
|
||||
continue;
|
||||
|
||||
var intoPosition = into[into.length - 1].where;
|
||||
var intoToken = tokens[intoPosition];
|
||||
var reducedBodies = [];
|
||||
|
||||
var selectors = isSpecial(options, complexSelector) ?
|
||||
[complexSelector] :
|
||||
into[0].list;
|
||||
|
||||
localContext.intoPosition = intoPosition;
|
||||
localContext.reducedBodies = reducedBodies;
|
||||
|
||||
for (var j = 0, m = selectors.length; j < m; j++) {
|
||||
var selector = selectors[j];
|
||||
var data = candidates[selector];
|
||||
|
||||
if (data.length < 2)
|
||||
continue allSelectors;
|
||||
|
||||
localContext.data = data;
|
||||
|
||||
reduceSelector(tokens, selector, data, {
|
||||
filterOut: filterOut,
|
||||
callback: collectReducedBodies
|
||||
}, options, validator);
|
||||
|
||||
if (stringifyBody(reducedBodies[reducedBodies.length - 1]) != stringifyBody(reducedBodies[0]))
|
||||
continue allSelectors;
|
||||
}
|
||||
|
||||
intoToken[2] = reducedBodies[0];
|
||||
}
|
||||
}
|
||||
|
||||
function reduceSelector(tokens, selector, data, context, options, validator) {
|
||||
var bodies = [];
|
||||
var bodiesAsList = [];
|
||||
var joinsAt = [];
|
||||
var processedTokens = [];
|
||||
|
||||
for (var j = data.length - 1, m = 0; j >= 0; j--) {
|
||||
if (context.filterOut(j, bodies))
|
||||
continue;
|
||||
|
||||
var where = data[j].where;
|
||||
var token = tokens[where];
|
||||
var clonedBody = cloneArray(token[2]);
|
||||
|
||||
bodies = bodies.concat(clonedBody);
|
||||
bodiesAsList.push(clonedBody);
|
||||
processedTokens.push(where);
|
||||
}
|
||||
|
||||
for (j = 0, m = bodiesAsList.length; j < m; j++) {
|
||||
if (bodiesAsList[j].length > 0)
|
||||
joinsAt.push((joinsAt[j - 1] || 0) + bodiesAsList[j].length);
|
||||
}
|
||||
|
||||
optimizeProperties(selector, bodies, joinsAt, false, options, validator);
|
||||
|
||||
var processedCount = processedTokens.length;
|
||||
var propertyIdx = bodies.length - 1;
|
||||
var tokenIdx = processedCount - 1;
|
||||
|
||||
while (tokenIdx >= 0) {
|
||||
if ((tokenIdx === 0 || (bodies[propertyIdx] && bodiesAsList[tokenIdx].indexOf(bodies[propertyIdx]) > -1)) && propertyIdx > -1) {
|
||||
propertyIdx--;
|
||||
continue;
|
||||
}
|
||||
|
||||
var newBody = bodies.splice(propertyIdx + 1);
|
||||
context.callback(tokens[processedTokens[tokenIdx]], newBody, processedCount, tokenIdx);
|
||||
|
||||
tokenIdx--;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = reduceNonAdjacent;
|
||||
21
node_modules/jade/node_modules/clean-css/lib/selectors/remove-duplicate-media-queries.js
generated
vendored
Normal file
21
node_modules/jade/node_modules/clean-css/lib/selectors/remove-duplicate-media-queries.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
var stringifyAll = require('../stringifier/one-time').all;
|
||||
|
||||
function removeDuplicateMediaQueries(tokens) {
|
||||
var candidates = {};
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
if (token[0] != 'block')
|
||||
continue;
|
||||
|
||||
var key = token[1][0] + '%' + stringifyAll(token[2]);
|
||||
var candidate = candidates[key];
|
||||
|
||||
if (candidate)
|
||||
candidate[2] = [];
|
||||
|
||||
candidates[key] = token;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeDuplicateMediaQueries;
|
||||
41
node_modules/jade/node_modules/clean-css/lib/selectors/remove-duplicates.js
generated
vendored
Normal file
41
node_modules/jade/node_modules/clean-css/lib/selectors/remove-duplicates.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
|
||||
function removeDuplicates(tokens) {
|
||||
var matched = {};
|
||||
var moreThanOnce = [];
|
||||
var id, token;
|
||||
var body, bodies;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
token = tokens[i];
|
||||
if (token[0] != 'selector')
|
||||
continue;
|
||||
|
||||
id = stringifySelectors(token[1]);
|
||||
|
||||
if (matched[id] && matched[id].length == 1)
|
||||
moreThanOnce.push(id);
|
||||
else
|
||||
matched[id] = matched[id] || [];
|
||||
|
||||
matched[id].push(i);
|
||||
}
|
||||
|
||||
for (i = 0, l = moreThanOnce.length; i < l; i++) {
|
||||
id = moreThanOnce[i];
|
||||
bodies = [];
|
||||
|
||||
for (var j = matched[id].length - 1; j >= 0; j--) {
|
||||
token = tokens[matched[id][j]];
|
||||
body = stringifyBody(token[2]);
|
||||
|
||||
if (bodies.indexOf(body) > -1)
|
||||
token[2] = [];
|
||||
else
|
||||
bodies.push(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = removeDuplicates;
|
||||
89
node_modules/jade/node_modules/clean-css/lib/selectors/reorderable.js
generated
vendored
Normal file
89
node_modules/jade/node_modules/clean-css/lib/selectors/reorderable.js
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
// TODO: it'd be great to merge it with the other canReorder functionality
|
||||
|
||||
var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/;
|
||||
var BORDER_PROPERTIES = /^border\-(top|right|bottom|left|color|style|width|radius)/;
|
||||
|
||||
function canReorder(left, right) {
|
||||
for (var i = right.length - 1; i >= 0; i--) {
|
||||
for (var j = left.length - 1; j >= 0; j--) {
|
||||
if (!canReorderSingle(left[j], right[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function canReorderSingle(left, right) {
|
||||
var leftName = left[0];
|
||||
var leftValue = left[1];
|
||||
var leftNameRoot = left[2];
|
||||
var leftSelector = left[5];
|
||||
var leftInSpecificSelector = left[6];
|
||||
var rightName = right[0];
|
||||
var rightValue = right[1];
|
||||
var rightNameRoot = right[2];
|
||||
var rightSelector = right[5];
|
||||
var rightInSpecificSelector = right[6];
|
||||
|
||||
if (leftName == 'font' && rightName == 'line-height' || rightName == 'font' && leftName == 'line-height')
|
||||
return false;
|
||||
if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName))
|
||||
return false;
|
||||
if (leftNameRoot == rightNameRoot && unprefixed(leftName) == unprefixed(rightName) && (vendorPrefixed(leftName) ^ vendorPrefixed(rightName)))
|
||||
return false;
|
||||
if (leftNameRoot == 'border' && BORDER_PROPERTIES.test(rightNameRoot) && (leftName == 'border' || leftName == rightNameRoot))
|
||||
return false;
|
||||
if (rightNameRoot == 'border' && BORDER_PROPERTIES.test(leftNameRoot) && (rightName == 'border' || rightName == leftNameRoot))
|
||||
return false;
|
||||
if (leftNameRoot == 'border' && rightNameRoot == 'border' && leftName != rightName && (isSideBorder(leftName) && isStyleBorder(rightName) || isStyleBorder(leftName) && isSideBorder(rightName)))
|
||||
return false;
|
||||
if (leftNameRoot != rightNameRoot)
|
||||
return true;
|
||||
if (leftName == rightName && leftNameRoot == rightNameRoot && (leftValue == rightValue || withDifferentVendorPrefix(leftValue, rightValue)))
|
||||
return true;
|
||||
if (leftName != rightName && leftNameRoot == rightNameRoot && leftName != leftNameRoot && rightName != rightNameRoot)
|
||||
return true;
|
||||
if (leftName != rightName && leftNameRoot == rightNameRoot && leftValue == rightValue)
|
||||
return true;
|
||||
if (rightInSpecificSelector && leftInSpecificSelector && selectorsDoNotOverlap(rightSelector, leftSelector))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function vendorPrefixed(name) {
|
||||
return /^\-(?:moz|webkit|ms|o)\-/.test(name);
|
||||
}
|
||||
|
||||
function unprefixed(name) {
|
||||
return name.replace(/^\-(?:moz|webkit|ms|o)\-/, '');
|
||||
}
|
||||
|
||||
function isSideBorder(name) {
|
||||
return name == 'border-top' || name == 'border-right' || name == 'border-bottom' || name == 'border-left';
|
||||
}
|
||||
|
||||
function isStyleBorder(name) {
|
||||
return name == 'border-color' || name == 'border-style' || name == 'border-width';
|
||||
}
|
||||
|
||||
function withDifferentVendorPrefix(value1, value2) {
|
||||
return vendorPrefixed(value1) && vendorPrefixed(value2) && value1.split('-')[1] != value2.split('-')[2];
|
||||
}
|
||||
|
||||
function selectorsDoNotOverlap(s1, s2) {
|
||||
for (var i = 0, l = s1.length; i < l; i++) {
|
||||
for (var j = 0, m = s2.length; j < m; j++) {
|
||||
if (s1[i][0] == s2[j][0])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
canReorder: canReorder,
|
||||
canReorderSingle: canReorderSingle
|
||||
};
|
||||
352
node_modules/jade/node_modules/clean-css/lib/selectors/restructure.js
generated
vendored
Normal file
352
node_modules/jade/node_modules/clean-css/lib/selectors/restructure.js
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
var extractProperties = require('./extractor');
|
||||
var canReorderSingle = require('./reorderable').canReorderSingle;
|
||||
var stringifyBody = require('../stringifier/one-time').body;
|
||||
var stringifySelectors = require('../stringifier/one-time').selectors;
|
||||
var cleanUpSelectorDuplicates = require('./clean-up').selectorDuplicates;
|
||||
var isSpecial = require('./is-special');
|
||||
|
||||
function naturalSorter(a, b) {
|
||||
return a > b;
|
||||
}
|
||||
|
||||
function restructure(tokens, options) {
|
||||
var movableTokens = {};
|
||||
var movedProperties = [];
|
||||
var multiPropertyMoveCache = {};
|
||||
var movedToBeDropped = [];
|
||||
var maxCombinationsLevel = 2;
|
||||
var ID_JOIN_CHARACTER = '%';
|
||||
|
||||
function sendToMultiPropertyMoveCache(position, movedProperty, allFits) {
|
||||
for (var i = allFits.length - 1; i >= 0; i--) {
|
||||
var fit = allFits[i][0];
|
||||
var id = addToCache(movedProperty, fit);
|
||||
|
||||
if (multiPropertyMoveCache[id].length > 1 && processMultiPropertyMove(position, multiPropertyMoveCache[id])) {
|
||||
removeAllMatchingFromCache(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addToCache(movedProperty, fit) {
|
||||
var id = cacheId(fit);
|
||||
multiPropertyMoveCache[id] = multiPropertyMoveCache[id] || [];
|
||||
multiPropertyMoveCache[id].push([movedProperty, fit]);
|
||||
return id;
|
||||
}
|
||||
|
||||
function removeAllMatchingFromCache(matchId) {
|
||||
var matchSelectors = matchId.split(ID_JOIN_CHARACTER);
|
||||
var forRemoval = [];
|
||||
var i;
|
||||
|
||||
for (var id in multiPropertyMoveCache) {
|
||||
var selectors = id.split(ID_JOIN_CHARACTER);
|
||||
for (i = selectors.length - 1; i >= 0; i--) {
|
||||
if (matchSelectors.indexOf(selectors[i]) > -1) {
|
||||
forRemoval.push(id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = forRemoval.length - 1; i >= 0; i--) {
|
||||
delete multiPropertyMoveCache[forRemoval[i]];
|
||||
}
|
||||
}
|
||||
|
||||
function cacheId(cachedTokens) {
|
||||
var id = [];
|
||||
for (var i = 0, l = cachedTokens.length; i < l; i++) {
|
||||
id.push(stringifySelectors(cachedTokens[i][1]));
|
||||
}
|
||||
return id.join(ID_JOIN_CHARACTER);
|
||||
}
|
||||
|
||||
function tokensToMerge(sourceTokens) {
|
||||
var uniqueTokensWithBody = [];
|
||||
var mergeableTokens = [];
|
||||
|
||||
for (var i = sourceTokens.length - 1; i >= 0; i--) {
|
||||
if (isSpecial(options, stringifySelectors(sourceTokens[i][1])))
|
||||
continue;
|
||||
|
||||
mergeableTokens.unshift(sourceTokens[i]);
|
||||
if (sourceTokens[i][2].length > 0 && uniqueTokensWithBody.indexOf(sourceTokens[i]) == -1)
|
||||
uniqueTokensWithBody.push(sourceTokens[i]);
|
||||
}
|
||||
|
||||
return uniqueTokensWithBody.length > 1 ?
|
||||
mergeableTokens :
|
||||
[];
|
||||
}
|
||||
|
||||
function shortenIfPossible(position, movedProperty) {
|
||||
var name = movedProperty[0];
|
||||
var value = movedProperty[1];
|
||||
var key = movedProperty[4];
|
||||
var valueSize = name.length + value.length + 1;
|
||||
var allSelectors = [];
|
||||
var qualifiedTokens = [];
|
||||
|
||||
var mergeableTokens = tokensToMerge(movableTokens[key]);
|
||||
if (mergeableTokens.length < 2)
|
||||
return;
|
||||
|
||||
var allFits = findAllFits(mergeableTokens, valueSize, 1);
|
||||
var bestFit = allFits[0];
|
||||
if (bestFit[1] > 0)
|
||||
return sendToMultiPropertyMoveCache(position, movedProperty, allFits);
|
||||
|
||||
for (var i = bestFit[0].length - 1; i >=0; i--) {
|
||||
allSelectors = bestFit[0][i][1].concat(allSelectors);
|
||||
qualifiedTokens.unshift(bestFit[0][i]);
|
||||
}
|
||||
|
||||
allSelectors = cleanUpSelectorDuplicates(allSelectors);
|
||||
dropAsNewTokenAt(position, [movedProperty], allSelectors, qualifiedTokens);
|
||||
}
|
||||
|
||||
function fitSorter(fit1, fit2) {
|
||||
return fit1[1] > fit2[1];
|
||||
}
|
||||
|
||||
function findAllFits(mergeableTokens, propertySize, propertiesCount) {
|
||||
var combinations = allCombinations(mergeableTokens, propertySize, propertiesCount, maxCombinationsLevel - 1);
|
||||
return combinations.sort(fitSorter);
|
||||
}
|
||||
|
||||
function allCombinations(tokensVariant, propertySize, propertiesCount, level) {
|
||||
var differenceVariants = [[tokensVariant, sizeDifference(tokensVariant, propertySize, propertiesCount)]];
|
||||
if (tokensVariant.length > 2 && level > 0) {
|
||||
for (var i = tokensVariant.length - 1; i >= 0; i--) {
|
||||
var subVariant = Array.prototype.slice.call(tokensVariant, 0);
|
||||
subVariant.splice(i, 1);
|
||||
differenceVariants = differenceVariants.concat(allCombinations(subVariant, propertySize, propertiesCount, level - 1));
|
||||
}
|
||||
}
|
||||
|
||||
return differenceVariants;
|
||||
}
|
||||
|
||||
function sizeDifference(tokensVariant, propertySize, propertiesCount) {
|
||||
var allSelectorsSize = 0;
|
||||
for (var i = tokensVariant.length - 1; i >= 0; i--) {
|
||||
allSelectorsSize += tokensVariant[i][2].length > propertiesCount ? stringifySelectors(tokensVariant[i][1]).length : -1;
|
||||
}
|
||||
return allSelectorsSize - (tokensVariant.length - 1) * propertySize + 1;
|
||||
}
|
||||
|
||||
function dropAsNewTokenAt(position, properties, allSelectors, mergeableTokens) {
|
||||
var i, j, k, m;
|
||||
var allProperties = [];
|
||||
|
||||
for (i = mergeableTokens.length - 1; i >= 0; i--) {
|
||||
var mergeableToken = mergeableTokens[i];
|
||||
|
||||
for (j = mergeableToken[2].length - 1; j >= 0; j--) {
|
||||
var mergeableProperty = mergeableToken[2][j];
|
||||
|
||||
for (k = 0, m = properties.length; k < m; k++) {
|
||||
var property = properties[k];
|
||||
|
||||
var mergeablePropertyName = mergeableProperty[0][0];
|
||||
var propertyName = property[0];
|
||||
var propertyBody = property[4];
|
||||
if (mergeablePropertyName == propertyName && stringifyBody([mergeableProperty]) == propertyBody) {
|
||||
mergeableToken[2].splice(j, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
allProperties.unshift(properties[i][3]);
|
||||
}
|
||||
|
||||
var newToken = ['selector', allSelectors, allProperties];
|
||||
tokens.splice(position, 0, newToken);
|
||||
}
|
||||
|
||||
function dropPropertiesAt(position, movedProperty) {
|
||||
var key = movedProperty[4];
|
||||
var toMove = movableTokens[key];
|
||||
|
||||
if (toMove && toMove.length > 1) {
|
||||
if (!shortenMultiMovesIfPossible(position, movedProperty))
|
||||
shortenIfPossible(position, movedProperty);
|
||||
}
|
||||
}
|
||||
|
||||
function shortenMultiMovesIfPossible(position, movedProperty) {
|
||||
var candidates = [];
|
||||
var propertiesAndMergableTokens = [];
|
||||
var key = movedProperty[4];
|
||||
var j, k;
|
||||
|
||||
var mergeableTokens = tokensToMerge(movableTokens[key]);
|
||||
if (mergeableTokens.length < 2)
|
||||
return;
|
||||
|
||||
movableLoop:
|
||||
for (var value in movableTokens) {
|
||||
var tokensList = movableTokens[value];
|
||||
|
||||
for (j = mergeableTokens.length - 1; j >= 0; j--) {
|
||||
if (tokensList.indexOf(mergeableTokens[j]) == -1)
|
||||
continue movableLoop;
|
||||
}
|
||||
|
||||
candidates.push(value);
|
||||
}
|
||||
|
||||
if (candidates.length < 2)
|
||||
return false;
|
||||
|
||||
for (j = candidates.length - 1; j >= 0; j--) {
|
||||
for (k = movedProperties.length - 1; k >= 0; k--) {
|
||||
if (movedProperties[k][4] == candidates[j]) {
|
||||
propertiesAndMergableTokens.unshift([movedProperties[k], mergeableTokens]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return processMultiPropertyMove(position, propertiesAndMergableTokens);
|
||||
}
|
||||
|
||||
function processMultiPropertyMove(position, propertiesAndMergableTokens) {
|
||||
var valueSize = 0;
|
||||
var properties = [];
|
||||
var property;
|
||||
|
||||
for (var i = propertiesAndMergableTokens.length - 1; i >= 0; i--) {
|
||||
property = propertiesAndMergableTokens[i][0];
|
||||
var fullValue = property[4];
|
||||
valueSize += fullValue.length + (i > 0 ? 1 : 0);
|
||||
|
||||
properties.push(property);
|
||||
}
|
||||
|
||||
var mergeableTokens = propertiesAndMergableTokens[0][1];
|
||||
var bestFit = findAllFits(mergeableTokens, valueSize, properties.length)[0];
|
||||
if (bestFit[1] > 0)
|
||||
return false;
|
||||
|
||||
var allSelectors = [];
|
||||
var qualifiedTokens = [];
|
||||
for (i = bestFit[0].length - 1; i >= 0; i--) {
|
||||
allSelectors = bestFit[0][i][1].concat(allSelectors);
|
||||
qualifiedTokens.unshift(bestFit[0][i]);
|
||||
}
|
||||
|
||||
allSelectors = cleanUpSelectorDuplicates(allSelectors);
|
||||
dropAsNewTokenAt(position, properties, allSelectors, qualifiedTokens);
|
||||
|
||||
for (i = properties.length - 1; i >= 0; i--) {
|
||||
property = properties[i];
|
||||
var index = movedProperties.indexOf(property);
|
||||
|
||||
delete movableTokens[property[4]];
|
||||
|
||||
if (index > -1 && movedToBeDropped.indexOf(index) == -1)
|
||||
movedToBeDropped.push(index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function boundToAnotherPropertyInCurrrentToken(property, movedProperty, token) {
|
||||
var propertyName = property[0];
|
||||
var movedPropertyName = movedProperty[0];
|
||||
if (propertyName != movedPropertyName)
|
||||
return false;
|
||||
|
||||
var key = movedProperty[4];
|
||||
var toMove = movableTokens[key];
|
||||
return toMove && toMove.indexOf(token) > -1;
|
||||
}
|
||||
|
||||
for (var i = tokens.length - 1; i >= 0; i--) {
|
||||
var token = tokens[i];
|
||||
var isSelector;
|
||||
var j, k, m;
|
||||
|
||||
if (token[0] == 'selector') {
|
||||
isSelector = true;
|
||||
} else if (token[0] == 'block') {
|
||||
isSelector = false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We cache movedProperties.length as it may change in the loop
|
||||
var movedCount = movedProperties.length;
|
||||
|
||||
var properties = extractProperties(token);
|
||||
movedToBeDropped = [];
|
||||
|
||||
var unmovableInCurrentToken = [];
|
||||
for (j = properties.length - 1; j >= 0; j--) {
|
||||
for (k = j - 1; k >= 0; k--) {
|
||||
if (!canReorderSingle(properties[j], properties[k])) {
|
||||
unmovableInCurrentToken.push(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (j = properties.length - 1; j >= 0; j--) {
|
||||
var property = properties[j];
|
||||
var movedSameProperty = false;
|
||||
|
||||
for (k = 0; k < movedCount; k++) {
|
||||
var movedProperty = movedProperties[k];
|
||||
|
||||
if (movedToBeDropped.indexOf(k) == -1 && !canReorderSingle(property, movedProperty) && !boundToAnotherPropertyInCurrrentToken(property, movedProperty, token)) {
|
||||
dropPropertiesAt(i + 1, movedProperty, token);
|
||||
|
||||
if (movedToBeDropped.indexOf(k) == -1) {
|
||||
movedToBeDropped.push(k);
|
||||
delete movableTokens[movedProperty[4]];
|
||||
}
|
||||
}
|
||||
|
||||
if (!movedSameProperty)
|
||||
movedSameProperty = property[0] == movedProperty[0] && property[1] == movedProperty[1];
|
||||
}
|
||||
|
||||
if (!isSelector || unmovableInCurrentToken.indexOf(j) > -1)
|
||||
continue;
|
||||
|
||||
var key = property[4];
|
||||
movableTokens[key] = movableTokens[key] || [];
|
||||
movableTokens[key].push(token);
|
||||
|
||||
if (!movedSameProperty)
|
||||
movedProperties.push(property);
|
||||
}
|
||||
|
||||
movedToBeDropped = movedToBeDropped.sort(naturalSorter);
|
||||
for (j = 0, m = movedToBeDropped.length; j < m; j++) {
|
||||
var dropAt = movedToBeDropped[j] - j;
|
||||
movedProperties.splice(dropAt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
var position = tokens[0] && tokens[0][0] == 'at-rule' && tokens[0][1][0].indexOf('@charset') === 0 ? 1 : 0;
|
||||
for (; position < tokens.length - 1; position++) {
|
||||
var isImportRule = tokens[position][0] === 'at-rule' && tokens[position][1][0].indexOf('@import') === 0;
|
||||
var isEscapedCommentSpecial = tokens[position][0] === 'text' && tokens[position][1][0].indexOf('__ESCAPED_COMMENT_SPECIAL') === 0;
|
||||
if (!(isImportRule || isEscapedCommentSpecial))
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < movedProperties.length; i++) {
|
||||
dropPropertiesAt(position, movedProperties[i]);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = restructure;
|
||||
444
node_modules/jade/node_modules/clean-css/lib/selectors/simple.js
generated
vendored
Normal file
444
node_modules/jade/node_modules/clean-css/lib/selectors/simple.js
generated
vendored
Normal file
@@ -0,0 +1,444 @@
|
||||
var cleanUpSelectors = require('./clean-up').selectors;
|
||||
var cleanUpBlock = require('./clean-up').block;
|
||||
var cleanUpAtRule = require('./clean-up').atRule;
|
||||
var split = require('../utils/split');
|
||||
|
||||
var RGB = require('../colors/rgb');
|
||||
var HSL = require('../colors/hsl');
|
||||
var HexNameShortener = require('../colors/hex-name-shortener');
|
||||
|
||||
var wrapForOptimizing = require('../properties/wrap-for-optimizing').all;
|
||||
var restoreFromOptimizing = require('../properties/restore-from-optimizing');
|
||||
var removeUnused = require('../properties/remove-unused');
|
||||
|
||||
var DEFAULT_ROUNDING_PRECISION = 2;
|
||||
var CHARSET_TOKEN = '@charset';
|
||||
var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');
|
||||
|
||||
var FONT_NUMERAL_WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];
|
||||
var FONT_NAME_WEIGHTS = ['normal', 'bold', 'bolder', 'lighter'];
|
||||
var FONT_NAME_WEIGHTS_WITHOUT_NORMAL = ['bold', 'bolder', 'lighter'];
|
||||
|
||||
var WHOLE_PIXEL_VALUE = /(?:^|\s|\()(-?\d+)px/;
|
||||
var TIME_VALUE = /^(\-?[\d\.]+)(m?s)$/;
|
||||
|
||||
var valueMinifiers = {
|
||||
'background': function (value, index, total) {
|
||||
return index === 0 && total == 1 && (value == 'none' || value == 'transparent') ? '0 0' : value;
|
||||
},
|
||||
'font-weight': function (value) {
|
||||
if (value == 'normal')
|
||||
return '400';
|
||||
else if (value == 'bold')
|
||||
return '700';
|
||||
else
|
||||
return value;
|
||||
},
|
||||
'outline': function (value, index, total) {
|
||||
return index === 0 && total == 1 && value == 'none' ? '0' : value;
|
||||
}
|
||||
};
|
||||
|
||||
function isNegative(property, idx) {
|
||||
return property.value[idx] && property.value[idx][0][0] == '-' && parseFloat(property.value[idx][0]) < 0;
|
||||
}
|
||||
|
||||
function zeroMinifier(name, value) {
|
||||
if (value.indexOf('0') == -1)
|
||||
return value;
|
||||
|
||||
if (value.indexOf('-') > -1) {
|
||||
value = value
|
||||
.replace(/([^\w\d\-]|^)\-0([^\.]|$)/g, '$10$2')
|
||||
.replace(/([^\w\d\-]|^)\-0([^\.]|$)/g, '$10$2');
|
||||
}
|
||||
|
||||
return value
|
||||
.replace(/(^|\s)0+([1-9])/g, '$1$2')
|
||||
.replace(/(^|\D)\.0+(\D|$)/g, '$10$2')
|
||||
.replace(/(^|\D)\.0+(\D|$)/g, '$10$2')
|
||||
.replace(/\.([1-9]*)0+(\D|$)/g, function (match, nonZeroPart, suffix) {
|
||||
return (nonZeroPart.length > 0 ? '.' : '') + nonZeroPart + suffix;
|
||||
})
|
||||
.replace(/(^|\D)0\.(\d)/g, '$1.$2');
|
||||
}
|
||||
|
||||
function zeroDegMinifier(_, value) {
|
||||
if (value.indexOf('0deg') == -1)
|
||||
return value;
|
||||
|
||||
return value.replace(/\(0deg\)/g, '(0)');
|
||||
}
|
||||
|
||||
function whitespaceMinifier(name, value) {
|
||||
if (name.indexOf('filter') > -1 || value.indexOf(' ') == -1)
|
||||
return value;
|
||||
|
||||
value = value.replace(/\s+/g, ' ');
|
||||
|
||||
if (value.indexOf('calc') > -1)
|
||||
value = value.replace(/\) ?\/ ?/g, ')/ ');
|
||||
|
||||
return value
|
||||
.replace(/\( /g, '(')
|
||||
.replace(/ \)/g, ')')
|
||||
.replace(/, /g, ',');
|
||||
}
|
||||
|
||||
function precisionMinifier(_, value, precisionOptions) {
|
||||
if (precisionOptions.value === -1 || value.indexOf('.') === -1)
|
||||
return value;
|
||||
|
||||
return value
|
||||
.replace(precisionOptions.regexp, function (match, number) {
|
||||
return Math.round(parseFloat(number) * precisionOptions.multiplier) / precisionOptions.multiplier + 'px';
|
||||
})
|
||||
.replace(/(\d)\.($|\D)/g, '$1$2');
|
||||
}
|
||||
|
||||
function unitMinifier(name, value, unitsRegexp) {
|
||||
if (/^(?:\-moz\-calc|\-webkit\-calc|calc)\(/.test(value))
|
||||
return value;
|
||||
|
||||
if (name == 'flex' || name == '-ms-flex' || name == '-webkit-flex' || name == 'flex-basis' || name == '-webkit-flex-basis')
|
||||
return value;
|
||||
|
||||
if (value.indexOf('%') > 0 && (name == 'height' || name == 'max-height'))
|
||||
return value;
|
||||
|
||||
return value
|
||||
.replace(unitsRegexp, '$1' + '0' + '$2')
|
||||
.replace(unitsRegexp, '$1' + '0' + '$2');
|
||||
}
|
||||
|
||||
function multipleZerosMinifier(property) {
|
||||
var values = property.value;
|
||||
var spliceAt;
|
||||
|
||||
if (values.length == 4 && values[0][0] === '0' && values[1][0] === '0' && values[2][0] === '0' && values[3][0] === '0') {
|
||||
if (property.name.indexOf('box-shadow') > -1)
|
||||
spliceAt = 2;
|
||||
else
|
||||
spliceAt = 1;
|
||||
}
|
||||
|
||||
if (spliceAt) {
|
||||
property.value.splice(spliceAt);
|
||||
property.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function colorMininifier(_, value, compatibility) {
|
||||
if (value.indexOf('#') === -1 && value.indexOf('rgb') == -1 && value.indexOf('hsl') == -1)
|
||||
return HexNameShortener.shorten(value);
|
||||
|
||||
value = value
|
||||
.replace(/rgb\((\-?\d+),(\-?\d+),(\-?\d+)\)/g, function (match, red, green, blue) {
|
||||
return new RGB(red, green, blue).toHex();
|
||||
})
|
||||
.replace(/hsl\((-?\d+),(-?\d+)%?,(-?\d+)%?\)/g, function (match, hue, saturation, lightness) {
|
||||
return new HSL(hue, saturation, lightness).toHex();
|
||||
})
|
||||
.replace(/(^|[^='"])#([0-9a-f]{6})/gi, function (match, prefix, color) {
|
||||
if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5])
|
||||
return prefix + '#' + color[0] + color[2] + color[4];
|
||||
else
|
||||
return prefix + '#' + color;
|
||||
})
|
||||
.replace(/(rgb|rgba|hsl|hsla)\(([^\)]+)\)/g, function (match, colorFunction, colorDef) {
|
||||
var tokens = colorDef.split(',');
|
||||
var applies = (colorFunction == 'hsl' && tokens.length == 3) ||
|
||||
(colorFunction == 'hsla' && tokens.length == 4) ||
|
||||
(colorFunction == 'rgb' && tokens.length == 3 && colorDef.indexOf('%') > 0) ||
|
||||
(colorFunction == 'rgba' && tokens.length == 4 && colorDef.indexOf('%') > 0);
|
||||
if (!applies)
|
||||
return match;
|
||||
|
||||
if (tokens[1].indexOf('%') == -1)
|
||||
tokens[1] += '%';
|
||||
if (tokens[2].indexOf('%') == -1)
|
||||
tokens[2] += '%';
|
||||
return colorFunction + '(' + tokens.join(',') + ')';
|
||||
});
|
||||
|
||||
if (compatibility.colors.opacity) {
|
||||
value = value.replace(/(?:rgba|hsla)\(0,0%?,0%?,0\)/g, function (match) {
|
||||
if (split(value, ',').pop().indexOf('gradient(') > -1)
|
||||
return match;
|
||||
|
||||
return 'transparent';
|
||||
});
|
||||
}
|
||||
|
||||
return HexNameShortener.shorten(value);
|
||||
}
|
||||
|
||||
function pixelLengthMinifier(_, value, compatibility) {
|
||||
if (!WHOLE_PIXEL_VALUE.test(value))
|
||||
return value;
|
||||
|
||||
return value.replace(WHOLE_PIXEL_VALUE, function (match, val) {
|
||||
var newValue;
|
||||
var intVal = parseInt(val);
|
||||
|
||||
if (intVal === 0)
|
||||
return match;
|
||||
|
||||
if (compatibility.properties.shorterLengthUnits && compatibility.units.pt && intVal * 3 % 4 === 0)
|
||||
newValue = intVal * 3 / 4 + 'pt';
|
||||
|
||||
if (compatibility.properties.shorterLengthUnits && compatibility.units.pc && intVal % 16 === 0)
|
||||
newValue = intVal / 16 + 'pc';
|
||||
|
||||
if (compatibility.properties.shorterLengthUnits && compatibility.units.in && intVal % 96 === 0)
|
||||
newValue = intVal / 96 + 'in';
|
||||
|
||||
if (newValue)
|
||||
newValue = match.substring(0, match.indexOf(val)) + newValue;
|
||||
|
||||
return newValue && newValue.length < match.length ? newValue : match;
|
||||
});
|
||||
}
|
||||
|
||||
function timeUnitMinifier(_, value) {
|
||||
if (!TIME_VALUE.test(value))
|
||||
return value;
|
||||
|
||||
return value.replace(TIME_VALUE, function (match, val, unit) {
|
||||
var newValue;
|
||||
|
||||
if (unit == 'ms') {
|
||||
newValue = parseInt(val) / 1000 + 's';
|
||||
} else if (unit == 's') {
|
||||
newValue = parseFloat(val) * 1000 + 'ms';
|
||||
}
|
||||
|
||||
return newValue.length < match.length ? newValue : match;
|
||||
});
|
||||
}
|
||||
|
||||
function minifyBorderRadius(property) {
|
||||
var values = property.value;
|
||||
var spliceAt;
|
||||
|
||||
if (values.length == 3 && values[1][0] == '/' && values[0][0] == values[2][0])
|
||||
spliceAt = 1;
|
||||
else if (values.length == 5 && values[2][0] == '/' && values[0][0] == values[3][0] && values[1][0] == values[4][0])
|
||||
spliceAt = 2;
|
||||
else if (values.length == 7 && values[3][0] == '/' && values[0][0] == values[4][0] && values[1][0] == values[5][0] && values[2][0] == values[6][0])
|
||||
spliceAt = 3;
|
||||
else if (values.length == 9 && values[4][0] == '/' && values[0][0] == values[5][0] && values[1][0] == values[6][0] && values[2][0] == values[7][0] && values[3][0] == values[8][0])
|
||||
spliceAt = 4;
|
||||
|
||||
if (spliceAt) {
|
||||
property.value.splice(spliceAt);
|
||||
property.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function minifyFilter(property) {
|
||||
if (property.value.length == 1) {
|
||||
property.value[0][0] = property.value[0][0].replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\W)/, function (match, filter, suffix) {
|
||||
return filter.toLowerCase() + suffix;
|
||||
});
|
||||
}
|
||||
|
||||
property.value[0][0] = property.value[0][0]
|
||||
.replace(/,(\S)/g, ', $1')
|
||||
.replace(/ ?= ?/g, '=');
|
||||
}
|
||||
|
||||
function minifyFont(property) {
|
||||
var values = property.value;
|
||||
var hasNumeral = FONT_NUMERAL_WEIGHTS.indexOf(values[0][0]) > -1 ||
|
||||
values[1] && FONT_NUMERAL_WEIGHTS.indexOf(values[1][0]) > -1 ||
|
||||
values[2] && FONT_NUMERAL_WEIGHTS.indexOf(values[2][0]) > -1;
|
||||
|
||||
if (hasNumeral)
|
||||
return;
|
||||
|
||||
if (values[1] == '/')
|
||||
return;
|
||||
|
||||
var normalCount = 0;
|
||||
if (values[0][0] == 'normal')
|
||||
normalCount++;
|
||||
if (values[1] && values[1][0] == 'normal')
|
||||
normalCount++;
|
||||
if (values[2] && values[2][0] == 'normal')
|
||||
normalCount++;
|
||||
|
||||
if (normalCount > 1)
|
||||
return;
|
||||
|
||||
var toOptimize;
|
||||
if (FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[0][0]) > -1)
|
||||
toOptimize = 0;
|
||||
else if (values[1] && FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[1][0]) > -1)
|
||||
toOptimize = 1;
|
||||
else if (values[2] && FONT_NAME_WEIGHTS_WITHOUT_NORMAL.indexOf(values[2][0]) > -1)
|
||||
toOptimize = 2;
|
||||
else if (FONT_NAME_WEIGHTS.indexOf(values[0][0]) > -1)
|
||||
toOptimize = 0;
|
||||
else if (values[1] && FONT_NAME_WEIGHTS.indexOf(values[1][0]) > -1)
|
||||
toOptimize = 1;
|
||||
else if (values[2] && FONT_NAME_WEIGHTS.indexOf(values[2][0]) > -1)
|
||||
toOptimize = 2;
|
||||
|
||||
if (toOptimize !== undefined) {
|
||||
property.value[toOptimize][0] = valueMinifiers['font-weight'](values[toOptimize][0]);
|
||||
property.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
function optimizeBody(properties, options) {
|
||||
var property, name, value;
|
||||
var _properties = wrapForOptimizing(properties);
|
||||
|
||||
for (var i = 0, l = _properties.length; i < l; i++) {
|
||||
property = _properties[i];
|
||||
name = property.name;
|
||||
|
||||
if (property.hack && (
|
||||
(property.hack == 'star' || property.hack == 'underscore') && !options.compatibility.properties.iePrefixHack ||
|
||||
property.hack == 'backslash' && !options.compatibility.properties.ieSuffixHack ||
|
||||
property.hack == 'bang' && !options.compatibility.properties.ieBangHack))
|
||||
property.unused = true;
|
||||
|
||||
if (name.indexOf('padding') === 0 && (isNegative(property, 0) || isNegative(property, 1) || isNegative(property, 2) || isNegative(property, 3)))
|
||||
property.unused = true;
|
||||
|
||||
if (property.unused)
|
||||
continue;
|
||||
|
||||
if (property.variable) {
|
||||
if (property.block)
|
||||
optimizeBody(property.value[0], options);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0, m = property.value.length; j < m; j++) {
|
||||
value = property.value[j][0];
|
||||
|
||||
if (valueMinifiers[name])
|
||||
value = valueMinifiers[name](value, j, m);
|
||||
|
||||
value = whitespaceMinifier(name, value);
|
||||
value = precisionMinifier(name, value, options.precision);
|
||||
value = pixelLengthMinifier(name, value, options.compatibility);
|
||||
value = timeUnitMinifier(name, value);
|
||||
value = zeroMinifier(name, value);
|
||||
if (options.compatibility.properties.zeroUnits) {
|
||||
value = zeroDegMinifier(name, value);
|
||||
value = unitMinifier(name, value, options.unitsRegexp);
|
||||
}
|
||||
if (options.compatibility.properties.colors)
|
||||
value = colorMininifier(name, value, options.compatibility);
|
||||
|
||||
property.value[j][0] = value;
|
||||
}
|
||||
|
||||
multipleZerosMinifier(property);
|
||||
|
||||
if (name.indexOf('border') === 0 && name.indexOf('radius') > 0)
|
||||
minifyBorderRadius(property);
|
||||
else if (name == 'filter')
|
||||
minifyFilter(property);
|
||||
else if (name == 'font')
|
||||
minifyFont(property);
|
||||
}
|
||||
|
||||
restoreFromOptimizing(_properties, true);
|
||||
removeUnused(_properties);
|
||||
}
|
||||
|
||||
function cleanupCharsets(tokens) {
|
||||
var hasCharset = false;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token[0] != 'at-rule')
|
||||
continue;
|
||||
|
||||
if (!CHARSET_REGEXP.test(token[1][0]))
|
||||
continue;
|
||||
|
||||
if (hasCharset || token[1][0].indexOf(CHARSET_TOKEN) == -1) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
} else {
|
||||
hasCharset = true;
|
||||
tokens.splice(i, 1);
|
||||
tokens.unshift(['at-rule', [token[1][0].replace(CHARSET_REGEXP, CHARSET_TOKEN)]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildUnitRegexp(options) {
|
||||
var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%'];
|
||||
var otherUnits = ['ch', 'rem', 'vh', 'vm', 'vmax', 'vmin', 'vw'];
|
||||
|
||||
otherUnits.forEach(function (unit) {
|
||||
if (options.compatibility.units[unit])
|
||||
units.push(unit);
|
||||
});
|
||||
|
||||
return new RegExp('(^|\\s|\\(|,)0(?:' + units.join('|') + ')(\\W|$)', 'g');
|
||||
}
|
||||
|
||||
function buildPrecision(options) {
|
||||
var precision = {};
|
||||
|
||||
precision.value = options.roundingPrecision === undefined ?
|
||||
DEFAULT_ROUNDING_PRECISION :
|
||||
options.roundingPrecision;
|
||||
precision.multiplier = Math.pow(10, precision.value);
|
||||
precision.regexp = new RegExp('(\\d*\\.\\d{' + (precision.value + 1) + ',})px', 'g');
|
||||
|
||||
return precision;
|
||||
}
|
||||
|
||||
function optimize(tokens, options) {
|
||||
var ie7Hack = options.compatibility.selectors.ie7Hack;
|
||||
var adjacentSpace = options.compatibility.selectors.adjacentSpace;
|
||||
var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace;
|
||||
var mayHaveCharset = false;
|
||||
|
||||
options.unitsRegexp = buildUnitRegexp(options);
|
||||
options.precision = buildPrecision(options);
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
switch (token[0]) {
|
||||
case 'selector':
|
||||
token[1] = cleanUpSelectors(token[1], !ie7Hack, adjacentSpace);
|
||||
optimizeBody(token[2], options);
|
||||
break;
|
||||
case 'block':
|
||||
cleanUpBlock(token[1], spaceAfterClosingBrace);
|
||||
optimize(token[2], options);
|
||||
break;
|
||||
case 'flat-block':
|
||||
cleanUpBlock(token[1], spaceAfterClosingBrace);
|
||||
optimizeBody(token[2], options);
|
||||
break;
|
||||
case 'at-rule':
|
||||
cleanUpAtRule(token[1]);
|
||||
mayHaveCharset = true;
|
||||
}
|
||||
|
||||
if (token[1].length === 0 || (token[2] && token[2].length === 0)) {
|
||||
tokens.splice(i, 1);
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
|
||||
if (mayHaveCharset)
|
||||
cleanupCharsets(tokens);
|
||||
}
|
||||
|
||||
module.exports = optimize;
|
||||
119
node_modules/jade/node_modules/clean-css/lib/source-maps/track.js
generated
vendored
Normal file
119
node_modules/jade/node_modules/clean-css/lib/source-maps/track.js
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
var escapePrefix = '__ESCAPED_';
|
||||
|
||||
function trackPrefix(value, context, interestingContent) {
|
||||
if (!interestingContent && value.indexOf('\n') == -1) {
|
||||
if (value.indexOf(escapePrefix) === 0) {
|
||||
return value;
|
||||
} else {
|
||||
context.column += value.length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var withoutContent = 0;
|
||||
var split = value.split('\n');
|
||||
var total = split.length;
|
||||
var shift = 0;
|
||||
|
||||
while (true) {
|
||||
if (withoutContent == total - 1)
|
||||
break;
|
||||
|
||||
var part = split[withoutContent];
|
||||
if (/\S/.test(part))
|
||||
break;
|
||||
|
||||
shift += part.length + 1;
|
||||
withoutContent++;
|
||||
}
|
||||
|
||||
context.line += withoutContent;
|
||||
context.column = withoutContent > 0 ? 0 : context.column;
|
||||
context.column += /^(\s)*/.exec(split[withoutContent])[0].length;
|
||||
|
||||
return value.substring(shift).trimLeft();
|
||||
}
|
||||
|
||||
function sourceFor(originalMetadata, contextMetadata, context) {
|
||||
var source = originalMetadata.source || contextMetadata.source;
|
||||
|
||||
if (source && context.resolvePath)
|
||||
return context.resolvePath(contextMetadata.source, source);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
function snapshot(data, context, fallbacks) {
|
||||
var metadata = {
|
||||
line: context.line,
|
||||
column: context.column,
|
||||
source: context.source
|
||||
};
|
||||
var sourceContent = null;
|
||||
var sourceMetadata = context.sourceMapTracker.isTracking(metadata.source) ?
|
||||
context.sourceMapTracker.originalPositionFor(metadata, data, fallbacks || 0) :
|
||||
{};
|
||||
|
||||
metadata.line = sourceMetadata.line || metadata.line;
|
||||
metadata.column = sourceMetadata.column || metadata.column;
|
||||
metadata.source = sourceMetadata.sourceResolved ?
|
||||
sourceMetadata.source :
|
||||
sourceFor(sourceMetadata, metadata, context);
|
||||
|
||||
if (context.sourceMapInlineSources) {
|
||||
var sourceMapSourcesContent = context.sourceMapTracker.sourcesContentFor(context.source);
|
||||
sourceContent = sourceMapSourcesContent && sourceMapSourcesContent[metadata.source] ?
|
||||
sourceMapSourcesContent :
|
||||
context.sourceReader.sourceAt(context.source);
|
||||
}
|
||||
|
||||
return sourceContent ?
|
||||
[metadata.line, metadata.column, metadata.source, sourceContent] :
|
||||
[metadata.line, metadata.column, metadata.source];
|
||||
}
|
||||
|
||||
function trackSuffix(data, context) {
|
||||
var parts = data.split('\n');
|
||||
|
||||
for (var i = 0, l = parts.length; i < l; i++) {
|
||||
var part = parts[i];
|
||||
var cursor = 0;
|
||||
|
||||
if (i > 0) {
|
||||
context.line++;
|
||||
context.column = 0;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var next = part.indexOf(escapePrefix, cursor);
|
||||
|
||||
if (next == -1) {
|
||||
context.column += part.substring(cursor).length;
|
||||
break;
|
||||
}
|
||||
|
||||
context.column += next - cursor;
|
||||
cursor += next - cursor;
|
||||
|
||||
var escaped = part.substring(next, part.indexOf('__', next + 1) + 2);
|
||||
var encodedValues = escaped.substring(escaped.indexOf('(') + 1, escaped.indexOf(')')).split(',');
|
||||
context.line += ~~encodedValues[0];
|
||||
context.column = (~~encodedValues[0] === 0 ? context.column : 0) + ~~encodedValues[1];
|
||||
cursor += escaped.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function track(data, context, snapshotMetadata, fallbacks) {
|
||||
var untracked = trackPrefix(data, context, snapshotMetadata);
|
||||
var metadata = snapshotMetadata ?
|
||||
snapshot(untracked, context, fallbacks) :
|
||||
[];
|
||||
|
||||
if (untracked)
|
||||
trackSuffix(untracked, context);
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
module.exports = track;
|
||||
161
node_modules/jade/node_modules/clean-css/lib/stringifier/helpers.js
generated
vendored
Normal file
161
node_modules/jade/node_modules/clean-css/lib/stringifier/helpers.js
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
var lineBreak = require('os').EOL;
|
||||
|
||||
var AT_RULE = 'at-rule';
|
||||
var PROPERTY_SEPARATOR = ';';
|
||||
|
||||
function hasMoreProperties(tokens, index) {
|
||||
for (var i = index, l = tokens.length; i < l; i++) {
|
||||
if (typeof tokens[i] != 'string')
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function supportsAfterClosingBrace(token) {
|
||||
return token[0][0] == 'background' || token[0][0] == 'transform' || token[0][0] == 'src';
|
||||
}
|
||||
|
||||
function isVariable(token, valueIndex) {
|
||||
return token[valueIndex][0].indexOf('var(') === 0;
|
||||
}
|
||||
|
||||
function afterClosingBrace(token, valueIndex) {
|
||||
return token[valueIndex][0][token[valueIndex][0].length - 1] == ')' || token[valueIndex][0].indexOf('__ESCAPED_URL_CLEAN_CSS') === 0;
|
||||
}
|
||||
|
||||
function afterComma(token, valueIndex) {
|
||||
return token[valueIndex][0] == ',';
|
||||
}
|
||||
|
||||
function afterSlash(token, valueIndex) {
|
||||
return token[valueIndex][0] == '/';
|
||||
}
|
||||
|
||||
function beforeComma(token, valueIndex) {
|
||||
return token[valueIndex + 1] && token[valueIndex + 1][0] == ',';
|
||||
}
|
||||
|
||||
function beforeSlash(token, valueIndex) {
|
||||
return token[valueIndex + 1] && token[valueIndex + 1][0] == '/';
|
||||
}
|
||||
|
||||
function inFilter(token) {
|
||||
return token[0][0] == 'filter' || token[0][0] == '-ms-filter';
|
||||
}
|
||||
|
||||
function inSpecialContext(token, valueIndex, context) {
|
||||
return (!context.spaceAfterClosingBrace && supportsAfterClosingBrace(token) || isVariable(token, valueIndex)) && afterClosingBrace(token, valueIndex) ||
|
||||
beforeSlash(token, valueIndex) ||
|
||||
afterSlash(token, valueIndex) ||
|
||||
beforeComma(token, valueIndex) ||
|
||||
afterComma(token, valueIndex);
|
||||
}
|
||||
|
||||
function selectors(tokens, context) {
|
||||
var store = context.store;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
store(tokens[i], context);
|
||||
|
||||
if (i < l - 1)
|
||||
store(',', context);
|
||||
}
|
||||
}
|
||||
|
||||
function body(tokens, context) {
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
property(tokens, i, i == l - 1, context);
|
||||
}
|
||||
}
|
||||
|
||||
function property(tokens, position, isLast, context) {
|
||||
var store = context.store;
|
||||
var token = tokens[position];
|
||||
|
||||
if (typeof token == 'string') {
|
||||
store(token, context);
|
||||
} else if (token[0] == AT_RULE) {
|
||||
propertyAtRule(token[1], isLast, context);
|
||||
} else {
|
||||
store(token[0], context);
|
||||
store(':', context);
|
||||
value(tokens, position, isLast, context);
|
||||
}
|
||||
}
|
||||
|
||||
function propertyAtRule(value, isLast, context) {
|
||||
var store = context.store;
|
||||
|
||||
store(value, context);
|
||||
if (!isLast)
|
||||
store(PROPERTY_SEPARATOR, context);
|
||||
}
|
||||
|
||||
function value(tokens, position, isLast, context) {
|
||||
var store = context.store;
|
||||
var token = tokens[position];
|
||||
var isVariableDeclaration = token[0][0].indexOf('--') === 0;
|
||||
|
||||
if (isVariableDeclaration && Array.isArray(token[1][0][0])) {
|
||||
store('{', context);
|
||||
body(token[1], context);
|
||||
store('};', context);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var j = 1, m = token.length; j < m; j++) {
|
||||
store(token[j], context);
|
||||
|
||||
if (j < m - 1 && (inFilter(token) || !inSpecialContext(token, j, context))) {
|
||||
store(' ', context);
|
||||
} else if (j == m - 1 && !isLast && hasMoreProperties(tokens, position + 1)) {
|
||||
store(PROPERTY_SEPARATOR, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function all(tokens, context) {
|
||||
var joinCharacter = context.keepBreaks ? lineBreak : '';
|
||||
var store = context.store;
|
||||
|
||||
for (var i = 0, l = tokens.length; i < l; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
switch (token[0]) {
|
||||
case 'at-rule':
|
||||
case 'text':
|
||||
store(token[1][0], context);
|
||||
store(joinCharacter, context);
|
||||
break;
|
||||
case 'block':
|
||||
selectors([token[1]], context);
|
||||
store('{', context);
|
||||
all(token[2], context);
|
||||
store('}', context);
|
||||
store(joinCharacter, context);
|
||||
break;
|
||||
case 'flat-block':
|
||||
selectors([token[1]], context);
|
||||
store('{', context);
|
||||
body(token[2], context);
|
||||
store('}', context);
|
||||
store(joinCharacter, context);
|
||||
break;
|
||||
default:
|
||||
selectors(token[1], context);
|
||||
store('{', context);
|
||||
body(token[2], context);
|
||||
store('}', context);
|
||||
store(joinCharacter, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
all: all,
|
||||
body: body,
|
||||
property: property,
|
||||
selectors: selectors,
|
||||
value: value
|
||||
};
|
||||
50
node_modules/jade/node_modules/clean-css/lib/stringifier/one-time.js
generated
vendored
Normal file
50
node_modules/jade/node_modules/clean-css/lib/stringifier/one-time.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
var helpers = require('./helpers');
|
||||
|
||||
function store(token, context) {
|
||||
context.output.push(typeof token == 'string' ? token : token[0]);
|
||||
}
|
||||
|
||||
function context() {
|
||||
return {
|
||||
output: [],
|
||||
store: store
|
||||
};
|
||||
}
|
||||
|
||||
function all(tokens) {
|
||||
var fakeContext = context();
|
||||
helpers.all(tokens, fakeContext);
|
||||
return fakeContext.output.join('');
|
||||
}
|
||||
|
||||
function body(tokens) {
|
||||
var fakeContext = context();
|
||||
helpers.body(tokens, fakeContext);
|
||||
return fakeContext.output.join('');
|
||||
}
|
||||
|
||||
function property(tokens, position) {
|
||||
var fakeContext = context();
|
||||
helpers.property(tokens, position, true, fakeContext);
|
||||
return fakeContext.output.join('');
|
||||
}
|
||||
|
||||
function selectors(tokens) {
|
||||
var fakeContext = context();
|
||||
helpers.selectors(tokens, fakeContext);
|
||||
return fakeContext.output.join('');
|
||||
}
|
||||
|
||||
function value(tokens, position) {
|
||||
var fakeContext = context();
|
||||
helpers.value(tokens, position, true, fakeContext);
|
||||
return fakeContext.output.join('');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
all: all,
|
||||
body: body,
|
||||
property: property,
|
||||
selectors: selectors,
|
||||
value: value
|
||||
};
|
||||
22
node_modules/jade/node_modules/clean-css/lib/stringifier/simple.js
generated
vendored
Normal file
22
node_modules/jade/node_modules/clean-css/lib/stringifier/simple.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
var all = require('./helpers').all;
|
||||
|
||||
function store(token, context) {
|
||||
context.output.push(typeof token == 'string' ? token : token[0]);
|
||||
}
|
||||
|
||||
function stringify(tokens, options, restoreCallback) {
|
||||
var context = {
|
||||
keepBreaks: options.keepBreaks,
|
||||
output: [],
|
||||
spaceAfterClosingBrace: options.compatibility.properties.spaceAfterClosingBrace,
|
||||
store: store
|
||||
};
|
||||
|
||||
all(tokens, context, false);
|
||||
|
||||
return {
|
||||
styles: restoreCallback(context.output.join('')).trim()
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = stringify;
|
||||
96
node_modules/jade/node_modules/clean-css/lib/stringifier/source-maps.js
generated
vendored
Normal file
96
node_modules/jade/node_modules/clean-css/lib/stringifier/source-maps.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
var SourceMapGenerator = require('source-map').SourceMapGenerator;
|
||||
var all = require('./helpers').all;
|
||||
|
||||
var isWindows = process.platform == 'win32';
|
||||
var unknownSource = '$stdin';
|
||||
|
||||
function store(element, context) {
|
||||
var fromString = typeof element == 'string';
|
||||
var value = fromString ? element : element[0];
|
||||
|
||||
if (value.indexOf('_') > -1)
|
||||
value = context.restore(value, prefixContentFrom(context.output));
|
||||
|
||||
track(value, fromString ? null : element, context);
|
||||
context.output.push(value);
|
||||
}
|
||||
|
||||
function prefixContentFrom(values) {
|
||||
var content = [];
|
||||
|
||||
for (var i = values.length - 1; i >= 0; i--) {
|
||||
var value = values[i];
|
||||
content.unshift(value);
|
||||
|
||||
if (value == '{' || value == ';')
|
||||
break;
|
||||
}
|
||||
|
||||
return content.join('');
|
||||
}
|
||||
|
||||
function track(value, element, context) {
|
||||
if (element)
|
||||
trackAllMappings(element, context);
|
||||
|
||||
var parts = value.split('\n');
|
||||
context.line += parts.length - 1;
|
||||
context.column = parts.length > 1 ? 0 : (context.column + parts.pop().length);
|
||||
}
|
||||
|
||||
function trackAllMappings(element, context) {
|
||||
var mapping = element[element.length - 1];
|
||||
|
||||
if (!Array.isArray(mapping))
|
||||
return;
|
||||
|
||||
for (var i = 0, l = mapping.length; i < l; i++) {
|
||||
trackMapping(mapping[i], context);
|
||||
}
|
||||
}
|
||||
|
||||
function trackMapping(mapping, context) {
|
||||
var source = mapping[2] || unknownSource;
|
||||
|
||||
if (isWindows)
|
||||
source = source.replace(/\\/g, '/');
|
||||
|
||||
context.outputMap.addMapping({
|
||||
generated: {
|
||||
line: context.line,
|
||||
column: context.column
|
||||
},
|
||||
source: source,
|
||||
original: {
|
||||
line: mapping[0],
|
||||
column: mapping[1]
|
||||
}
|
||||
});
|
||||
|
||||
if (mapping[3])
|
||||
context.outputMap.setSourceContent(source, mapping[3][mapping[2]]);
|
||||
}
|
||||
|
||||
function stringify(tokens, options, restoreCallback, inputMapTracker) {
|
||||
var context = {
|
||||
column: 0,
|
||||
inputMapTracker: inputMapTracker,
|
||||
keepBreaks: options.keepBreaks,
|
||||
line: 1,
|
||||
output: [],
|
||||
outputMap: new SourceMapGenerator(),
|
||||
restore: restoreCallback,
|
||||
sourceMapInlineSources: options.sourceMapInlineSources,
|
||||
spaceAfterClosingBrace: options.compatibility.properties.spaceAfterClosingBrace,
|
||||
store: store
|
||||
};
|
||||
|
||||
all(tokens, context, false);
|
||||
|
||||
return {
|
||||
sourceMap: context.outputMap,
|
||||
styles: context.output.join('').trim()
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = stringify;
|
||||
131
node_modules/jade/node_modules/clean-css/lib/text/comments-processor.js
generated
vendored
Normal file
131
node_modules/jade/node_modules/clean-css/lib/text/comments-processor.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
var EscapeStore = require('./escape-store');
|
||||
var QuoteScanner = require('../utils/quote-scanner');
|
||||
|
||||
var SPECIAL_COMMENT_PREFIX = '/*!';
|
||||
var COMMENT_PREFIX = '/*';
|
||||
var COMMENT_SUFFIX = '*/';
|
||||
|
||||
var lineBreak = require('os').EOL;
|
||||
|
||||
function CommentsProcessor(context, keepSpecialComments, keepBreaks, saveWaypoints) {
|
||||
this.comments = new EscapeStore('COMMENT');
|
||||
this.specialComments = new EscapeStore('COMMENT_SPECIAL');
|
||||
|
||||
this.context = context;
|
||||
this.restored = 0;
|
||||
this.keepAll = keepSpecialComments == '*';
|
||||
this.keepOne = keepSpecialComments == '1' || keepSpecialComments === 1;
|
||||
this.keepBreaks = keepBreaks;
|
||||
this.saveWaypoints = saveWaypoints;
|
||||
}
|
||||
|
||||
function quoteScannerFor(data) {
|
||||
var quoteMap = [];
|
||||
new QuoteScanner(data).each(function (quotedString, _, startsAt) {
|
||||
quoteMap.push([startsAt, startsAt + quotedString.length]);
|
||||
});
|
||||
|
||||
return function (position) {
|
||||
for (var i = 0, l = quoteMap.length; i < l; i++) {
|
||||
if (quoteMap[i][0] < position && quoteMap[i][1] > position)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
CommentsProcessor.prototype.escape = function (data) {
|
||||
var tempData = [];
|
||||
var nextStart = 0;
|
||||
var nextEnd = 0;
|
||||
var cursor = 0;
|
||||
var indent = 0;
|
||||
var breaksCount;
|
||||
var lastBreakAt;
|
||||
var newIndent;
|
||||
var isQuotedAt = quoteScannerFor(data);
|
||||
var saveWaypoints = this.saveWaypoints;
|
||||
|
||||
for (; nextEnd < data.length;) {
|
||||
nextStart = data.indexOf(COMMENT_PREFIX, cursor);
|
||||
if (nextStart == -1)
|
||||
break;
|
||||
|
||||
if (isQuotedAt(nextStart)) {
|
||||
tempData.push(data.substring(cursor, nextStart + COMMENT_PREFIX.length));
|
||||
cursor = nextStart + COMMENT_PREFIX.length;
|
||||
continue;
|
||||
}
|
||||
|
||||
nextEnd = data.indexOf(COMMENT_SUFFIX, nextStart + COMMENT_PREFIX.length);
|
||||
if (nextEnd == -1) {
|
||||
this.context.warnings.push('Broken comment: \'' + data.substring(nextStart) + '\'.');
|
||||
nextEnd = data.length - 2;
|
||||
}
|
||||
|
||||
tempData.push(data.substring(cursor, nextStart));
|
||||
|
||||
var comment = data.substring(nextStart, nextEnd + COMMENT_SUFFIX.length);
|
||||
var isSpecialComment = comment.indexOf(SPECIAL_COMMENT_PREFIX) === 0;
|
||||
|
||||
if (saveWaypoints) {
|
||||
breaksCount = comment.split(lineBreak).length - 1;
|
||||
lastBreakAt = comment.lastIndexOf(lineBreak);
|
||||
newIndent = lastBreakAt > 0 ?
|
||||
comment.substring(lastBreakAt + lineBreak.length).length :
|
||||
indent + comment.length;
|
||||
}
|
||||
|
||||
if (saveWaypoints || isSpecialComment) {
|
||||
var metadata = saveWaypoints ? [breaksCount, newIndent] : null;
|
||||
var placeholder = isSpecialComment ?
|
||||
this.specialComments.store(comment, metadata) :
|
||||
this.comments.store(comment, metadata);
|
||||
tempData.push(placeholder);
|
||||
}
|
||||
|
||||
if (saveWaypoints)
|
||||
indent = newIndent + 1;
|
||||
cursor = nextEnd + COMMENT_SUFFIX.length;
|
||||
}
|
||||
|
||||
return tempData.length > 0 ?
|
||||
tempData.join('') + data.substring(cursor, data.length) :
|
||||
data;
|
||||
};
|
||||
|
||||
function restore(context, data, from, isSpecial) {
|
||||
var tempData = [];
|
||||
var cursor = 0;
|
||||
|
||||
for (; cursor < data.length;) {
|
||||
var nextMatch = from.nextMatch(data, cursor);
|
||||
if (nextMatch.start < 0)
|
||||
break;
|
||||
|
||||
tempData.push(data.substring(cursor, nextMatch.start));
|
||||
var comment = from.restore(nextMatch.match);
|
||||
|
||||
if (isSpecial && (context.keepAll || (context.keepOne && context.restored === 0))) {
|
||||
context.restored++;
|
||||
tempData.push(comment);
|
||||
|
||||
cursor = nextMatch.end;
|
||||
} else {
|
||||
cursor = nextMatch.end + (context.keepBreaks && data[nextMatch.end] == lineBreak ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return tempData.length > 0 ?
|
||||
tempData.join('') + data.substring(cursor, data.length) :
|
||||
data;
|
||||
}
|
||||
|
||||
CommentsProcessor.prototype.restore = function (data) {
|
||||
data = restore(this, data, this.comments, false);
|
||||
data = restore(this, data, this.specialComments, true);
|
||||
return data;
|
||||
};
|
||||
|
||||
module.exports = CommentsProcessor;
|
||||
53
node_modules/jade/node_modules/clean-css/lib/text/escape-store.js
generated
vendored
Normal file
53
node_modules/jade/node_modules/clean-css/lib/text/escape-store.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
var placeholderBrace = '__';
|
||||
|
||||
function EscapeStore(placeholderRoot) {
|
||||
this.placeholderRoot = 'ESCAPED_' + placeholderRoot + '_CLEAN_CSS';
|
||||
this.placeholderToData = {};
|
||||
this.dataToPlaceholder = {};
|
||||
this.count = 0;
|
||||
this.restoreMatcher = new RegExp(this.placeholderRoot + '(\\d+)');
|
||||
}
|
||||
|
||||
EscapeStore.prototype._nextPlaceholder = function (metadata) {
|
||||
return {
|
||||
index: this.count,
|
||||
value: placeholderBrace + this.placeholderRoot + this.count++ + metadata + placeholderBrace
|
||||
};
|
||||
};
|
||||
|
||||
EscapeStore.prototype.store = function (data, metadata) {
|
||||
var encodedMetadata = metadata ?
|
||||
'(' + metadata.join(',') + ')' :
|
||||
'';
|
||||
var placeholder = this.dataToPlaceholder[data];
|
||||
|
||||
if (!placeholder) {
|
||||
var nextPlaceholder = this._nextPlaceholder(encodedMetadata);
|
||||
placeholder = nextPlaceholder.value;
|
||||
this.placeholderToData[nextPlaceholder.index] = data;
|
||||
this.dataToPlaceholder[data] = nextPlaceholder.value;
|
||||
}
|
||||
|
||||
if (metadata)
|
||||
placeholder = placeholder.replace(/\([^\)]+\)/, encodedMetadata);
|
||||
|
||||
return placeholder;
|
||||
};
|
||||
|
||||
EscapeStore.prototype.nextMatch = function (data, cursor) {
|
||||
var next = {};
|
||||
|
||||
next.start = data.indexOf(this.placeholderRoot, cursor) - placeholderBrace.length;
|
||||
next.end = data.indexOf(placeholderBrace, next.start + placeholderBrace.length) + placeholderBrace.length;
|
||||
if (next.start > -1 && next.end > -1)
|
||||
next.match = data.substring(next.start, next.end);
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
EscapeStore.prototype.restore = function (placeholder) {
|
||||
var index = this.restoreMatcher.exec(placeholder)[1];
|
||||
return this.placeholderToData[index];
|
||||
};
|
||||
|
||||
module.exports = EscapeStore;
|
||||
117
node_modules/jade/node_modules/clean-css/lib/text/expressions-processor.js
generated
vendored
Normal file
117
node_modules/jade/node_modules/clean-css/lib/text/expressions-processor.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
var EscapeStore = require('./escape-store');
|
||||
|
||||
var EXPRESSION_NAME = 'expression';
|
||||
var EXPRESSION_START = '(';
|
||||
var EXPRESSION_END = ')';
|
||||
var EXPRESSION_PREFIX = EXPRESSION_NAME + EXPRESSION_START;
|
||||
var BODY_START = '{';
|
||||
var BODY_END = '}';
|
||||
|
||||
var lineBreak = require('os').EOL;
|
||||
|
||||
function findEnd(data, start) {
|
||||
var end = start + EXPRESSION_NAME.length;
|
||||
var level = 0;
|
||||
var quoted = false;
|
||||
var braced = false;
|
||||
|
||||
while (true) {
|
||||
var current = data[end++];
|
||||
|
||||
if (quoted) {
|
||||
quoted = current != '\'' && current != '"';
|
||||
} else {
|
||||
quoted = current == '\'' || current == '"';
|
||||
|
||||
if (current == EXPRESSION_START)
|
||||
level++;
|
||||
if (current == EXPRESSION_END)
|
||||
level--;
|
||||
if (current == BODY_START)
|
||||
braced = true;
|
||||
if (current == BODY_END && !braced && level == 1) {
|
||||
end--;
|
||||
level--;
|
||||
}
|
||||
}
|
||||
|
||||
if (level === 0 && current == EXPRESSION_END)
|
||||
break;
|
||||
if (!current) {
|
||||
end = data.substring(0, end).lastIndexOf(BODY_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
function ExpressionsProcessor(saveWaypoints) {
|
||||
this.expressions = new EscapeStore('EXPRESSION');
|
||||
this.saveWaypoints = saveWaypoints;
|
||||
}
|
||||
|
||||
ExpressionsProcessor.prototype.escape = function (data) {
|
||||
var nextStart = 0;
|
||||
var nextEnd = 0;
|
||||
var cursor = 0;
|
||||
var tempData = [];
|
||||
var indent = 0;
|
||||
var breaksCount;
|
||||
var lastBreakAt;
|
||||
var newIndent;
|
||||
var saveWaypoints = this.saveWaypoints;
|
||||
|
||||
for (; nextEnd < data.length;) {
|
||||
nextStart = data.indexOf(EXPRESSION_PREFIX, nextEnd);
|
||||
if (nextStart == -1)
|
||||
break;
|
||||
|
||||
nextEnd = findEnd(data, nextStart);
|
||||
|
||||
var expression = data.substring(nextStart, nextEnd);
|
||||
if (saveWaypoints) {
|
||||
breaksCount = expression.split(lineBreak).length - 1;
|
||||
lastBreakAt = expression.lastIndexOf(lineBreak);
|
||||
newIndent = lastBreakAt > 0 ?
|
||||
expression.substring(lastBreakAt + lineBreak.length).length :
|
||||
indent + expression.length;
|
||||
}
|
||||
|
||||
var metadata = saveWaypoints ? [breaksCount, newIndent] : null;
|
||||
var placeholder = this.expressions.store(expression, metadata);
|
||||
tempData.push(data.substring(cursor, nextStart));
|
||||
tempData.push(placeholder);
|
||||
|
||||
if (saveWaypoints)
|
||||
indent = newIndent + 1;
|
||||
cursor = nextEnd;
|
||||
}
|
||||
|
||||
return tempData.length > 0 ?
|
||||
tempData.join('') + data.substring(cursor, data.length) :
|
||||
data;
|
||||
};
|
||||
|
||||
ExpressionsProcessor.prototype.restore = function (data) {
|
||||
var tempData = [];
|
||||
var cursor = 0;
|
||||
|
||||
for (; cursor < data.length;) {
|
||||
var nextMatch = this.expressions.nextMatch(data, cursor);
|
||||
if (nextMatch.start < 0)
|
||||
break;
|
||||
|
||||
tempData.push(data.substring(cursor, nextMatch.start));
|
||||
var comment = this.expressions.restore(nextMatch.match);
|
||||
tempData.push(comment);
|
||||
|
||||
cursor = nextMatch.end;
|
||||
}
|
||||
|
||||
return tempData.length > 0 ?
|
||||
tempData.join('') + data.substring(cursor, data.length) :
|
||||
data;
|
||||
};
|
||||
|
||||
module.exports = ExpressionsProcessor;
|
||||
98
node_modules/jade/node_modules/clean-css/lib/text/free-text-processor.js
generated
vendored
Normal file
98
node_modules/jade/node_modules/clean-css/lib/text/free-text-processor.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
var EscapeStore = require('./escape-store');
|
||||
var QuoteScanner = require('../utils/quote-scanner');
|
||||
|
||||
var lineBreak = require('os').EOL;
|
||||
|
||||
function FreeTextProcessor(saveWaypoints) {
|
||||
this.matches = new EscapeStore('FREE_TEXT');
|
||||
this.saveWaypoints = saveWaypoints;
|
||||
}
|
||||
|
||||
// Strip content tags by replacing them by the a special
|
||||
// marker for further restoring. It's done via string scanning
|
||||
// instead of regexps to speed up the process.
|
||||
FreeTextProcessor.prototype.escape = function (data) {
|
||||
var self = this;
|
||||
var breaksCount;
|
||||
var lastBreakAt;
|
||||
var indent;
|
||||
var metadata;
|
||||
var saveWaypoints = this.saveWaypoints;
|
||||
|
||||
return new QuoteScanner(data).each(function (match, store) {
|
||||
if (saveWaypoints) {
|
||||
breaksCount = match.split(lineBreak).length - 1;
|
||||
lastBreakAt = match.lastIndexOf(lineBreak);
|
||||
indent = lastBreakAt > 0 ?
|
||||
match.substring(lastBreakAt + lineBreak.length).length :
|
||||
match.length;
|
||||
metadata = [breaksCount, indent];
|
||||
}
|
||||
|
||||
var placeholder = self.matches.store(match, metadata);
|
||||
store.push(placeholder);
|
||||
});
|
||||
};
|
||||
|
||||
function normalize(text, data, prefixContext, cursor) {
|
||||
// FIXME: this is even a bigger hack now - see #407
|
||||
var searchIn = data;
|
||||
if (prefixContext) {
|
||||
searchIn = prefixContext + data.substring(0, data.indexOf('__ESCAPED_FREE_TEXT_CLEAN_CSS'));
|
||||
cursor = searchIn.length;
|
||||
}
|
||||
|
||||
var lastSemicolon = searchIn.lastIndexOf(';', cursor);
|
||||
var lastOpenBrace = searchIn.lastIndexOf('{', cursor);
|
||||
var lastOne = 0;
|
||||
|
||||
if (lastSemicolon > -1 && lastOpenBrace > -1)
|
||||
lastOne = Math.max(lastSemicolon, lastOpenBrace);
|
||||
else if (lastSemicolon == -1)
|
||||
lastOne = lastOpenBrace;
|
||||
else
|
||||
lastOne = lastSemicolon;
|
||||
|
||||
var context = searchIn.substring(lastOne + 1, cursor);
|
||||
|
||||
if (/\[[\w\d\-]+[\*\|\~\^\$]?=$/.test(context)) {
|
||||
text = text
|
||||
.replace(/\\\n|\\\r\n/g, '')
|
||||
.replace(/\n|\r\n/g, '');
|
||||
}
|
||||
|
||||
if (/^['"][a-zA-Z][a-zA-Z\d\-_]+['"]$/.test(text) && !/format\($/.test(context)) {
|
||||
var isFont = /^(font|font\-family):/.test(context);
|
||||
var isAttribute = /\[[\w\d\-]+[\*\|\~\^\$]?=$/.test(context);
|
||||
var isKeyframe = /@(-moz-|-o-|-webkit-)?keyframes /.test(context);
|
||||
var isAnimation = /^(-moz-|-o-|-webkit-)?animation(-name)?:/.test(context);
|
||||
|
||||
if (isFont || isAttribute || isKeyframe || isAnimation)
|
||||
text = text.substring(1, text.length - 1);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
FreeTextProcessor.prototype.restore = function (data, prefixContext) {
|
||||
var tempData = [];
|
||||
var cursor = 0;
|
||||
|
||||
for (; cursor < data.length;) {
|
||||
var nextMatch = this.matches.nextMatch(data, cursor);
|
||||
if (nextMatch.start < 0)
|
||||
break;
|
||||
|
||||
tempData.push(data.substring(cursor, nextMatch.start));
|
||||
var text = normalize(this.matches.restore(nextMatch.match), data, prefixContext, nextMatch.start);
|
||||
tempData.push(text);
|
||||
|
||||
cursor = nextMatch.end;
|
||||
}
|
||||
|
||||
return tempData.length > 0 ?
|
||||
tempData.join('') + data.substring(cursor, data.length) :
|
||||
data;
|
||||
};
|
||||
|
||||
module.exports = FreeTextProcessor;
|
||||
72
node_modules/jade/node_modules/clean-css/lib/text/urls-processor.js
generated
vendored
Normal file
72
node_modules/jade/node_modules/clean-css/lib/text/urls-processor.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
var EscapeStore = require('./escape-store');
|
||||
var reduceUrls = require('../urls/reduce');
|
||||
|
||||
var lineBreak = require('os').EOL;
|
||||
|
||||
function UrlsProcessor(context, saveWaypoints, keepUrlQuotes) {
|
||||
this.urls = new EscapeStore('URL');
|
||||
this.context = context;
|
||||
this.saveWaypoints = saveWaypoints;
|
||||
this.keepUrlQuotes = keepUrlQuotes;
|
||||
}
|
||||
|
||||
// Strip urls by replacing them by a special
|
||||
// marker for further restoring. It's done via string scanning
|
||||
// instead of regexps to speed up the process.
|
||||
UrlsProcessor.prototype.escape = function (data) {
|
||||
var breaksCount;
|
||||
var lastBreakAt;
|
||||
var indent;
|
||||
var saveWaypoints = this.saveWaypoints;
|
||||
var self = this;
|
||||
|
||||
return reduceUrls(data, this.context, function (url, tempData) {
|
||||
if (saveWaypoints) {
|
||||
breaksCount = url.split(lineBreak).length - 1;
|
||||
lastBreakAt = url.lastIndexOf(lineBreak);
|
||||
indent = lastBreakAt > 0 ?
|
||||
url.substring(lastBreakAt + lineBreak.length).length :
|
||||
url.length;
|
||||
}
|
||||
|
||||
var placeholder = self.urls.store(url, saveWaypoints ? [breaksCount, indent] : null);
|
||||
tempData.push(placeholder);
|
||||
});
|
||||
};
|
||||
|
||||
function normalize(url, keepUrlQuotes) {
|
||||
url = url
|
||||
.replace(/^url/gi, 'url')
|
||||
.replace(/\\?\n|\\?\r\n/g, '')
|
||||
.replace(/(\s{2,}|\s)/g, ' ')
|
||||
.replace(/^url\((['"])? /, 'url($1')
|
||||
.replace(/ (['"])?\)$/, '$1)');
|
||||
|
||||
if (!keepUrlQuotes && !/^['"].+['"]$/.test(url) && !/url\(.*[\s\(\)].*\)/.test(url) && !/url\(['"]data:[^;]+;charset/.test(url))
|
||||
url = url.replace(/["']/g, '');
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
UrlsProcessor.prototype.restore = function (data) {
|
||||
var tempData = [];
|
||||
var cursor = 0;
|
||||
|
||||
for (; cursor < data.length;) {
|
||||
var nextMatch = this.urls.nextMatch(data, cursor);
|
||||
if (nextMatch.start < 0)
|
||||
break;
|
||||
|
||||
tempData.push(data.substring(cursor, nextMatch.start));
|
||||
var url = normalize(this.urls.restore(nextMatch.match), this.keepUrlQuotes);
|
||||
tempData.push(url);
|
||||
|
||||
cursor = nextMatch.end;
|
||||
}
|
||||
|
||||
return tempData.length > 0 ?
|
||||
tempData.join('') + data.substring(cursor, data.length) :
|
||||
data;
|
||||
};
|
||||
|
||||
module.exports = UrlsProcessor;
|
||||
188
node_modules/jade/node_modules/clean-css/lib/tokenizer/extract-properties.js
generated
vendored
Normal file
188
node_modules/jade/node_modules/clean-css/lib/tokenizer/extract-properties.js
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
var split = require('../utils/split');
|
||||
|
||||
var COMMA = ',';
|
||||
var FORWARD_SLASH = '/';
|
||||
|
||||
var AT_RULE = 'at-rule';
|
||||
|
||||
function selectorName(value) {
|
||||
return value[0];
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
function withoutComments(string, into, heading, context) {
|
||||
var matcher = heading ? /^__ESCAPED_COMMENT_/ : /__ESCAPED_COMMENT_/;
|
||||
var track = heading ? context.track : noop; // don't track when comment not in a heading as we do it later in `trackComments`
|
||||
|
||||
while (matcher.test(string)) {
|
||||
var startOfComment = string.indexOf('__');
|
||||
var endOfComment = string.indexOf('__', startOfComment + 1) + 2;
|
||||
var comment = string.substring(startOfComment, endOfComment);
|
||||
string = string.substring(0, startOfComment) + string.substring(endOfComment);
|
||||
|
||||
track(comment);
|
||||
into.push(comment);
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
function withoutHeadingComments(string, into, context) {
|
||||
return withoutComments(string, into, true, context);
|
||||
}
|
||||
|
||||
function withoutInnerComments(string, into, context) {
|
||||
return withoutComments(string, into, false, context);
|
||||
}
|
||||
|
||||
function trackComments(comments, into, context) {
|
||||
for (var i = 0, l = comments.length; i < l; i++) {
|
||||
context.track(comments[i]);
|
||||
into.push(comments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function extractProperties(string, selectors, context) {
|
||||
var list = [];
|
||||
var innerComments = [];
|
||||
var valueSeparator = /[ ,\/]/;
|
||||
|
||||
if (typeof string != 'string')
|
||||
return [];
|
||||
|
||||
if (string.indexOf(')') > -1)
|
||||
string = string.replace(/\)([^\s_;:,\)])/g, context.sourceMap ? ') __ESCAPED_COMMENT_CLEAN_CSS(0,-1)__ $1' : ') $1');
|
||||
|
||||
if (string.indexOf('ESCAPED_URL_CLEAN_CSS') > -1)
|
||||
string = string.replace(/(ESCAPED_URL_CLEAN_CSS[^_]+?__)/g, context.sourceMap ? '$1 __ESCAPED_COMMENT_CLEAN_CSS(0,-1)__ ' : '$1 ');
|
||||
|
||||
var candidates = split(string, ';', false, '{', '}');
|
||||
|
||||
for (var i = 0, l = candidates.length; i < l; i++) {
|
||||
var candidate = candidates[i];
|
||||
var firstColonAt = candidate.indexOf(':');
|
||||
|
||||
var atRule = candidate.trim()[0] == '@';
|
||||
if (atRule) {
|
||||
context.track(candidate);
|
||||
list.push([AT_RULE, candidate.trim()]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (firstColonAt == -1) {
|
||||
context.track(candidate);
|
||||
if (candidate.indexOf('__ESCAPED_COMMENT_SPECIAL') > -1)
|
||||
list.push(candidate.trim());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidate.indexOf('{') > 0 && candidate.indexOf('{') < firstColonAt) {
|
||||
context.track(candidate);
|
||||
continue;
|
||||
}
|
||||
|
||||
var body = [];
|
||||
var name = candidate.substring(0, firstColonAt);
|
||||
|
||||
innerComments = [];
|
||||
|
||||
if (name.indexOf('__ESCAPED_COMMENT') > -1)
|
||||
name = withoutHeadingComments(name, list, context);
|
||||
|
||||
if (name.indexOf('__ESCAPED_COMMENT') > -1)
|
||||
name = withoutInnerComments(name, innerComments, context);
|
||||
|
||||
body.push([name.trim()].concat(context.track(name, true)));
|
||||
context.track(':');
|
||||
|
||||
trackComments(innerComments, list, context);
|
||||
|
||||
var firstBraceAt = candidate.indexOf('{');
|
||||
var isVariable = name.trim().indexOf('--') === 0;
|
||||
if (isVariable && firstBraceAt > 0) {
|
||||
var blockPrefix = candidate.substring(firstColonAt + 1, firstBraceAt + 1);
|
||||
var blockSuffix = candidate.substring(candidate.indexOf('}'));
|
||||
var blockContent = candidate.substring(firstBraceAt + 1, candidate.length - blockSuffix.length);
|
||||
|
||||
context.track(blockPrefix);
|
||||
body.push(extractProperties(blockContent, selectors, context));
|
||||
list.push(body);
|
||||
context.track(blockSuffix);
|
||||
context.track(i < l - 1 ? ';' : '');
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var values = split(candidate.substring(firstColonAt + 1), valueSeparator, true);
|
||||
|
||||
if (values.length == 1 && values[0] === '') {
|
||||
context.warnings.push('Empty property \'' + name + '\' inside \'' + selectors.filter(selectorName).join(',') + '\' selector. Ignoring.');
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0, m = values.length; j < m; j++) {
|
||||
var value = values[j];
|
||||
var trimmed = value.trim();
|
||||
|
||||
if (trimmed.length === 0)
|
||||
continue;
|
||||
|
||||
var lastCharacter = trimmed[trimmed.length - 1];
|
||||
var endsWithNonSpaceSeparator = trimmed.length > 1 && (lastCharacter == COMMA || lastCharacter == FORWARD_SLASH);
|
||||
|
||||
if (endsWithNonSpaceSeparator)
|
||||
trimmed = trimmed.substring(0, trimmed.length - 1);
|
||||
|
||||
if (trimmed.indexOf('__ESCAPED_COMMENT_CLEAN_CSS(0,-') > -1) {
|
||||
context.track(trimmed);
|
||||
continue;
|
||||
}
|
||||
|
||||
innerComments = [];
|
||||
|
||||
if (trimmed.indexOf('__ESCAPED_COMMENT') > -1)
|
||||
trimmed = withoutHeadingComments(trimmed, list, context);
|
||||
|
||||
if (trimmed.indexOf('__ESCAPED_COMMENT') > -1)
|
||||
trimmed = withoutInnerComments(trimmed, innerComments, context);
|
||||
|
||||
if (trimmed.length === 0) {
|
||||
trackComments(innerComments, list, context);
|
||||
continue;
|
||||
}
|
||||
|
||||
var pos = body.length - 1;
|
||||
if (trimmed == 'important' && body[pos][0] == '!') {
|
||||
context.track(trimmed);
|
||||
body[pos - 1][0] += '!important';
|
||||
body.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trimmed == '!important' || (trimmed == 'important' && body[pos][0][body[pos][0].length - 1] == '!')) {
|
||||
context.track(trimmed);
|
||||
body[pos][0] += trimmed;
|
||||
continue;
|
||||
}
|
||||
|
||||
body.push([trimmed].concat(context.track(value, true)));
|
||||
|
||||
trackComments(innerComments, list, context);
|
||||
|
||||
if (endsWithNonSpaceSeparator) {
|
||||
body.push([lastCharacter]);
|
||||
context.track(lastCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
if (i < l - 1)
|
||||
context.track(';');
|
||||
|
||||
list.push(body);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
module.exports = extractProperties;
|
||||
17
node_modules/jade/node_modules/clean-css/lib/tokenizer/extract-selectors.js
generated
vendored
Normal file
17
node_modules/jade/node_modules/clean-css/lib/tokenizer/extract-selectors.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
var split = require('../utils/split');
|
||||
|
||||
function extractSelectors(string, context) {
|
||||
var list = [];
|
||||
var metadata;
|
||||
var selectors = split(string, ',');
|
||||
|
||||
for (var i = 0, l = selectors.length; i < l; i++) {
|
||||
metadata = context.track(selectors[i], true, i);
|
||||
context.track(',');
|
||||
list.push([selectors[i].trim()].concat(metadata));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
module.exports = extractSelectors;
|
||||
264
node_modules/jade/node_modules/clean-css/lib/tokenizer/tokenize.js
generated
vendored
Normal file
264
node_modules/jade/node_modules/clean-css/lib/tokenizer/tokenize.js
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
var extractProperties = require('./extract-properties');
|
||||
var extractSelectors = require('./extract-selectors');
|
||||
var track = require('../source-maps/track');
|
||||
var split = require('../utils/split');
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var flatBlock = /(@(font\-face|page|\-ms\-viewport|\-o\-viewport|viewport|counter\-style)|\\@.+?)/;
|
||||
|
||||
function tokenize(data, outerContext) {
|
||||
var chunks = split(normalize(data), '}', true, '{', '}');
|
||||
if (chunks.length === 0)
|
||||
return [];
|
||||
|
||||
var context = {
|
||||
chunk: chunks.shift(),
|
||||
chunks: chunks,
|
||||
column: 0,
|
||||
cursor: 0,
|
||||
line: 1,
|
||||
mode: 'top',
|
||||
resolvePath: outerContext.options.explicitTarget ?
|
||||
relativePathResolver(outerContext.options.root, outerContext.options.target) :
|
||||
null,
|
||||
source: undefined,
|
||||
sourceMap: outerContext.options.sourceMap,
|
||||
sourceMapInlineSources: outerContext.options.sourceMapInlineSources,
|
||||
sourceMapTracker: outerContext.inputSourceMapTracker,
|
||||
sourceReader: outerContext.sourceReader,
|
||||
sourceTracker: outerContext.sourceTracker,
|
||||
state: [],
|
||||
track: outerContext.options.sourceMap ?
|
||||
function (data, snapshotMetadata, fallbacks) { return [[track(data, context, snapshotMetadata, fallbacks)]]; } :
|
||||
function () { return []; },
|
||||
warnings: outerContext.warnings
|
||||
};
|
||||
|
||||
return intoTokens(context);
|
||||
}
|
||||
|
||||
function normalize(data) {
|
||||
return data.replace(/\r\n/g, '\n');
|
||||
}
|
||||
|
||||
function relativePathResolver(root, target) {
|
||||
var rebaseTo = path.relative(root, target);
|
||||
|
||||
return function (relativeTo, sourcePath) {
|
||||
return relativeTo != sourcePath ?
|
||||
path.normalize(path.join(path.relative(rebaseTo, path.dirname(relativeTo)), sourcePath)) :
|
||||
sourcePath;
|
||||
};
|
||||
}
|
||||
|
||||
function whatsNext(context) {
|
||||
var mode = context.mode;
|
||||
var chunk = context.chunk;
|
||||
var closest;
|
||||
|
||||
if (chunk.length == context.cursor) {
|
||||
if (context.chunks.length === 0)
|
||||
return null;
|
||||
|
||||
context.chunk = chunk = context.chunks.shift();
|
||||
context.cursor = 0;
|
||||
}
|
||||
|
||||
if (mode == 'body') {
|
||||
if (chunk[context.cursor] == '}')
|
||||
return [context.cursor, 'bodyEnd'];
|
||||
|
||||
if (chunk.indexOf('}', context.cursor) == -1)
|
||||
return null;
|
||||
|
||||
closest = context.cursor + split(chunk.substring(context.cursor - 1), '}', true, '{', '}')[0].length - 2;
|
||||
return [closest, 'bodyEnd'];
|
||||
}
|
||||
|
||||
var nextSpecial = chunk.indexOf('@', context.cursor);
|
||||
var nextEscape = chunk.indexOf('__ESCAPED_', context.cursor);
|
||||
var nextBodyStart = chunk.indexOf('{', context.cursor);
|
||||
var nextBodyEnd = chunk.indexOf('}', context.cursor);
|
||||
|
||||
if (nextEscape > -1 && /\S/.test(chunk.substring(context.cursor, nextEscape)))
|
||||
nextEscape = -1;
|
||||
|
||||
closest = nextSpecial;
|
||||
if (closest == -1 || (nextEscape > -1 && nextEscape < closest))
|
||||
closest = nextEscape;
|
||||
if (closest == -1 || (nextBodyStart > -1 && nextBodyStart < closest))
|
||||
closest = nextBodyStart;
|
||||
if (closest == -1 || (nextBodyEnd > -1 && nextBodyEnd < closest))
|
||||
closest = nextBodyEnd;
|
||||
|
||||
if (closest == -1)
|
||||
return;
|
||||
if (nextEscape === closest)
|
||||
return [closest, 'escape'];
|
||||
if (nextBodyStart === closest)
|
||||
return [closest, 'bodyStart'];
|
||||
if (nextBodyEnd === closest)
|
||||
return [closest, 'bodyEnd'];
|
||||
if (nextSpecial === closest)
|
||||
return [closest, 'special'];
|
||||
}
|
||||
|
||||
function intoTokens(context) {
|
||||
var chunk = context.chunk;
|
||||
var tokenized = [];
|
||||
var newToken;
|
||||
var value;
|
||||
|
||||
while (true) {
|
||||
var next = whatsNext(context);
|
||||
if (!next) {
|
||||
var whatsLeft = context.chunk.substring(context.cursor);
|
||||
if (whatsLeft.trim().length > 0) {
|
||||
if (context.mode == 'body') {
|
||||
context.warnings.push('Missing \'}\' after \'' + whatsLeft + '\'. Ignoring.');
|
||||
} else {
|
||||
tokenized.push(['text', [whatsLeft]]);
|
||||
}
|
||||
context.cursor += whatsLeft.length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
var nextSpecial = next[0];
|
||||
var what = next[1];
|
||||
var nextEnd;
|
||||
var oldMode;
|
||||
|
||||
chunk = context.chunk;
|
||||
|
||||
if (context.cursor != nextSpecial && what != 'bodyEnd') {
|
||||
var spacing = chunk.substring(context.cursor, nextSpecial);
|
||||
var leadingWhitespace = /^\s+/.exec(spacing);
|
||||
|
||||
if (leadingWhitespace) {
|
||||
context.cursor += leadingWhitespace[0].length;
|
||||
context.track(leadingWhitespace[0]);
|
||||
}
|
||||
}
|
||||
|
||||
if (what == 'special') {
|
||||
var firstOpenBraceAt = chunk.indexOf('{', nextSpecial);
|
||||
var firstSemicolonAt = chunk.indexOf(';', nextSpecial);
|
||||
var isSingle = firstSemicolonAt > -1 && (firstOpenBraceAt == -1 || firstSemicolonAt < firstOpenBraceAt);
|
||||
var isBroken = firstOpenBraceAt == -1 && firstSemicolonAt == -1;
|
||||
if (isBroken) {
|
||||
context.warnings.push('Broken declaration: \'' + chunk.substring(context.cursor) + '\'.');
|
||||
context.cursor = chunk.length;
|
||||
} else if (isSingle) {
|
||||
nextEnd = chunk.indexOf(';', nextSpecial + 1);
|
||||
value = chunk.substring(context.cursor, nextEnd + 1);
|
||||
|
||||
tokenized.push([
|
||||
'at-rule',
|
||||
[value].concat(context.track(value, true))
|
||||
]);
|
||||
|
||||
context.track(';');
|
||||
context.cursor = nextEnd + 1;
|
||||
} else {
|
||||
nextEnd = chunk.indexOf('{', nextSpecial + 1);
|
||||
value = chunk.substring(context.cursor, nextEnd);
|
||||
|
||||
var trimmedValue = value.trim();
|
||||
var isFlat = flatBlock.test(trimmedValue);
|
||||
oldMode = context.mode;
|
||||
context.cursor = nextEnd + 1;
|
||||
context.mode = isFlat ? 'body' : 'block';
|
||||
|
||||
newToken = [
|
||||
isFlat ? 'flat-block' : 'block'
|
||||
];
|
||||
|
||||
newToken.push([trimmedValue].concat(context.track(value, true)));
|
||||
context.track('{');
|
||||
newToken.push(intoTokens(context));
|
||||
|
||||
if (typeof newToken[2] == 'string')
|
||||
newToken[2] = extractProperties(newToken[2], [[trimmedValue]], context);
|
||||
|
||||
context.mode = oldMode;
|
||||
context.track('}');
|
||||
|
||||
tokenized.push(newToken);
|
||||
}
|
||||
} else if (what == 'escape') {
|
||||
nextEnd = chunk.indexOf('__', nextSpecial + 1);
|
||||
var escaped = chunk.substring(context.cursor, nextEnd + 2);
|
||||
var isStartSourceMarker = !!context.sourceTracker.nextStart(escaped);
|
||||
var isEndSourceMarker = !!context.sourceTracker.nextEnd(escaped);
|
||||
|
||||
if (isStartSourceMarker) {
|
||||
context.track(escaped);
|
||||
context.state.push({
|
||||
source: context.source,
|
||||
line: context.line,
|
||||
column: context.column
|
||||
});
|
||||
context.source = context.sourceTracker.nextStart(escaped).filename;
|
||||
context.line = 1;
|
||||
context.column = 0;
|
||||
} else if (isEndSourceMarker) {
|
||||
var oldState = context.state.pop();
|
||||
context.source = oldState.source;
|
||||
context.line = oldState.line;
|
||||
context.column = oldState.column;
|
||||
context.track(escaped);
|
||||
} else {
|
||||
if (escaped.indexOf('__ESCAPED_COMMENT_SPECIAL') === 0)
|
||||
tokenized.push(['text', [escaped]]);
|
||||
|
||||
context.track(escaped);
|
||||
}
|
||||
|
||||
context.cursor = nextEnd + 2;
|
||||
} else if (what == 'bodyStart') {
|
||||
var selectors = extractSelectors(chunk.substring(context.cursor, nextSpecial), context);
|
||||
|
||||
oldMode = context.mode;
|
||||
context.cursor = nextSpecial + 1;
|
||||
context.mode = 'body';
|
||||
|
||||
var body = extractProperties(intoTokens(context), selectors, context);
|
||||
|
||||
context.track('{');
|
||||
context.mode = oldMode;
|
||||
|
||||
tokenized.push([
|
||||
'selector',
|
||||
selectors,
|
||||
body
|
||||
]);
|
||||
} else if (what == 'bodyEnd') {
|
||||
// extra closing brace at the top level can be safely ignored
|
||||
if (context.mode == 'top') {
|
||||
var at = context.cursor;
|
||||
var warning = chunk[context.cursor] == '}' ?
|
||||
'Unexpected \'}\' in \'' + chunk.substring(at - 20, at + 20) + '\'. Ignoring.' :
|
||||
'Unexpected content: \'' + chunk.substring(at, nextSpecial + 1) + '\'. Ignoring.';
|
||||
|
||||
context.warnings.push(warning);
|
||||
context.cursor = nextSpecial + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (context.mode == 'block')
|
||||
context.track(chunk.substring(context.cursor, nextSpecial));
|
||||
if (context.mode != 'block')
|
||||
tokenized = chunk.substring(context.cursor, nextSpecial);
|
||||
|
||||
context.cursor = nextSpecial + 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return tokenized;
|
||||
}
|
||||
|
||||
module.exports = tokenize;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user