initial commit
This commit is contained in:
377
node_modules/csso/HISTORY.md
generated
vendored
Normal file
377
node_modules/csso/HISTORY.md
generated
vendored
Normal file
@@ -0,0 +1,377 @@
|
||||
## 3.5.1 (June 7, 2018)
|
||||
|
||||
- Bumped [CSSTree](https://github.com/csstree/csstree) to `1.0.0-alpha.29` (fixes some issues)
|
||||
|
||||
## 3.5.0 (January 14, 2018)
|
||||
|
||||
- Migrated to [CSSTree](https://github.com/csstree/csstree) `1.0.0-alpha.27`
|
||||
|
||||
## 3.4.0 (November 3, 2017)
|
||||
|
||||
- Added percent sign removal for zero percentages for some properties that is safe (@RubaXa, #286)
|
||||
- Removed unit removal for zero values in `-ms-flex` due it breaks flex in IE10/11 (#362)
|
||||
- Improved performance of selectors comparison (@smelukov, #343)
|
||||
|
||||
## 3.3.1 (October 17, 2017)
|
||||
|
||||
- Fixed merge of `position` declarations when `sticky` fallback is using (@gruzzilkin, #356)
|
||||
|
||||
## 3.3.0 (October 12, 2017)
|
||||
|
||||
- Migrated to [CSSTree](https://github.com/csstree/csstree) `1.0.0-alpha25`
|
||||
- Changed AST format (see [CSSTree change log](https://github.com/csstree/csstree/blob/master/HISTORY.md) for details)
|
||||
- Fixed performance issue when generate CSS with source map (quadratic increase in time depending on the size of the CSS)
|
||||
|
||||
## 3.2.0 (September 10, 2017)
|
||||
|
||||
- Fixed named color compression to apply only when an identifier is guaranteed to be a color
|
||||
- Added lifting of `@keyframes` to the beginning of style sheet (chunk), but after `@charset` and `@import` rules
|
||||
- Added removal of `@keyframes`, `@media` and `@supports` with no prelude
|
||||
- Added removal of duplicate `@keyframes` (#202)
|
||||
- Added new option `forceMediaMerge` to force media rules merging. It's unsafe in general, but works fine in many cases. Use it on your own risk (#350)
|
||||
- Bumped `CSSTree` to `1.0.0-alpha23`
|
||||
|
||||
## 3.1.1 (April 25, 2017)
|
||||
|
||||
- Fixed crash on a number processing when it used not in a list (#335)
|
||||
|
||||
## 3.1.0 (April 24, 2017)
|
||||
|
||||
- Implemented optimisation for `none` keyword in `border` and `outline` properties (@zoobestik, #41)
|
||||
- Implemented replacing `rgba(x, x, x, 0)` to `transparent`
|
||||
- Fixed plus sign omitting for numbers following identifier, hex color, number or unicode range, since it can change the meaning of CSS (e.g. `calc(1px+2px)` has been optimized to `calc(1px2px)` before, now it stays the same)
|
||||
- Improved usage filtering for nested selectors (i.e. for `:nth-*()`, `:has()`, `:matches` and other pseudos)
|
||||
- Implemented `blacklist` filtering in usage (#334, see [Black list filtering](https://github.com/css/csso#black-list-filtering))
|
||||
- Improved white space removing, now white spaces are removing in the beginning and at the ending of sequences, and between stylesheet and block nodes
|
||||
- Bumped `CSSTree` to `1.0.0-alpha19`
|
||||
|
||||
## 3.0.1 (March 14, 2017)
|
||||
|
||||
- Fixed declaration merging when declaration contains an `!important`
|
||||
|
||||
## 3.0.0 (March 13, 2017)
|
||||
|
||||
- Migrated to [CSSTree](https://github.com/csstree/csstree) as AST backend and exposed its API behind `syntax` property
|
||||
- Extracted CLI into standalone package [css/csso-cli](https://github.com/css/csso-cli)
|
||||
|
||||
## 2.3.1 (January 6, 2017)
|
||||
|
||||
- Added `\0` IE hack support (#320)
|
||||
|
||||
## 2.3.0 (October 25, 2016)
|
||||
|
||||
- Added `beforeCompress` and `afterCompress` options support (#316)
|
||||
- Fixed crash on empty argument in function (#317)
|
||||
|
||||
## 2.2.1 (July 25, 2016)
|
||||
|
||||
- Fixed shorthand optimisation issue when value has a color value or something unknown (#311)
|
||||
- Fixed `cursor` broken fallback (#306)
|
||||
|
||||
## 2.2.0 (June 23, 2016)
|
||||
|
||||
- Implement AST cloning by adding `clone()` [function](https://github.com/css/csso#cloneast) and `clone` [option](https://github.com/css/csso#compressast-options) for `compress()` function (#296)
|
||||
- Fix parse and translate attribute selector with flags but w/o operator (i.e. `[attrName i]`)
|
||||
- Don't merge rules with flagged attribute selectors with others (#291)
|
||||
- Take in account functions when merge TRBL-properties (#297, thanks to @ArturAralin)
|
||||
- Improve partial merge (#304)
|
||||
- Tweak scanner, reduce code deoptimizations and other small improvements
|
||||
|
||||
## 2.1.1 (May 11, 2016)
|
||||
|
||||
- Fix wrong declaration with `\9` hack merge (#295)
|
||||
|
||||
## 2.1.0 (May 8, 2016)
|
||||
|
||||
- New option `comments` to specify what comments to left: `exclamation`, `first-exclamation` and `none`
|
||||
- Add `offset` to CSS parse error details
|
||||
- Fix token `offset` computation
|
||||
|
||||
## 2.0.0 (April 5, 2016)
|
||||
|
||||
- No more `gonzales` AST format and related code
|
||||
- `minify()` and `minifyBlock()` is always return an object as result now (i.e. `{ css: String, map: SourceMapGenerator or null }`)
|
||||
- `parse()`
|
||||
- Returns AST in new format (so called `internal`)
|
||||
- Dynamic scanner implemented
|
||||
- New AST format + dynamic scanner = performance boost and less memory consumption
|
||||
- No more `context` argument, context should be specified via `options`
|
||||
- Supported contexts now: `stylesheet`, `atrule`, `atruleExpression`, `ruleset`, `selector`, `simpleSelector`, `block`, `declaration` and `value`
|
||||
- Drop `needPositions` option, `positions` option should be used instead
|
||||
- Drop `needInfo` option, `info` object is attaching to nodes when some information is requested by `options`
|
||||
- `options` should be an object, otherwise it treats as empty object
|
||||
- `compress()`
|
||||
- No more AST converting (performance boost and less memory consumption)
|
||||
- Drop `outputAst` option
|
||||
- Returns an object as result instead of AST (i.e. `{ ast: Object }`)
|
||||
- Drop methods: `justDoIt()`, `stringify()`, `cleanInfo()`
|
||||
|
||||
## 1.8.1 (March 30, 2016)
|
||||
|
||||
- Don't remove spaces after function/braces/urls since unsafe (#289)
|
||||
|
||||
## 1.8.0 (March 24, 2016)
|
||||
|
||||
- Usage data support:
|
||||
- Filter rulesets by tag names, class names and ids white lists.
|
||||
- More aggressive ruleset moving using class name scopes information.
|
||||
- New CLI option `--usage` to pass usage data file.
|
||||
- Improve initial ruleset merge
|
||||
- Change order of ruleset processing, now it's left to right. Previously unmerged rulesets may prevent lookup and other rulesets merge.
|
||||
- Difference in pseudo signature just prevents ruleset merging, but don't stop lookup.
|
||||
- Simplify block comparison (performance).
|
||||
- New method `csso.minifyBlock()` for css block compression (e.g. `style` attribute content).
|
||||
- Ruleset merge improvement: at-rules with block (like `@media` or `@supports`) now can be skipped during ruleset merge lookup if doesn't contain something prevents it.
|
||||
- FIX: Add negation (`:not()`) to pseudo signature to avoid unsafe merge (old browsers doesn't support it).
|
||||
- FIX: Check nested parts of value when compute compatibility. It fixes unsafe property merging.
|
||||
|
||||
## 1.7.1 (March 16, 2016)
|
||||
|
||||
- pass block mode to tokenizer for correct parsing of declarations properties with `//` hack
|
||||
- fix wrongly `@import` and `@charset` removal on double exclamation comment
|
||||
|
||||
## 1.7.0 (March 10, 2016)
|
||||
|
||||
- support for [CSS Custom Properties](https://www.w3.org/TR/css-variables/) (#279)
|
||||
- rework RTBL properties merge – better merge for values with special units and don't merge values with CSS-wide keywords (#255)
|
||||
- remove redundant universal selectors (#178)
|
||||
- take in account `!important` when check for property overriding (#280)
|
||||
- don't merge `text-align` declarations with some values (#281)
|
||||
- add spaces around `/deep/` combinator on translate, since it together with universal selector can produce a comment
|
||||
- better keyword and property name resolving (tolerant to hacks and so on)
|
||||
- integration improvements
|
||||
- compression log function could be customized by `logger` option for `compress()` and `minify()`
|
||||
- make possible to set initial line and column for parser
|
||||
|
||||
## 1.6.4 (March 1, 2016)
|
||||
|
||||
- `npm` publish issue (#276)
|
||||
|
||||
## 1.6.3 (February 29, 2016)
|
||||
|
||||
- add `file` to generated source map since other tools can relay on it in source map transform chain
|
||||
|
||||
## 1.6.2 (February 29, 2016)
|
||||
|
||||
- tweak some parse error messages and their positions
|
||||
- fix `:not()` parsing and selector groups in `:not()` is supported now (#215)
|
||||
- `needPosition` parser option is deprecated, `positions` option should be used instead (`needPosition` is used still if `positions` option omitted)
|
||||
- expose internal AST API as `csso.internal.*`
|
||||
- `minify()` adds `sourcesContent` by default when source map is generated
|
||||
- bring back support for node.js `0.10` until major release (#275)
|
||||
|
||||
## 1.6.1 (February 28, 2016)
|
||||
|
||||
- fix exception on zero length dimension compress outside declaration (#273)
|
||||
|
||||
## 1.6.0 (February 27, 2016)
|
||||
|
||||
- **source maps support**
|
||||
- parser remake:
|
||||
- various parsing issues fixed
|
||||
- fix unicode sequence processing in ident (#191)
|
||||
- support for flags in attribute selector (#270)
|
||||
- position (line and column) of parse error (#109)
|
||||
- 4x performance boost, less memory consumption
|
||||
- compressor refactoring
|
||||
- internal AST is using doubly linked lists (with safe transformation support during iteration) instead of arrays
|
||||
- rename `restructuring` to `restructure` option for `minify()`/`compress()` (`restructuring` is alias for `restructure` now, with lower priority)
|
||||
- unquote urls when possible (#141, #60)
|
||||
- setup code coverage and a number of related fixes
|
||||
- add eslint to check unused things
|
||||
|
||||
## 1.5.4 (January 27, 2016)
|
||||
|
||||
- one more fix (in `restructRuleset` this time) with merge of rulesets when a ruleset with same specificity places between them (#264)
|
||||
- disable partial merge of rulesets in `@keyframes` rulesets (until sure it's correct)
|
||||
|
||||
## 1.5.3 (January 25, 2016)
|
||||
|
||||
- don't override display values with different browser support (#259)
|
||||
- fix publish issue (one of modules leak in development state)
|
||||
|
||||
## 1.5.2 (January 24, 2016)
|
||||
|
||||
- don't merge rulesets if between them a ruleset with same specificity (#264)
|
||||
|
||||
## 1.5.1 (January 14, 2016)
|
||||
|
||||
- ensure `-` is not used as an identifier in attribute selectors (thanks to @mathiasbynens)
|
||||
- fix broken `justDoIt()` function
|
||||
- various small fixes
|
||||
|
||||
## 1.5.0 (January 14, 2016)
|
||||
|
||||
### Parser
|
||||
|
||||
- attach minus to number
|
||||
|
||||
### Compressor
|
||||
|
||||
- split code base into small modules and related refactoring
|
||||
- introduce internal AST format for compressor (`gonzales`→`internal` and `internal`→`gonzales` convertors, walkers, translator)
|
||||
- various optimizations: no snapshots, using caches and indexes
|
||||
- sort selectors, merge selectors in alphabet order
|
||||
- compute selector's specificity
|
||||
- better ruleset restructuring, improve compression of partially equal blocks
|
||||
- better ruleset merge – not only closest but also disjoined by other rulesets when safe
|
||||
- join `@media` with same query
|
||||
- `outputAst` – new option to specify output AST format (`gonzales` by default for backward compatibility)
|
||||
- remove quotes surrounding attribute values in attribute selectors when possible (#73)
|
||||
- replace `from`→`0%` and `100%`→`to` at `@keyframes` (#205)
|
||||
- prevent partial merge of rulesets at `@keyframes` (#80, #197)
|
||||
|
||||
### API
|
||||
|
||||
- walker for `gonzales` AST was implemented
|
||||
|
||||
### CLI
|
||||
|
||||
- new option `--stat` (output stat in `stderr`)
|
||||
- new optional parameter `level` for `--debug` option
|
||||
|
||||
## 1.4.4 (December 10, 2015)
|
||||
|
||||
- prevent removal of spaces after braces that before identifier that breaking at-rules expressions (#258)
|
||||
|
||||
## 1.4.3 (December 4, 2015)
|
||||
|
||||
- fix unicode-range parsing that cause to wrong function detection (#250)
|
||||
|
||||
## 1.4.2 (November 9, 2015)
|
||||
|
||||
- allow spaces between `progid:` and rest part of value for IE's `filter` property as `autoprefixer` generates this kind of code (#249)
|
||||
- fixes for Windows:
|
||||
- correct processing new lines
|
||||
- normalize file content in test suite
|
||||
- fixes to work in strict mode (#252)
|
||||
- init compressor dictionaries for every css block (#248, #251)
|
||||
- bump uglify-js version
|
||||
|
||||
## 1.4.1 (October 20, 2015)
|
||||
|
||||
- allow merge for `display` property (#167, #244)
|
||||
- more accurate `rect` (`clip` property value) merge
|
||||
- fix typo when specifying options in cli (thanks to @Taritsyn)
|
||||
- fix safe unit values merge with keyword values (#244)
|
||||
- fix wrong descendant combinator removal (#246)
|
||||
- build browser version on `prepublish` (thanks to @silentroach)
|
||||
- parser: store whitespaces as single token (performance and reduce memory consumption)
|
||||
- rearrange compress tests layout
|
||||
|
||||
## 1.4 (October 16, 2015)
|
||||
|
||||
Bringing project back to life. Changed files structure, cleaned up and refactored most of sources.
|
||||
|
||||
### Common
|
||||
|
||||
- single code base (no more `src` folder)
|
||||
- build browser version with `browserify` (no more `make`, and `web` folder), browser version is available at `dist/csso-browser.js`
|
||||
- main file is `lib/index.js` now
|
||||
- minimal `node.js` version is `0.12` now
|
||||
- restrict file list to publish on npm (no more useless folders and files in package)
|
||||
- add `jscs` to control code style
|
||||
- automate `gh-pages` update
|
||||
- util functions reworked
|
||||
- translator reworked
|
||||
- test suite reworked
|
||||
- compressor refactored
|
||||
- initial parser refactoring
|
||||
|
||||
### API
|
||||
|
||||
- new method `minify(src, options)`, options:
|
||||
- `restructuring` – if set to `false`, disable structure optimisations (`true` by default)
|
||||
- `debug` - outputs intermediate state of CSS during compression (`false` by default)
|
||||
- deprecate `justDoIt()` method (use `minify` instead)
|
||||
- rename `treeToString()` method to `stringify()`
|
||||
- drop `printTree()` method
|
||||
- AST node info
|
||||
- `column` and `offset` added
|
||||
- `ln` renamed to `line`
|
||||
- fix line counting across multiple files and input with CR LF (#147)
|
||||
|
||||
### CLI
|
||||
|
||||
- completely reworked, use [clap](https://github.com/lahmatiy/clap) to parse argv
|
||||
- add support for input from stdin (#128)
|
||||
- drop undocumented and obsoleted options `--rule` and `--parser` (suppose nobody use it)
|
||||
- drop `-off` alias for `--restructure-off` as incorrect (only one letter options should starts with single `-`)
|
||||
- new option `--debug` that reflecting to `options.debug` for `minify`
|
||||
|
||||
### Parsing and optimizations
|
||||
|
||||
- keep all exclamation comments (#194)
|
||||
- add `/deep/` combinator support (#209)
|
||||
- attribute selector
|
||||
- allow colon in attribute name (#237)
|
||||
- support for namespaces (#233)
|
||||
- color
|
||||
- support all css/html colors
|
||||
- convert `hsla` to `rgba` and `hls` to `rgb`
|
||||
- convert `rgba` with 1 as alpha value to `rgb` (#122)
|
||||
- interpolate `rgb` and `rgba` percentage values to absolute values
|
||||
- replace percentage values in `rgba` for normalized/interpolated values
|
||||
- lowercase hex colors and color names (#169)
|
||||
- fix color minification when hex value replaced for color name (#176)
|
||||
- fit rgb values to 0..255 range (#181)
|
||||
- calc
|
||||
- remove spaces for multiple operator in calc
|
||||
- don't remove units inside calc (#222)
|
||||
- fix wrong white space removal around `+` and `-` (#228)
|
||||
- don't remove units in `flex` property as it could change value meaning (#200)
|
||||
- don't merge `\9` hack values (#231)
|
||||
- merge property values only if they have the same functions (#150, #227)
|
||||
- don't merge property values with some sort of units (#140, #161)
|
||||
- fix `!important` issue for `top-right-bottom-left` properties (#189)
|
||||
- fix `top-right-bottom-left` properties merge (#139, #175)
|
||||
- support for unicode-range (#148)
|
||||
- don't crash on ruleset with no selector (#135)
|
||||
- tolerant to class names that starts with digit (#99, #105)
|
||||
- fix background compressing (#170)
|
||||
|
||||
## 1.3.12 (October 8, 2015)
|
||||
|
||||
- Case insensitive check for `!important` (#187)
|
||||
- Fix problems with using `csso` as cli command on Windows (#83, #136, #142 and others)
|
||||
- Remove byte order marker (the UTF-8 BOM) from input
|
||||
- Don't strip space between funktion-funktion and funktion-vhash (#134)
|
||||
- Don't merge TRBL values having \9 (hack for IE8 in bootstrap) (#159, #214, #230, #231 and others)
|
||||
- Don't strip units off dimensions of non-length (#226, #229 and others)
|
||||
|
||||
## 1.3.7 (February 11, 2013)
|
||||
|
||||
- Gonzales 1.0.7.
|
||||
|
||||
## 1.3.6 (November 26, 2012)
|
||||
|
||||
- Gonzales 1.0.6.
|
||||
|
||||
## 1.3.5 (October 28, 2012)
|
||||
|
||||
- Gonzales 1.0.5.
|
||||
- Protecting copyright notices in CSS: https://github.com/css/csso/issues/92
|
||||
- Zero CSS throws an error: https://github.com/css/csso/issues/96
|
||||
- Don't minify the second `0s` in Firefox for animations: https://github.com/css/csso/issues/100
|
||||
- Japan manual
|
||||
- BEM ready documentation
|
||||
|
||||
## 1.3.4 (October 10, 2012)
|
||||
|
||||
- @page inside @media Causes Error: https://github.com/css/csso/issues/90
|
||||
|
||||
## 1.3.3 (October 9, 2012)
|
||||
|
||||
- CSSO 1.3.2 compresses ".t-1" and ".t-01" as identical classes: https://github.com/css/csso/issues/88
|
||||
|
||||
## 1.3.2 (October 8, 2012)
|
||||
|
||||
- filter + important breaks CSSO v1.3.1: https://github.com/css/csso/issues/87
|
||||
|
||||
## 1.3.1 (October 8, 2012)
|
||||
|
||||
- "filter" IE property breaks CSSO v1.3.0: https://github.com/css/csso/issues/86
|
||||
|
||||
## 1.3.0 (October 4, 2012)
|
||||
|
||||
- PeCode CSS parser replaced by Gonzales CSS parser
|
||||
19
node_modules/csso/LICENSE
generated
vendored
Normal file
19
node_modules/csso/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2011-2017 by Sergey Kryzhanovsky
|
||||
|
||||
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.
|
||||
376
node_modules/csso/README.md
generated
vendored
Normal file
376
node_modules/csso/README.md
generated
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
[](https://www.npmjs.com/package/csso)
|
||||
[](https://travis-ci.org/css/csso)
|
||||
[](https://coveralls.io/github/css/csso?branch=master)
|
||||
[](https://www.npmjs.com/package/csso)
|
||||
[](https://twitter.com/cssoptimizer)
|
||||
|
||||
CSSO (CSS Optimizer) is a CSS minifier. It performs three sort of transformations: cleaning (removing redundant), compression (replacement for shorter form) and restructuring (merge of declarations, rulesets and so on). As a result your CSS becomes much smaller.
|
||||
|
||||
[](https://www.yandex.com/)
|
||||
[](https://www.avito.ru/)
|
||||
|
||||
## Ready to use
|
||||
|
||||
- [Web interface](http://css.github.io/csso/csso.html)
|
||||
- [csso-cli](https://github.com/css/csso-cli) – command line interface
|
||||
- [gulp-csso](https://github.com/ben-eb/gulp-csso) – `Gulp` plugin
|
||||
- [grunt-csso](https://github.com/t32k/grunt-csso) – `Grunt` plugin
|
||||
- [broccoli-csso](https://github.com/sindresorhus/broccoli-csso) – `Broccoli` plugin
|
||||
- [postcss-csso](https://github.com/lahmatiy/postcss-csso) – `PostCSS` plugin
|
||||
- [csso-loader](https://github.com/sandark7/csso-loader) – `webpack` loader
|
||||
- [csso-webpack-plugin](https://github.com/zoobestik/csso-webpack-plugin) – `webpack` plugin
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install csso
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [minify\(source\[, options\]\)](#minifysource-options)
|
||||
- [minifyBlock\(source\[, options\]\)](#minifyblocksource-options)
|
||||
- [compress\(ast\[, options\]\)](#compressast-options)
|
||||
- [Source maps](#source-maps)
|
||||
- [Usage data](#usage-data)
|
||||
- [White list filtering](#white-list-filtering)
|
||||
- [Black list filtering](#black-list-filtering)
|
||||
- [Scopes](#scopes)
|
||||
- [Debugging](#debugging)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
Basic usage:
|
||||
|
||||
```js
|
||||
var csso = require('csso');
|
||||
|
||||
var minifiedCss = csso.minify('.test { color: #ff0000; }').css;
|
||||
|
||||
console.log(minifiedCss);
|
||||
// .test{color:red}
|
||||
```
|
||||
|
||||
CSSO is based on [CSSTree](https://github.com/csstree/csstree) to parse CSS into AST, AST traversal and to generate AST back to CSS. All `CSSTree` API is available behind `syntax` field. You may minify CSS step by step:
|
||||
|
||||
```js
|
||||
var csso = require('csso');
|
||||
var ast = csso.syntax.parse('.test { color: #ff0000; }');
|
||||
var compressedAst = csso.compress(ast).ast;
|
||||
var minifiedCss = csso.syntax.generate(compressedAst);
|
||||
|
||||
console.log(minifiedCss);
|
||||
// .test{color:red}
|
||||
```
|
||||
|
||||
> Warning: CSSO uses early versions of CSSTree that still in active development. CSSO doesn't guarantee API behind `syntax` field or AST format will not change in future releases of CSSO, since it's subject to change in CSSTree. Be carefull with CSSO updates if you use `syntax` API until this warning removal.
|
||||
|
||||
### minify(source[, options])
|
||||
|
||||
Minify `source` CSS passed as `String`.
|
||||
|
||||
```js
|
||||
var result = csso.minify('.test { color: #ff0000; }', {
|
||||
restructure: false, // don't change CSS structure, i.e. don't merge declarations, rulesets etc
|
||||
debug: true // show additional debug information:
|
||||
// true or number from 1 to 3 (greater number - more details)
|
||||
});
|
||||
|
||||
console.log(result.css);
|
||||
// > .test{color:red}
|
||||
```
|
||||
|
||||
Returns an object with properties:
|
||||
|
||||
- css `String` – resulting CSS
|
||||
- map `Object` – instance of [`SourceMapGenerator`](https://github.com/mozilla/source-map#sourcemapgenerator) or `null`
|
||||
|
||||
Options:
|
||||
|
||||
- sourceMap
|
||||
|
||||
Type: `Boolean`
|
||||
Default: `false`
|
||||
|
||||
Generate a source map when `true`.
|
||||
|
||||
- filename
|
||||
|
||||
Type: `String`
|
||||
Default: `'<unknown>'`
|
||||
|
||||
Filename of input CSS, uses for source map generation.
|
||||
|
||||
- debug
|
||||
|
||||
Type: `Boolean`
|
||||
Default: `false`
|
||||
|
||||
Output debug information to `stderr`.
|
||||
|
||||
- beforeCompress
|
||||
|
||||
Type: `function(ast, options)` or `Array<function(ast, options)>` or `null`
|
||||
Default: `null`
|
||||
|
||||
Called right after parse is run.
|
||||
|
||||
- afterCompress
|
||||
|
||||
Type: `function(compressResult, options)` or `Array<function(compressResult, options)>` or `null`
|
||||
Default: `null`
|
||||
|
||||
Called right after [`compress()`](#compressast-options) is run.
|
||||
|
||||
- Other options are the same as for [`compress()`](#compressast-options) function.
|
||||
|
||||
### minifyBlock(source[, options])
|
||||
|
||||
The same as `minify()` but for list of declarations. Usually it's a `style` attribute value.
|
||||
|
||||
```js
|
||||
var result = csso.minifyBlock('color: rgba(255, 0, 0, 1); color: #ff0000');
|
||||
|
||||
console.log(result.css);
|
||||
// > color:red
|
||||
```
|
||||
|
||||
### compress(ast[, options])
|
||||
|
||||
Does the main task – compress an AST.
|
||||
|
||||
> NOTE: `compress()` performs AST compression by transforming input AST by default (since AST cloning is expensive and needed in rare cases). Use `clone` option with truthy value in case you want to keep input AST untouched.
|
||||
|
||||
Returns an object with properties:
|
||||
|
||||
- ast `Object` – resulting AST
|
||||
|
||||
Options:
|
||||
|
||||
- restructure
|
||||
|
||||
Type: `Boolean`
|
||||
Default: `true`
|
||||
|
||||
Disable or enable a structure optimisations.
|
||||
|
||||
- forceMediaMerge
|
||||
|
||||
Type: `Boolean`
|
||||
Default: `false`
|
||||
|
||||
Enables merging of `@media` rules with the same media query by splitted by other rules. The optimisation is unsafe in general, but should work fine in most cases. Use it on your own risk.
|
||||
|
||||
- clone
|
||||
|
||||
Type: `Boolean`
|
||||
Default: `false`
|
||||
|
||||
Transform a copy of input AST if `true`. Useful in case of AST reuse.
|
||||
|
||||
- comments
|
||||
|
||||
Type: `String` or `Boolean`
|
||||
Default: `true`
|
||||
|
||||
Specify what comments to leave:
|
||||
|
||||
- `'exclamation'` or `true` – leave all exclamation comments (i.e. `/*! .. */`)
|
||||
- `'first-exclamation'` – remove every comment except first one
|
||||
- `false` – remove all comments
|
||||
|
||||
- usage
|
||||
|
||||
Type: `Object` or `null`
|
||||
Default: `null`
|
||||
|
||||
Usage data for advanced optimisations (see [Usage data](#usage-data) for details)
|
||||
|
||||
- logger
|
||||
|
||||
Type: `Function` or `null`
|
||||
Default: `null`
|
||||
|
||||
Function to track every step of transformation.
|
||||
|
||||
### Source maps
|
||||
|
||||
To get a source map set `true` for `sourceMap` option. Additianaly `filename` option can be passed to specify source file. When `sourceMap` option is `true`, `map` field of result object will contain a [`SourceMapGenerator`](https://github.com/mozilla/source-map#sourcemapgenerator) instance. This object can be mixed with another source map or translated to string.
|
||||
|
||||
```js
|
||||
var csso = require('csso');
|
||||
var css = fs.readFileSync('path/to/my.css', 'utf8');
|
||||
var result = csso.minify(css, {
|
||||
filename: 'path/to/my.css', // will be added to source map as reference to source file
|
||||
sourceMap: true // generate source map
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
// { css: '...minified...', map: SourceMapGenerator {} }
|
||||
|
||||
console.log(result.map.toString());
|
||||
// '{ .. source map content .. }'
|
||||
```
|
||||
|
||||
Example of generating source map with respect of source map from input CSS:
|
||||
|
||||
```js
|
||||
var require('source-map');
|
||||
var csso = require('csso');
|
||||
var inputFile = 'path/to/my.css';
|
||||
var input = fs.readFileSync(inputFile, 'utf8');
|
||||
var inputMap = input.match(/\/\*# sourceMappingURL=(\S+)\s*\*\/\s*$/);
|
||||
var output = csso.minify(input, {
|
||||
filename: inputFile,
|
||||
sourceMap: true
|
||||
});
|
||||
|
||||
// apply input source map to output
|
||||
if (inputMap) {
|
||||
output.map.applySourceMap(
|
||||
new SourceMapConsumer(inputMap[1]),
|
||||
inputFile
|
||||
)
|
||||
}
|
||||
|
||||
// result CSS with source map
|
||||
console.log(
|
||||
output.css +
|
||||
'/*# sourceMappingURL=data:application/json;base64,' +
|
||||
new Buffer(output.map.toString()).toString('base64') +
|
||||
' */'
|
||||
);
|
||||
```
|
||||
|
||||
### Usage data
|
||||
|
||||
`CSSO` can use data about how `CSS` is used in a markup for better compression. File with this data (`JSON`) can be set using `usage` option. Usage data may contain following sections:
|
||||
|
||||
- `blacklist` – a set of black lists (see [Black list filtering](#black-list-filtering))
|
||||
- `tags` – white list of tags
|
||||
- `ids` – white list of ids
|
||||
- `classes` – white list of classes
|
||||
- `scopes` – groups of classes which never used with classes from other groups on the same element
|
||||
|
||||
All sections are optional. Value of `tags`, `ids` and `classes` should be an array of a string, value of `scopes` should be an array of arrays of strings. Other values are ignoring.
|
||||
|
||||
#### White list filtering
|
||||
|
||||
`tags`, `ids` and `classes` are using on clean stage to filter selectors that contain something not in the lists. Selectors are filtering only by those kind of simple selector which white list is specified. For example, if only `tags` list is specified then type selectors are checking, and if all type selectors in selector present in list or selector has no any type selector it isn't filter.
|
||||
|
||||
> `ids` and `classes` are case sensitive, `tags` – is not.
|
||||
|
||||
Input CSS:
|
||||
|
||||
```css
|
||||
* { color: green; }
|
||||
ul, ol, li { color: blue; }
|
||||
UL.foo, span.bar { color: red; }
|
||||
```
|
||||
|
||||
Usage data:
|
||||
|
||||
```json
|
||||
{
|
||||
"tags": ["ul", "LI"]
|
||||
}
|
||||
```
|
||||
|
||||
Resulting CSS:
|
||||
|
||||
```css
|
||||
*{color:green}ul,li{color:blue}ul.foo{color:red}
|
||||
```
|
||||
|
||||
Filtering performs for nested selectors too. `:not()` pseudos content is ignoring since the result of matching is unpredictable. Example for the same usage data as above:
|
||||
|
||||
```css
|
||||
:nth-child(2n of ul, ol) { color: red }
|
||||
:nth-child(3n + 1 of img) { color: yellow }
|
||||
:not(div, ol, ul) { color: green }
|
||||
:has(:matches(ul, ol), ul, ol) { color: blue }
|
||||
```
|
||||
|
||||
Turns into:
|
||||
|
||||
```css
|
||||
:nth-child(2n of ul){color:red}:not(div,ol,ul){color:green}:has(:matches(ul),ul){color:blue}
|
||||
```
|
||||
|
||||
#### Black list filtering
|
||||
|
||||
Black list filtering performs the same as white list filtering, but filters things that mentioned in the lists. `blacklist` can contain the lists `tags`, `ids` and `classes`.
|
||||
|
||||
Black list has a higher priority, so when something mentioned in the white list and in the black list then white list occurrence is ignoring. The `:not()` pseudos content ignoring as well.
|
||||
|
||||
```css
|
||||
* { color: green; }
|
||||
ul, ol, li { color: blue; }
|
||||
UL.foo, li.bar { color: red; }
|
||||
```
|
||||
|
||||
Usage data:
|
||||
|
||||
```json
|
||||
{
|
||||
"blacklist": {
|
||||
"tags": ["ul"]
|
||||
},
|
||||
"tags": ["ul", "LI"]
|
||||
}
|
||||
```
|
||||
|
||||
Resulting CSS:
|
||||
|
||||
```css
|
||||
*{color:green}li{color:blue}li.bar{color:red}
|
||||
```
|
||||
|
||||
#### Scopes
|
||||
|
||||
Scopes is designed for CSS scope isolation solutions such as [css-modules](https://github.com/css-modules/css-modules). Scopes are similar to namespaces and define lists of class names that exclusively used on some markup. This information allows the optimizer to move rules more agressive. Since it assumes selectors from different scopes don't match for the same element. This can improve rule merging.
|
||||
|
||||
Suppose we have a file:
|
||||
|
||||
```css
|
||||
.module1-foo { color: red; }
|
||||
.module1-bar { font-size: 1.5em; background: yellow; }
|
||||
|
||||
.module2-baz { color: red; }
|
||||
.module2-qux { font-size: 1.5em; background: yellow; width: 50px; }
|
||||
```
|
||||
|
||||
It can be assumed that first two rules are never used with the second two on the same markup. But we can't say that for sure without a markup review. The optimizer doesn't know it either and will perform safe transformations only. The result will be the same as input but with no spaces and some semicolons:
|
||||
|
||||
```css
|
||||
.module1-foo{color:red}.module1-bar{font-size:1.5em;background:#ff0}.module2-baz{color:red}.module2-qux{font-size:1.5em;background:#ff0;width:50px}
|
||||
```
|
||||
|
||||
With usage data `CSSO` can produce better output. If follow usage data is provided:
|
||||
|
||||
```json
|
||||
{
|
||||
"scopes": [
|
||||
["module1-foo", "module1-bar"],
|
||||
["module2-baz", "module2-qux"]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The result will be (29 bytes extra saving):
|
||||
|
||||
```css
|
||||
.module1-foo,.module2-baz{color:red}.module1-bar,.module2-qux{font-size:1.5em;background:#ff0}.module2-qux{width:50px}
|
||||
```
|
||||
|
||||
If class name isn't mentioned in the `scopes` it belongs to default scope. `scopes` data doesn't affect `classes` whitelist. If class name mentioned in `scopes` but missed in `classes` (both sections are specified) it will be filtered.
|
||||
|
||||
Note that class name can't be set for several scopes. Also a selector can't have class names from different scopes. In both cases an exception will thrown.
|
||||
|
||||
Currently the optimizer doesn't care about changing order safety for out-of-bounds selectors (i.e. selectors that match to elements without class name, e.g. `.scope div` or `.scope ~ :last-child`). It assumes that scoped CSS modules doesn't relay on it's order. It may be fix in future if to be an issue.
|
||||
|
||||
### Debugging
|
||||
|
||||
> TODO
|
||||
7
node_modules/csso/dist/csso-browser.js
generated
vendored
Normal file
7
node_modules/csso/dist/csso-browser.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
65
node_modules/csso/lib/clean/Atrule.js
generated
vendored
Normal file
65
node_modules/csso/lib/clean/Atrule.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
var resolveKeyword = require('css-tree').keyword;
|
||||
|
||||
module.exports = function cleanAtrule(node, item, list) {
|
||||
if (node.block) {
|
||||
// otherwise removed at-rule don't prevent @import for removal
|
||||
if (this.stylesheet !== null) {
|
||||
this.stylesheet.firstAtrulesAllowed = false;
|
||||
}
|
||||
|
||||
if (node.block.children.isEmpty()) {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (node.name) {
|
||||
case 'charset':
|
||||
if (!node.prelude || node.prelude.children.isEmpty()) {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is any rule before @charset -> remove it
|
||||
if (item.prev) {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'import':
|
||||
if (this.stylesheet === null || !this.stylesheet.firstAtrulesAllowed) {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
// if there are some rules that not an @import or @charset before @import
|
||||
// remove it
|
||||
list.prevUntil(item.prev, function(rule) {
|
||||
if (rule.type === 'Atrule') {
|
||||
if (rule.name === 'import' || rule.name === 'charset') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.root.firstAtrulesAllowed = false;
|
||||
list.remove(item);
|
||||
return true;
|
||||
}, this);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
var name = resolveKeyword(node.name).basename;
|
||||
if (name === 'keyframes' ||
|
||||
name === 'media' ||
|
||||
name === 'supports') {
|
||||
|
||||
// drop at-rule with no prelude
|
||||
if (!node.prelude || node.prelude.children.isEmpty()) {
|
||||
list.remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
3
node_modules/csso/lib/clean/Comment.js
generated
vendored
Normal file
3
node_modules/csso/lib/clean/Comment.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function cleanComment(data, item, list) {
|
||||
list.remove(item);
|
||||
};
|
||||
5
node_modules/csso/lib/clean/Declaration.js
generated
vendored
Normal file
5
node_modules/csso/lib/clean/Declaration.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = function cleanDeclartion(node, item, list) {
|
||||
if (node.value.children && node.value.children.isEmpty()) {
|
||||
list.remove(item);
|
||||
}
|
||||
};
|
||||
14
node_modules/csso/lib/clean/Operator.js
generated
vendored
Normal file
14
node_modules/csso/lib/clean/Operator.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// remove white spaces around operators when safe
|
||||
module.exports = function cleanWhitespace(node, item, list) {
|
||||
if (node.value === '+' || node.value === '-') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.prev !== null && item.prev.data.type === 'WhiteSpace') {
|
||||
list.remove(item.prev);
|
||||
}
|
||||
|
||||
if (item.next !== null && item.next.data.type === 'WhiteSpace') {
|
||||
list.remove(item.next);
|
||||
}
|
||||
};
|
||||
87
node_modules/csso/lib/clean/Rule.js
generated
vendored
Normal file
87
node_modules/csso/lib/clean/Rule.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var walk = require('css-tree').walk;
|
||||
|
||||
function cleanUnused(selectorList, usageData) {
|
||||
selectorList.children.each(function(selector, item, list) {
|
||||
var shouldRemove = false;
|
||||
|
||||
walk(selector, function(node) {
|
||||
// ignore nodes in nested selectors
|
||||
if (this.selector === null || this.selector === selectorList) {
|
||||
switch (node.type) {
|
||||
case 'SelectorList':
|
||||
// TODO: remove toLowerCase when pseudo selectors will be normalized
|
||||
// ignore selectors inside :not()
|
||||
if (this['function'] === null || this['function'].name.toLowerCase() !== 'not') {
|
||||
if (cleanUnused(node, usageData)) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ClassSelector':
|
||||
if (usageData.whitelist !== null &&
|
||||
usageData.whitelist.classes !== null &&
|
||||
!hasOwnProperty.call(usageData.whitelist.classes, node.name)) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
if (usageData.blacklist !== null &&
|
||||
usageData.blacklist.classes !== null &&
|
||||
hasOwnProperty.call(usageData.blacklist.classes, node.name)) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'IdSelector':
|
||||
if (usageData.whitelist !== null &&
|
||||
usageData.whitelist.ids !== null &&
|
||||
!hasOwnProperty.call(usageData.whitelist.ids, node.name)) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
if (usageData.blacklist !== null &&
|
||||
usageData.blacklist.ids !== null &&
|
||||
hasOwnProperty.call(usageData.blacklist.ids, node.name)) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'TypeSelector':
|
||||
// TODO: remove toLowerCase when type selectors will be normalized
|
||||
// ignore universal selectors
|
||||
if (node.name.charAt(node.name.length - 1) !== '*') {
|
||||
if (usageData.whitelist !== null &&
|
||||
usageData.whitelist.tags !== null &&
|
||||
!hasOwnProperty.call(usageData.whitelist.tags, node.name.toLowerCase())) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
if (usageData.blacklist !== null &&
|
||||
usageData.blacklist.tags !== null &&
|
||||
hasOwnProperty.call(usageData.blacklist.tags, node.name.toLowerCase())) {
|
||||
shouldRemove = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (shouldRemove) {
|
||||
list.remove(item);
|
||||
}
|
||||
});
|
||||
|
||||
return selectorList.children.isEmpty();
|
||||
}
|
||||
|
||||
module.exports = function cleanRuleset(node, item, list, options) {
|
||||
var usageData = options.usage;
|
||||
|
||||
if (usageData && (usageData.whitelist !== null || usageData.blacklist !== null)) {
|
||||
cleanUnused(node.prelude, usageData);
|
||||
}
|
||||
|
||||
if (node.prelude.children.isEmpty() ||
|
||||
node.block.children.isEmpty()) {
|
||||
list.remove(item);
|
||||
}
|
||||
};
|
||||
19
node_modules/csso/lib/clean/TypeSelector.js
generated
vendored
Normal file
19
node_modules/csso/lib/clean/TypeSelector.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// remove useless universal selector
|
||||
module.exports = function cleanType(node, item, list) {
|
||||
var name = item.data.name;
|
||||
|
||||
// check it's a non-namespaced universal selector
|
||||
if (name !== '*') {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove when universal selector before other selectors
|
||||
var nextType = item.next && item.next.data.type;
|
||||
if (nextType === 'IdSelector' ||
|
||||
nextType === 'ClassSelector' ||
|
||||
nextType === 'AttributeSelector' ||
|
||||
nextType === 'PseudoClassSelector' ||
|
||||
nextType === 'PseudoElementSelector') {
|
||||
list.remove(item);
|
||||
}
|
||||
};
|
||||
19
node_modules/csso/lib/clean/WhiteSpace.js
generated
vendored
Normal file
19
node_modules/csso/lib/clean/WhiteSpace.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
module.exports = function cleanWhitespace(node, item, list) {
|
||||
// remove when first or last item in sequence
|
||||
if (item.next === null || item.prev === null) {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
// remove when previous node is whitespace
|
||||
if (item.prev.data.type === 'WhiteSpace') {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((this.stylesheet !== null && this.stylesheet.children === list) ||
|
||||
(this.block !== null && this.block.children === list)) {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
};
|
||||
20
node_modules/csso/lib/clean/index.js
generated
vendored
Normal file
20
node_modules/csso/lib/clean/index.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var walk = require('css-tree').walk;
|
||||
var handlers = {
|
||||
Atrule: require('./Atrule'),
|
||||
Rule: require('./Rule'),
|
||||
Declaration: require('./Declaration'),
|
||||
TypeSelector: require('./TypeSelector'),
|
||||
Comment: require('./Comment'),
|
||||
Operator: require('./Operator'),
|
||||
WhiteSpace: require('./WhiteSpace')
|
||||
};
|
||||
|
||||
module.exports = function(ast, options) {
|
||||
walk(ast, {
|
||||
leave: function(node, item, list) {
|
||||
if (handlers.hasOwnProperty(node.type)) {
|
||||
handlers[node.type].call(this, node, item, list, options);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
195
node_modules/csso/lib/compress.js
generated
vendored
Normal file
195
node_modules/csso/lib/compress.js
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
var List = require('css-tree').List;
|
||||
var clone = require('css-tree').clone;
|
||||
var usageUtils = require('./usage');
|
||||
var clean = require('./clean');
|
||||
var replace = require('./replace');
|
||||
var restructure = require('./restructure');
|
||||
var walk = require('css-tree').walk;
|
||||
|
||||
function readChunk(children, specialComments) {
|
||||
var buffer = new List();
|
||||
var nonSpaceTokenInBuffer = false;
|
||||
var protectedComment;
|
||||
|
||||
children.nextUntil(children.head, function(node, item, list) {
|
||||
if (node.type === 'Comment') {
|
||||
if (!specialComments || node.value.charAt(0) !== '!') {
|
||||
list.remove(item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nonSpaceTokenInBuffer || protectedComment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
list.remove(item);
|
||||
protectedComment = node;
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.type !== 'WhiteSpace') {
|
||||
nonSpaceTokenInBuffer = true;
|
||||
}
|
||||
|
||||
buffer.insert(list.remove(item));
|
||||
});
|
||||
|
||||
return {
|
||||
comment: protectedComment,
|
||||
stylesheet: {
|
||||
type: 'StyleSheet',
|
||||
loc: null,
|
||||
children: buffer
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function compressChunk(ast, firstAtrulesAllowed, num, options) {
|
||||
options.logger('Compress block #' + num, null, true);
|
||||
|
||||
var seed = 1;
|
||||
|
||||
if (ast.type === 'StyleSheet') {
|
||||
ast.firstAtrulesAllowed = firstAtrulesAllowed;
|
||||
ast.id = seed++;
|
||||
}
|
||||
|
||||
walk(ast, {
|
||||
visit: 'Atrule',
|
||||
enter: function markScopes(node) {
|
||||
if (node.block !== null) {
|
||||
node.block.id = seed++;
|
||||
}
|
||||
}
|
||||
});
|
||||
options.logger('init', ast);
|
||||
|
||||
// remove redundant
|
||||
clean(ast, options);
|
||||
options.logger('clean', ast);
|
||||
|
||||
// replace nodes for shortened forms
|
||||
replace(ast, options);
|
||||
options.logger('replace', ast);
|
||||
|
||||
// structure optimisations
|
||||
if (options.restructuring) {
|
||||
restructure(ast, options);
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
function getCommentsOption(options) {
|
||||
var comments = 'comments' in options ? options.comments : 'exclamation';
|
||||
|
||||
if (typeof comments === 'boolean') {
|
||||
comments = comments ? 'exclamation' : false;
|
||||
} else if (comments !== 'exclamation' && comments !== 'first-exclamation') {
|
||||
comments = false;
|
||||
}
|
||||
|
||||
return comments;
|
||||
}
|
||||
|
||||
function getRestructureOption(options) {
|
||||
return 'restructure' in options ? options.restructure :
|
||||
'restructuring' in options ? options.restructuring :
|
||||
true;
|
||||
}
|
||||
|
||||
function wrapBlock(block) {
|
||||
return new List().appendData({
|
||||
type: 'Rule',
|
||||
loc: null,
|
||||
prelude: {
|
||||
type: 'SelectorList',
|
||||
loc: null,
|
||||
children: new List().appendData({
|
||||
type: 'Selector',
|
||||
loc: null,
|
||||
children: new List().appendData({
|
||||
type: 'TypeSelector',
|
||||
loc: null,
|
||||
name: 'x'
|
||||
})
|
||||
})
|
||||
},
|
||||
block: block
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function compress(ast, options) {
|
||||
ast = ast || { type: 'StyleSheet', loc: null, children: new List() };
|
||||
options = options || {};
|
||||
|
||||
var compressOptions = {
|
||||
logger: typeof options.logger === 'function' ? options.logger : function() {},
|
||||
restructuring: getRestructureOption(options),
|
||||
forceMediaMerge: Boolean(options.forceMediaMerge),
|
||||
usage: options.usage ? usageUtils.buildIndex(options.usage) : false
|
||||
};
|
||||
var specialComments = getCommentsOption(options);
|
||||
var firstAtrulesAllowed = true;
|
||||
var input;
|
||||
var output = new List();
|
||||
var chunk;
|
||||
var chunkNum = 1;
|
||||
var chunkChildren;
|
||||
|
||||
if (options.clone) {
|
||||
ast = clone(ast);
|
||||
}
|
||||
|
||||
if (ast.type === 'StyleSheet') {
|
||||
input = ast.children;
|
||||
ast.children = output;
|
||||
} else {
|
||||
input = wrapBlock(ast);
|
||||
}
|
||||
|
||||
do {
|
||||
chunk = readChunk(input, Boolean(specialComments));
|
||||
compressChunk(chunk.stylesheet, firstAtrulesAllowed, chunkNum++, compressOptions);
|
||||
chunkChildren = chunk.stylesheet.children;
|
||||
|
||||
if (chunk.comment) {
|
||||
// add \n before comment if there is another content in output
|
||||
if (!output.isEmpty()) {
|
||||
output.insert(List.createItem({
|
||||
type: 'Raw',
|
||||
value: '\n'
|
||||
}));
|
||||
}
|
||||
|
||||
output.insert(List.createItem(chunk.comment));
|
||||
|
||||
// add \n after comment if chunk is not empty
|
||||
if (!chunkChildren.isEmpty()) {
|
||||
output.insert(List.createItem({
|
||||
type: 'Raw',
|
||||
value: '\n'
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (firstAtrulesAllowed && !chunkChildren.isEmpty()) {
|
||||
var lastRule = chunkChildren.last();
|
||||
|
||||
if (lastRule.type !== 'Atrule' ||
|
||||
(lastRule.name !== 'import' && lastRule.name !== 'charset')) {
|
||||
firstAtrulesAllowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialComments !== 'exclamation') {
|
||||
specialComments = false;
|
||||
}
|
||||
|
||||
output.appendList(chunkChildren);
|
||||
} while (!input.isEmpty());
|
||||
|
||||
return {
|
||||
ast: ast
|
||||
};
|
||||
};
|
||||
142
node_modules/csso/lib/index.js
generated
vendored
Normal file
142
node_modules/csso/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
var csstree = require('css-tree');
|
||||
var parse = csstree.parse;
|
||||
var compress = require('./compress');
|
||||
var generate = csstree.generate;
|
||||
|
||||
function debugOutput(name, options, startTime, data) {
|
||||
if (options.debug) {
|
||||
console.error('## ' + name + ' done in %d ms\n', Date.now() - startTime);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function createDefaultLogger(level) {
|
||||
var lastDebug;
|
||||
|
||||
return function logger(title, ast) {
|
||||
var line = title;
|
||||
|
||||
if (ast) {
|
||||
line = '[' + ((Date.now() - lastDebug) / 1000).toFixed(3) + 's] ' + line;
|
||||
}
|
||||
|
||||
if (level > 1 && ast) {
|
||||
var css = generate(ast);
|
||||
|
||||
// when level 2, limit css to 256 symbols
|
||||
if (level === 2 && css.length > 256) {
|
||||
css = css.substr(0, 256) + '...';
|
||||
}
|
||||
|
||||
line += '\n ' + css + '\n';
|
||||
}
|
||||
|
||||
console.error(line);
|
||||
lastDebug = Date.now();
|
||||
};
|
||||
}
|
||||
|
||||
function copy(obj) {
|
||||
var result = {};
|
||||
|
||||
for (var key in obj) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildCompressOptions(options) {
|
||||
options = copy(options);
|
||||
|
||||
if (typeof options.logger !== 'function' && options.debug) {
|
||||
options.logger = createDefaultLogger(options.debug);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
function runHandler(ast, options, handlers) {
|
||||
if (!Array.isArray(handlers)) {
|
||||
handlers = [handlers];
|
||||
}
|
||||
|
||||
handlers.forEach(function(fn) {
|
||||
fn(ast, options);
|
||||
});
|
||||
}
|
||||
|
||||
function minify(context, source, options) {
|
||||
options = options || {};
|
||||
|
||||
var filename = options.filename || '<unknown>';
|
||||
var result;
|
||||
|
||||
// parse
|
||||
var ast = debugOutput('parsing', options, Date.now(),
|
||||
parse(source, {
|
||||
context: context,
|
||||
filename: filename,
|
||||
positions: Boolean(options.sourceMap)
|
||||
})
|
||||
);
|
||||
|
||||
// before compress handlers
|
||||
if (options.beforeCompress) {
|
||||
debugOutput('beforeCompress', options, Date.now(),
|
||||
runHandler(ast, options, options.beforeCompress)
|
||||
);
|
||||
}
|
||||
|
||||
// compress
|
||||
var compressResult = debugOutput('compress', options, Date.now(),
|
||||
compress(ast, buildCompressOptions(options))
|
||||
);
|
||||
|
||||
// after compress handlers
|
||||
if (options.afterCompress) {
|
||||
debugOutput('afterCompress', options, Date.now(),
|
||||
runHandler(compressResult, options, options.afterCompress)
|
||||
);
|
||||
}
|
||||
|
||||
// generate
|
||||
if (options.sourceMap) {
|
||||
result = debugOutput('generate(sourceMap: true)', options, Date.now(), (function() {
|
||||
var tmp = generate(compressResult.ast, { sourceMap: true });
|
||||
tmp.map._file = filename; // since other tools can relay on file in source map transform chain
|
||||
tmp.map.setSourceContent(filename, source);
|
||||
return tmp;
|
||||
})());
|
||||
} else {
|
||||
result = debugOutput('generate', options, Date.now(), {
|
||||
css: generate(compressResult.ast),
|
||||
map: null
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function minifyStylesheet(source, options) {
|
||||
return minify('stylesheet', source, options);
|
||||
}
|
||||
|
||||
function minifyBlock(source, options) {
|
||||
return minify('declarationList', source, options);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
version: require('../package.json').version,
|
||||
|
||||
// main methods
|
||||
minify: minifyStylesheet,
|
||||
minifyBlock: minifyBlock,
|
||||
|
||||
// compress an AST
|
||||
compress: compress,
|
||||
|
||||
// css syntax parser/walkers/generator/etc
|
||||
syntax: csstree
|
||||
};
|
||||
9
node_modules/csso/lib/replace/Atrule.js
generated
vendored
Normal file
9
node_modules/csso/lib/replace/Atrule.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
var resolveKeyword = require('css-tree').keyword;
|
||||
var compressKeyframes = require('./atrule/keyframes');
|
||||
|
||||
module.exports = function(node) {
|
||||
// compress @keyframe selectors
|
||||
if (resolveKeyword(node.name).basename === 'keyframes') {
|
||||
compressKeyframes(node);
|
||||
}
|
||||
};
|
||||
33
node_modules/csso/lib/replace/AttributeSelector.js
generated
vendored
Normal file
33
node_modules/csso/lib/replace/AttributeSelector.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Can unquote attribute detection
|
||||
// Adopted implementation of Mathias Bynens
|
||||
// https://github.com/mathiasbynens/mothereff.in/blob/master/unquoted-attributes/eff.js
|
||||
var escapesRx = /\\([0-9A-Fa-f]{1,6})(\r\n|[ \t\n\f\r])?|\\./g;
|
||||
var blockUnquoteRx = /^(-?\d|--)|[\u0000-\u002c\u002e\u002f\u003A-\u0040\u005B-\u005E\u0060\u007B-\u009f]/;
|
||||
|
||||
function canUnquote(value) {
|
||||
if (value === '' || value === '-') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Escapes are valid, so replace them with a valid non-empty string
|
||||
value = value.replace(escapesRx, 'a');
|
||||
|
||||
return !blockUnquoteRx.test(value);
|
||||
}
|
||||
|
||||
module.exports = function(node) {
|
||||
var attrValue = node.value;
|
||||
|
||||
if (!attrValue || attrValue.type !== 'String') {
|
||||
return;
|
||||
}
|
||||
|
||||
var unquotedValue = attrValue.value.replace(/^(.)(.*)\1$/, '$2');
|
||||
if (canUnquote(unquotedValue)) {
|
||||
node.value = {
|
||||
type: 'Identifier',
|
||||
loc: attrValue.loc,
|
||||
name: unquotedValue
|
||||
};
|
||||
}
|
||||
};
|
||||
56
node_modules/csso/lib/replace/Dimension.js
generated
vendored
Normal file
56
node_modules/csso/lib/replace/Dimension.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
var packNumber = require('./Number').pack;
|
||||
var LENGTH_UNIT = {
|
||||
// absolute length units
|
||||
'px': true,
|
||||
'mm': true,
|
||||
'cm': true,
|
||||
'in': true,
|
||||
'pt': true,
|
||||
'pc': true,
|
||||
|
||||
// relative length units
|
||||
'em': true,
|
||||
'ex': true,
|
||||
'ch': true,
|
||||
'rem': true,
|
||||
|
||||
// viewport-percentage lengths
|
||||
'vh': true,
|
||||
'vw': true,
|
||||
'vmin': true,
|
||||
'vmax': true,
|
||||
'vm': true
|
||||
};
|
||||
|
||||
module.exports = function compressDimension(node, item) {
|
||||
var value = packNumber(node.value, item);
|
||||
|
||||
node.value = value;
|
||||
|
||||
if (value === '0' && this.declaration !== null && this.atrulePrelude === null) {
|
||||
var unit = node.unit.toLowerCase();
|
||||
|
||||
// only length values can be compressed
|
||||
if (!LENGTH_UNIT.hasOwnProperty(unit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// issue #362: shouldn't remove unit in -ms-flex since it breaks flex in IE10/11
|
||||
// issue #200: shouldn't remove unit in flex since it breaks flex in IE10/11
|
||||
if (this.declaration.property === '-ms-flex' ||
|
||||
this.declaration.property === 'flex') {
|
||||
return;
|
||||
}
|
||||
|
||||
// issue #222: don't remove units inside calc
|
||||
if (this['function'] && this['function'].name === 'calc') {
|
||||
return;
|
||||
}
|
||||
|
||||
item.data = {
|
||||
type: 'Number',
|
||||
loc: node.loc,
|
||||
value: value
|
||||
};
|
||||
}
|
||||
};
|
||||
39
node_modules/csso/lib/replace/Number.js
generated
vendored
Normal file
39
node_modules/csso/lib/replace/Number.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
var OMIT_PLUSSIGN = /^(?:\+|(-))?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/;
|
||||
var KEEP_PLUSSIGN = /^([\+\-])?0*(\d*)(?:\.0*|(\.\d*?)0*)?$/;
|
||||
var unsafeToRemovePlusSignAfter = {
|
||||
Dimension: true,
|
||||
HexColor: true,
|
||||
Identifier: true,
|
||||
Number: true,
|
||||
Raw: true,
|
||||
UnicodeRange: true
|
||||
};
|
||||
|
||||
function packNumber(value, item) {
|
||||
// omit plus sign only if no prev or prev is safe type
|
||||
var regexp = item && item.prev !== null && unsafeToRemovePlusSignAfter.hasOwnProperty(item.prev.data.type)
|
||||
? KEEP_PLUSSIGN
|
||||
: OMIT_PLUSSIGN;
|
||||
|
||||
// 100 -> '100'
|
||||
// 00100 -> '100'
|
||||
// +100 -> '100' (only when safe, e.g. omitting plus sign for 1px+1px leads to single dimension instead of two)
|
||||
// -100 -> '-100'
|
||||
// 0.123 -> '.123'
|
||||
// 0.12300 -> '.123'
|
||||
// 0.0 -> ''
|
||||
// 0 -> ''
|
||||
// -0 -> '-'
|
||||
value = String(value).replace(regexp, '$1$2$3');
|
||||
|
||||
if (value === '' || value === '-') {
|
||||
value = '0';
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
module.exports = function(node, item) {
|
||||
node.value = packNumber(node.value, item);
|
||||
};
|
||||
module.exports.pack = packNumber;
|
||||
55
node_modules/csso/lib/replace/Percentage.js
generated
vendored
Normal file
55
node_modules/csso/lib/replace/Percentage.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
var packNumber = require('./Number').pack;
|
||||
var PERCENTAGE_LENGTH_PROPERTY = {
|
||||
'margin': true,
|
||||
'margin-top': true,
|
||||
'margin-left': true,
|
||||
'margin-bottom': true,
|
||||
'margin-right': true,
|
||||
|
||||
'padding': true,
|
||||
'padding-top': true,
|
||||
'padding-left': true,
|
||||
'padding-bottom': true,
|
||||
'padding-right': true,
|
||||
|
||||
'top': true,
|
||||
'left': true,
|
||||
'bottom': true,
|
||||
'right': true,
|
||||
|
||||
'background-position': true,
|
||||
'background-position-x': true,
|
||||
'background-position-y': true,
|
||||
'background-size': true,
|
||||
|
||||
'border': true,
|
||||
'border-width': true,
|
||||
'border-top-width': true,
|
||||
'border-left-width': true,
|
||||
'border-bottom-width': true,
|
||||
'border-right-width': true,
|
||||
'border-image-width': true,
|
||||
|
||||
'border-radius': true,
|
||||
'border-bottom-left-radius': true,
|
||||
'border-bottom-right-radius': true,
|
||||
'border-top-left-radius': true,
|
||||
'border-top-right-radius': true
|
||||
};
|
||||
|
||||
module.exports = function compressPercentage(node, item) {
|
||||
var value = packNumber(node.value, item);
|
||||
var property = this.declaration !== null ? this.declaration.property : null;
|
||||
|
||||
node.value = value;
|
||||
|
||||
if (property !== null && PERCENTAGE_LENGTH_PROPERTY.hasOwnProperty(property)) {
|
||||
if (value === '0') {
|
||||
item.data = {
|
||||
type: 'Number',
|
||||
loc: node.loc,
|
||||
value: value
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
12
node_modules/csso/lib/replace/String.js
generated
vendored
Normal file
12
node_modules/csso/lib/replace/String.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = function(node) {
|
||||
var value = node.value;
|
||||
|
||||
// remove escaped newlines, i.e.
|
||||
// .a { content: "foo\
|
||||
// bar"}
|
||||
// ->
|
||||
// .a { content: "foobar" }
|
||||
value = value.replace(/\\(\r\n|\r|\n|\f)/g, '');
|
||||
|
||||
node.value = value;
|
||||
};
|
||||
33
node_modules/csso/lib/replace/Url.js
generated
vendored
Normal file
33
node_modules/csso/lib/replace/Url.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
var UNICODE = '\\\\[0-9a-f]{1,6}(\\r\\n|[ \\n\\r\\t\\f])?';
|
||||
var ESCAPE = '(' + UNICODE + '|\\\\[^\\n\\r\\f0-9a-fA-F])';
|
||||
var NONPRINTABLE = '\u0000\u0008\u000b\u000e-\u001f\u007f';
|
||||
var SAFE_URL = new RegExp('^(' + ESCAPE + '|[^\"\'\\(\\)\\\\\\s' + NONPRINTABLE + '])*$', 'i');
|
||||
|
||||
module.exports = function(node) {
|
||||
var value = node.value;
|
||||
|
||||
if (value.type !== 'String') {
|
||||
return;
|
||||
}
|
||||
|
||||
var quote = value.value[0];
|
||||
var url = value.value.substr(1, value.value.length - 2);
|
||||
|
||||
// convert `\\` to `/`
|
||||
url = url.replace(/\\\\/g, '/');
|
||||
|
||||
// remove quotes when safe
|
||||
// https://www.w3.org/TR/css-syntax-3/#url-unquoted-diagram
|
||||
if (SAFE_URL.test(url)) {
|
||||
node.value = {
|
||||
type: 'Raw',
|
||||
loc: node.value.loc,
|
||||
value: url
|
||||
};
|
||||
} else {
|
||||
// use double quotes if string has no double quotes
|
||||
// otherwise use original quotes
|
||||
// TODO: make better quote type selection
|
||||
node.value.value = url.indexOf('"') === -1 ? '"' + url + '"' : quote + url + quote;
|
||||
}
|
||||
};
|
||||
20
node_modules/csso/lib/replace/Value.js
generated
vendored
Normal file
20
node_modules/csso/lib/replace/Value.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var resolveName = require('css-tree').property;
|
||||
var handlers = {
|
||||
'font': require('./property/font'),
|
||||
'font-weight': require('./property/font-weight'),
|
||||
'background': require('./property/background'),
|
||||
'border': require('./property/border'),
|
||||
'outline': require('./property/border')
|
||||
};
|
||||
|
||||
module.exports = function compressValue(node) {
|
||||
if (!this.declaration) {
|
||||
return;
|
||||
}
|
||||
|
||||
var property = resolveName(this.declaration.property);
|
||||
|
||||
if (handlers.hasOwnProperty(property.basename)) {
|
||||
handlers[property.basename](node);
|
||||
}
|
||||
};
|
||||
21
node_modules/csso/lib/replace/atrule/keyframes.js
generated
vendored
Normal file
21
node_modules/csso/lib/replace/atrule/keyframes.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
module.exports = function(node) {
|
||||
node.block.children.each(function(rule) {
|
||||
rule.prelude.children.each(function(simpleselector) {
|
||||
simpleselector.children.each(function(data, item) {
|
||||
if (data.type === 'Percentage' && data.value === '100') {
|
||||
item.data = {
|
||||
type: 'TypeSelector',
|
||||
loc: data.loc,
|
||||
name: 'to'
|
||||
};
|
||||
} else if (data.type === 'TypeSelector' && data.name === 'from') {
|
||||
item.data = {
|
||||
type: 'Percentage',
|
||||
loc: data.loc,
|
||||
value: '0'
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
510
node_modules/csso/lib/replace/color.js
generated
vendored
Normal file
510
node_modules/csso/lib/replace/color.js
generated
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
var lexer = require('css-tree').lexer;
|
||||
var packNumber = require('./Number').pack;
|
||||
|
||||
// http://www.w3.org/TR/css3-color/#svg-color
|
||||
var NAME_TO_HEX = {
|
||||
'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',
|
||||
'darkgrey': 'a9a9a9',
|
||||
'darkgreen': '006400',
|
||||
'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',
|
||||
'grey': '808080',
|
||||
'green': '008000',
|
||||
'greenyellow': 'adff2f',
|
||||
'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',
|
||||
'lightgrey': 'd3d3d3',
|
||||
'lightgreen': '90ee90',
|
||||
'lightpink': 'ffb6c1',
|
||||
'lightsalmon': 'ffa07a',
|
||||
'lightseagreen': '20b2aa',
|
||||
'lightskyblue': '87cefa',
|
||||
'lightslategray': '789',
|
||||
'lightslategrey': '789',
|
||||
'lightsteelblue': 'b0c4de',
|
||||
'lightyellow': 'ffffe0',
|
||||
'lime': '0f0',
|
||||
'limegreen': '32cd32',
|
||||
'linen': 'faf0e6',
|
||||
'magenta': 'f0f',
|
||||
'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': '639',
|
||||
'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 HEX_TO_NAME = {
|
||||
'800000': 'maroon',
|
||||
'800080': 'purple',
|
||||
'808000': 'olive',
|
||||
'808080': 'gray',
|
||||
'00ffff': 'cyan',
|
||||
'f0ffff': 'azure',
|
||||
'f5f5dc': 'beige',
|
||||
'ffe4c4': 'bisque',
|
||||
'000000': 'black',
|
||||
'0000ff': 'blue',
|
||||
'a52a2a': 'brown',
|
||||
'ff7f50': 'coral',
|
||||
'ffd700': 'gold',
|
||||
'008000': 'green',
|
||||
'4b0082': 'indigo',
|
||||
'fffff0': 'ivory',
|
||||
'f0e68c': 'khaki',
|
||||
'00ff00': 'lime',
|
||||
'faf0e6': 'linen',
|
||||
'000080': 'navy',
|
||||
'ffa500': 'orange',
|
||||
'da70d6': 'orchid',
|
||||
'cd853f': 'peru',
|
||||
'ffc0cb': 'pink',
|
||||
'dda0dd': 'plum',
|
||||
'f00': 'red',
|
||||
'ff0000': 'red',
|
||||
'fa8072': 'salmon',
|
||||
'a0522d': 'sienna',
|
||||
'c0c0c0': 'silver',
|
||||
'fffafa': 'snow',
|
||||
'd2b48c': 'tan',
|
||||
'008080': 'teal',
|
||||
'ff6347': 'tomato',
|
||||
'ee82ee': 'violet',
|
||||
'f5deb3': 'wheat',
|
||||
'ffffff': 'white',
|
||||
'ffff00': 'yellow'
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function hslToRgb(h, s, l, a) {
|
||||
var r;
|
||||
var g;
|
||||
var b;
|
||||
|
||||
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 [
|
||||
Math.round(r * 255),
|
||||
Math.round(g * 255),
|
||||
Math.round(b * 255),
|
||||
a
|
||||
];
|
||||
}
|
||||
|
||||
function toHex(value) {
|
||||
value = value.toString(16);
|
||||
return value.length === 1 ? '0' + value : value;
|
||||
}
|
||||
|
||||
function parseFunctionArgs(functionArgs, count, rgb) {
|
||||
var cursor = functionArgs.head;
|
||||
var args = [];
|
||||
var wasValue = false;
|
||||
|
||||
while (cursor !== null) {
|
||||
var node = cursor.data;
|
||||
var type = node.type;
|
||||
|
||||
switch (type) {
|
||||
case 'Number':
|
||||
case 'Percentage':
|
||||
if (wasValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
wasValue = true;
|
||||
args.push({
|
||||
type: type,
|
||||
value: Number(node.value)
|
||||
});
|
||||
break;
|
||||
|
||||
case 'Operator':
|
||||
if (node.value === ',') {
|
||||
if (!wasValue) {
|
||||
return;
|
||||
}
|
||||
wasValue = false;
|
||||
} else if (wasValue || node.value !== '+') {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// something we couldn't understand
|
||||
return;
|
||||
}
|
||||
|
||||
cursor = cursor.next;
|
||||
}
|
||||
|
||||
if (args.length !== count) {
|
||||
// invalid arguments count
|
||||
// TODO: remove those tokens
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.length === 4) {
|
||||
if (args[3].type !== 'Number') {
|
||||
// 4th argument should be a number
|
||||
// TODO: remove those tokens
|
||||
return;
|
||||
}
|
||||
|
||||
args[3].type = 'Alpha';
|
||||
}
|
||||
|
||||
if (rgb) {
|
||||
if (args[0].type !== args[1].type || args[0].type !== args[2].type) {
|
||||
// invalid color, numbers and percentage shouldn't be mixed
|
||||
// TODO: remove those tokens
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (args[0].type !== 'Number' ||
|
||||
args[1].type !== 'Percentage' ||
|
||||
args[2].type !== 'Percentage') {
|
||||
// invalid color, for hsl values should be: number, percentage, percentage
|
||||
// TODO: remove those tokens
|
||||
return;
|
||||
}
|
||||
|
||||
args[0].type = 'Angle';
|
||||
}
|
||||
|
||||
return args.map(function(arg) {
|
||||
var value = Math.max(0, arg.value);
|
||||
|
||||
switch (arg.type) {
|
||||
case 'Number':
|
||||
// fit value to [0..255] range
|
||||
value = Math.min(value, 255);
|
||||
break;
|
||||
|
||||
case 'Percentage':
|
||||
// convert 0..100% to value in [0..255] range
|
||||
value = Math.min(value, 100) / 100;
|
||||
|
||||
if (!rgb) {
|
||||
return value;
|
||||
}
|
||||
|
||||
value = 255 * value;
|
||||
break;
|
||||
|
||||
case 'Angle':
|
||||
// fit value to (-360..360) range
|
||||
return (((value % 360) + 360) % 360) / 360;
|
||||
|
||||
case 'Alpha':
|
||||
// fit value to [0..1] range
|
||||
return Math.min(value, 1);
|
||||
}
|
||||
|
||||
return Math.round(value);
|
||||
});
|
||||
}
|
||||
|
||||
function compressFunction(node, item, list) {
|
||||
var functionName = node.name;
|
||||
var args;
|
||||
|
||||
if (functionName === 'rgba' || functionName === 'hsla') {
|
||||
args = parseFunctionArgs(node.children, 4, functionName === 'rgba');
|
||||
|
||||
if (!args) {
|
||||
// something went wrong
|
||||
return;
|
||||
}
|
||||
|
||||
if (functionName === 'hsla') {
|
||||
args = hslToRgb.apply(null, args);
|
||||
node.name = 'rgba';
|
||||
}
|
||||
|
||||
if (args[3] === 0) {
|
||||
// try to replace `rgba(x, x, x, 0)` to `transparent`
|
||||
// always replace `rgba(0, 0, 0, 0)` to `transparent`
|
||||
// otherwise avoid replacement in gradients since it may break color transition
|
||||
// http://stackoverflow.com/questions/11829410/css3-gradient-rendering-issues-from-transparent-to-white
|
||||
var scopeFunctionName = this['function'] && this['function'].name;
|
||||
if ((args[0] === 0 && args[1] === 0 && args[2] === 0) ||
|
||||
!/^(?:to|from|color-stop)$|gradient$/i.test(scopeFunctionName)) {
|
||||
|
||||
item.data = {
|
||||
type: 'Identifier',
|
||||
loc: node.loc,
|
||||
name: 'transparent'
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (args[3] !== 1) {
|
||||
// replace argument values for normalized/interpolated
|
||||
node.children.each(function(node, item, list) {
|
||||
if (node.type === 'Operator') {
|
||||
if (node.value !== ',') {
|
||||
list.remove(item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
item.data = {
|
||||
type: 'Number',
|
||||
loc: node.loc,
|
||||
value: packNumber(args.shift(), null)
|
||||
};
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise convert to rgb, i.e. rgba(255, 0, 0, 1) -> rgb(255, 0, 0)
|
||||
functionName = 'rgb';
|
||||
}
|
||||
|
||||
if (functionName === 'hsl') {
|
||||
args = args || parseFunctionArgs(node.children, 3, false);
|
||||
|
||||
if (!args) {
|
||||
// something went wrong
|
||||
return;
|
||||
}
|
||||
|
||||
// convert to rgb
|
||||
args = hslToRgb.apply(null, args);
|
||||
functionName = 'rgb';
|
||||
}
|
||||
|
||||
if (functionName === 'rgb') {
|
||||
args = args || parseFunctionArgs(node.children, 3, true);
|
||||
|
||||
if (!args) {
|
||||
// something went wrong
|
||||
return;
|
||||
}
|
||||
|
||||
// check if color is not at the end and not followed by space
|
||||
var next = item.next;
|
||||
if (next && next.data.type !== 'WhiteSpace') {
|
||||
list.insert(list.createItem({
|
||||
type: 'WhiteSpace',
|
||||
value: ' '
|
||||
}), next);
|
||||
}
|
||||
|
||||
item.data = {
|
||||
type: 'HexColor',
|
||||
loc: node.loc,
|
||||
value: toHex(args[0]) + toHex(args[1]) + toHex(args[2])
|
||||
};
|
||||
|
||||
compressHex(item.data, item);
|
||||
}
|
||||
}
|
||||
|
||||
function compressIdent(node, item) {
|
||||
if (this.declaration === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var color = node.name.toLowerCase();
|
||||
|
||||
if (NAME_TO_HEX.hasOwnProperty(color) &&
|
||||
lexer.matchDeclaration(this.declaration).isType(node, 'color')) {
|
||||
var hex = NAME_TO_HEX[color];
|
||||
|
||||
if (hex.length + 1 <= color.length) {
|
||||
// replace for shorter hex value
|
||||
item.data = {
|
||||
type: 'HexColor',
|
||||
loc: node.loc,
|
||||
value: hex
|
||||
};
|
||||
} else {
|
||||
// special case for consistent colors
|
||||
if (color === 'grey') {
|
||||
color = 'gray';
|
||||
}
|
||||
|
||||
// just replace value for lower cased name
|
||||
node.name = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compressHex(node, item) {
|
||||
var color = node.value.toLowerCase();
|
||||
|
||||
// #112233 -> #123
|
||||
if (color.length === 6 &&
|
||||
color[0] === color[1] &&
|
||||
color[2] === color[3] &&
|
||||
color[4] === color[5]) {
|
||||
color = color[0] + color[2] + color[4];
|
||||
}
|
||||
|
||||
if (HEX_TO_NAME[color]) {
|
||||
item.data = {
|
||||
type: 'Identifier',
|
||||
loc: node.loc,
|
||||
name: HEX_TO_NAME[color]
|
||||
};
|
||||
} else {
|
||||
node.value = color;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compressFunction: compressFunction,
|
||||
compressIdent: compressIdent,
|
||||
compressHex: compressHex
|
||||
};
|
||||
24
node_modules/csso/lib/replace/index.js
generated
vendored
Normal file
24
node_modules/csso/lib/replace/index.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
var walk = require('css-tree').walk;
|
||||
var handlers = {
|
||||
Atrule: require('./Atrule'),
|
||||
AttributeSelector: require('./AttributeSelector'),
|
||||
Value: require('./Value'),
|
||||
Dimension: require('./Dimension'),
|
||||
Percentage: require('./Percentage'),
|
||||
Number: require('./Number'),
|
||||
String: require('./String'),
|
||||
Url: require('./Url'),
|
||||
HexColor: require('./color').compressHex,
|
||||
Identifier: require('./color').compressIdent,
|
||||
Function: require('./color').compressFunction
|
||||
};
|
||||
|
||||
module.exports = function(ast) {
|
||||
walk(ast, {
|
||||
leave: function(node, item, list) {
|
||||
if (handlers.hasOwnProperty(node.type)) {
|
||||
handlers[node.type].call(this, node, item, list);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
69
node_modules/csso/lib/replace/property/background.js
generated
vendored
Normal file
69
node_modules/csso/lib/replace/property/background.js
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
var List = require('css-tree').List;
|
||||
|
||||
module.exports = function compressBackground(node) {
|
||||
function lastType() {
|
||||
if (buffer.length) {
|
||||
return buffer[buffer.length - 1].type;
|
||||
}
|
||||
}
|
||||
|
||||
function flush() {
|
||||
if (lastType() === 'WhiteSpace') {
|
||||
buffer.pop();
|
||||
}
|
||||
|
||||
if (!buffer.length) {
|
||||
buffer.unshift(
|
||||
{
|
||||
type: 'Number',
|
||||
loc: null,
|
||||
value: '0'
|
||||
},
|
||||
{
|
||||
type: 'WhiteSpace',
|
||||
value: ' '
|
||||
},
|
||||
{
|
||||
type: 'Number',
|
||||
loc: null,
|
||||
value: '0'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
newValue.push.apply(newValue, buffer);
|
||||
|
||||
buffer = [];
|
||||
}
|
||||
|
||||
var newValue = [];
|
||||
var buffer = [];
|
||||
|
||||
node.children.each(function(node) {
|
||||
if (node.type === 'Operator' && node.value === ',') {
|
||||
flush();
|
||||
newValue.push(node);
|
||||
return;
|
||||
}
|
||||
|
||||
// remove defaults
|
||||
if (node.type === 'Identifier') {
|
||||
if (node.name === 'transparent' ||
|
||||
node.name === 'none' ||
|
||||
node.name === 'repeat' ||
|
||||
node.name === 'scroll') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// don't add redundant spaces
|
||||
if (node.type === 'WhiteSpace' && (!buffer.length || lastType() === 'WhiteSpace')) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.push(node);
|
||||
});
|
||||
|
||||
flush();
|
||||
node.children = new List().fromArray(newValue);
|
||||
};
|
||||
31
node_modules/csso/lib/replace/property/border.js
generated
vendored
Normal file
31
node_modules/csso/lib/replace/property/border.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
function removeItemAndRedundantWhiteSpace(list, item) {
|
||||
var prev = item.prev;
|
||||
var next = item.next;
|
||||
|
||||
if (next !== null) {
|
||||
if (next.data.type === 'WhiteSpace' && (prev === null || prev.data.type === 'WhiteSpace')) {
|
||||
list.remove(next);
|
||||
}
|
||||
} else if (prev !== null && prev.data.type === 'WhiteSpace') {
|
||||
list.remove(prev);
|
||||
}
|
||||
|
||||
list.remove(item);
|
||||
}
|
||||
|
||||
module.exports = function compressBorder(node) {
|
||||
node.children.each(function(node, item, list) {
|
||||
if (node.type === 'Identifier' && node.name.toLowerCase() === 'none') {
|
||||
if (list.head === list.tail) {
|
||||
// replace `none` for zero when `none` is a single term
|
||||
item.data = {
|
||||
type: 'Number',
|
||||
loc: node.loc,
|
||||
value: '0'
|
||||
};
|
||||
} else {
|
||||
removeItemAndRedundantWhiteSpace(list, item);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
22
node_modules/csso/lib/replace/property/font-weight.js
generated
vendored
Normal file
22
node_modules/csso/lib/replace/property/font-weight.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
module.exports = function compressFontWeight(node) {
|
||||
var value = node.children.head.data;
|
||||
|
||||
if (value.type === 'Identifier') {
|
||||
switch (value.name) {
|
||||
case 'normal':
|
||||
node.children.head.data = {
|
||||
type: 'Number',
|
||||
loc: value.loc,
|
||||
value: '400'
|
||||
};
|
||||
break;
|
||||
case 'bold':
|
||||
node.children.head.data = {
|
||||
type: 'Number',
|
||||
loc: value.loc,
|
||||
value: '700'
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
45
node_modules/csso/lib/replace/property/font.js
generated
vendored
Normal file
45
node_modules/csso/lib/replace/property/font.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
module.exports = function compressFont(node) {
|
||||
var list = node.children;
|
||||
|
||||
list.eachRight(function(node, item) {
|
||||
if (node.type === 'Identifier') {
|
||||
if (node.name === 'bold') {
|
||||
item.data = {
|
||||
type: 'Number',
|
||||
loc: node.loc,
|
||||
value: '700'
|
||||
};
|
||||
} else if (node.name === 'normal') {
|
||||
var prev = item.prev;
|
||||
|
||||
if (prev && prev.data.type === 'Operator' && prev.data.value === '/') {
|
||||
this.remove(prev);
|
||||
}
|
||||
|
||||
this.remove(item);
|
||||
} else if (node.name === 'medium') {
|
||||
var next = item.next;
|
||||
|
||||
if (!next || next.data.type !== 'Operator') {
|
||||
this.remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// remove redundant spaces
|
||||
list.each(function(node, item) {
|
||||
if (node.type === 'WhiteSpace') {
|
||||
if (!item.prev || !item.next || item.next.data.type === 'WhiteSpace') {
|
||||
this.remove(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (list.isEmpty()) {
|
||||
list.insert(list.createItem({
|
||||
type: 'Identifier',
|
||||
name: 'normal'
|
||||
}));
|
||||
}
|
||||
};
|
||||
107
node_modules/csso/lib/restructure/1-mergeAtrule.js
generated
vendored
Normal file
107
node_modules/csso/lib/restructure/1-mergeAtrule.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
var List = require('css-tree').List;
|
||||
var resolveKeyword = require('css-tree').keyword;
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var walk = require('css-tree').walk;
|
||||
|
||||
function addRuleToMap(map, item, list, single) {
|
||||
var node = item.data;
|
||||
var name = resolveKeyword(node.name).basename;
|
||||
var id = node.name.toLowerCase() + '/' + (node.prelude ? node.prelude.id : null);
|
||||
|
||||
if (!hasOwnProperty.call(map, name)) {
|
||||
map[name] = Object.create(null);
|
||||
}
|
||||
|
||||
if (single) {
|
||||
delete map[name][id];
|
||||
}
|
||||
|
||||
if (!hasOwnProperty.call(map[name], id)) {
|
||||
map[name][id] = new List();
|
||||
}
|
||||
|
||||
map[name][id].append(list.remove(item));
|
||||
}
|
||||
|
||||
function relocateAtrules(ast, options) {
|
||||
var collected = Object.create(null);
|
||||
var topInjectPoint = null;
|
||||
|
||||
ast.children.each(function(node, item, list) {
|
||||
if (node.type === 'Atrule') {
|
||||
var name = resolveKeyword(node.name).basename;
|
||||
|
||||
switch (name) {
|
||||
case 'keyframes':
|
||||
addRuleToMap(collected, item, list, true);
|
||||
return;
|
||||
|
||||
case 'media':
|
||||
if (options.forceMediaMerge) {
|
||||
addRuleToMap(collected, item, list, false);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (topInjectPoint === null &&
|
||||
name !== 'charset' &&
|
||||
name !== 'import') {
|
||||
topInjectPoint = item;
|
||||
}
|
||||
} else {
|
||||
if (topInjectPoint === null) {
|
||||
topInjectPoint = item;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (var atrule in collected) {
|
||||
for (var id in collected[atrule]) {
|
||||
ast.children.insertList(
|
||||
collected[atrule][id],
|
||||
atrule === 'media' ? null : topInjectPoint
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function isMediaRule(node) {
|
||||
return node.type === 'Atrule' && node.name === 'media';
|
||||
}
|
||||
|
||||
function processAtrule(node, item, list) {
|
||||
if (!isMediaRule(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var prev = item.prev && item.prev.data;
|
||||
|
||||
if (!prev || !isMediaRule(prev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// merge @media with same query
|
||||
if (node.prelude &&
|
||||
prev.prelude &&
|
||||
node.prelude.id === prev.prelude.id) {
|
||||
prev.block.children.appendList(node.block.children);
|
||||
list.remove(item);
|
||||
|
||||
// TODO: use it when we can refer to several points in source
|
||||
// prev.loc = {
|
||||
// primary: prev.loc,
|
||||
// merged: node.loc
|
||||
// };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function rejoinAtrule(ast, options) {
|
||||
relocateAtrules(ast, options);
|
||||
|
||||
walk(ast, {
|
||||
visit: 'Atrule',
|
||||
reverse: true,
|
||||
enter: processAtrule
|
||||
});
|
||||
};
|
||||
47
node_modules/csso/lib/restructure/2-initialMergeRuleset.js
generated
vendored
Normal file
47
node_modules/csso/lib/restructure/2-initialMergeRuleset.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
var walk = require('css-tree').walk;
|
||||
var utils = require('./utils');
|
||||
|
||||
function processRule(node, item, list) {
|
||||
var selectors = node.prelude.children;
|
||||
var declarations = node.block.children;
|
||||
|
||||
list.prevUntil(item.prev, function(prev) {
|
||||
// skip non-ruleset node if safe
|
||||
if (prev.type !== 'Rule') {
|
||||
return utils.unsafeToSkipNode.call(selectors, prev);
|
||||
}
|
||||
|
||||
var prevSelectors = prev.prelude.children;
|
||||
var prevDeclarations = prev.block.children;
|
||||
|
||||
// try to join rulesets with equal pseudo signature
|
||||
if (node.pseudoSignature === prev.pseudoSignature) {
|
||||
// try to join by selectors
|
||||
if (utils.isEqualSelectors(prevSelectors, selectors)) {
|
||||
prevDeclarations.appendList(declarations);
|
||||
list.remove(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to join by declarations
|
||||
if (utils.isEqualDeclarations(declarations, prevDeclarations)) {
|
||||
utils.addSelectors(prevSelectors, selectors);
|
||||
list.remove(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// go to prev ruleset if has no selector similarities
|
||||
return utils.hasSimilarSelectors(selectors, prevSelectors);
|
||||
});
|
||||
}
|
||||
|
||||
// NOTE: direction should be left to right, since rulesets merge to left
|
||||
// ruleset. When direction right to left unmerged rulesets may prevent lookup
|
||||
// TODO: remove initial merge
|
||||
module.exports = function initialMergeRule(ast) {
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
enter: processRule
|
||||
});
|
||||
};
|
||||
42
node_modules/csso/lib/restructure/3-disjoinRuleset.js
generated
vendored
Normal file
42
node_modules/csso/lib/restructure/3-disjoinRuleset.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
var List = require('css-tree').List;
|
||||
var walk = require('css-tree').walk;
|
||||
|
||||
function processRule(node, item, list) {
|
||||
var selectors = node.prelude.children;
|
||||
|
||||
// generate new rule sets:
|
||||
// .a, .b { color: red; }
|
||||
// ->
|
||||
// .a { color: red; }
|
||||
// .b { color: red; }
|
||||
|
||||
// while there are more than 1 simple selector split for rulesets
|
||||
while (selectors.head !== selectors.tail) {
|
||||
var newSelectors = new List();
|
||||
newSelectors.insert(selectors.remove(selectors.head));
|
||||
|
||||
list.insert(list.createItem({
|
||||
type: 'Rule',
|
||||
loc: node.loc,
|
||||
prelude: {
|
||||
type: 'SelectorList',
|
||||
loc: node.prelude.loc,
|
||||
children: newSelectors
|
||||
},
|
||||
block: {
|
||||
type: 'Block',
|
||||
loc: node.block.loc,
|
||||
children: node.block.children.copy()
|
||||
},
|
||||
pseudoSignature: node.pseudoSignature
|
||||
}), item);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function disjoinRule(ast) {
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
reverse: true,
|
||||
enter: processRule
|
||||
});
|
||||
};
|
||||
428
node_modules/csso/lib/restructure/4-restructShorthand.js
generated
vendored
Normal file
428
node_modules/csso/lib/restructure/4-restructShorthand.js
generated
vendored
Normal file
@@ -0,0 +1,428 @@
|
||||
var List = require('css-tree').List;
|
||||
var generate = require('css-tree').generate;
|
||||
var walk = require('css-tree').walk;
|
||||
|
||||
var REPLACE = 1;
|
||||
var REMOVE = 2;
|
||||
var TOP = 0;
|
||||
var RIGHT = 1;
|
||||
var BOTTOM = 2;
|
||||
var LEFT = 3;
|
||||
var SIDES = ['top', 'right', 'bottom', 'left'];
|
||||
var SIDE = {
|
||||
'margin-top': 'top',
|
||||
'margin-right': 'right',
|
||||
'margin-bottom': 'bottom',
|
||||
'margin-left': 'left',
|
||||
|
||||
'padding-top': 'top',
|
||||
'padding-right': 'right',
|
||||
'padding-bottom': 'bottom',
|
||||
'padding-left': 'left',
|
||||
|
||||
'border-top-color': 'top',
|
||||
'border-right-color': 'right',
|
||||
'border-bottom-color': 'bottom',
|
||||
'border-left-color': 'left',
|
||||
'border-top-width': 'top',
|
||||
'border-right-width': 'right',
|
||||
'border-bottom-width': 'bottom',
|
||||
'border-left-width': 'left',
|
||||
'border-top-style': 'top',
|
||||
'border-right-style': 'right',
|
||||
'border-bottom-style': 'bottom',
|
||||
'border-left-style': 'left'
|
||||
};
|
||||
var MAIN_PROPERTY = {
|
||||
'margin': 'margin',
|
||||
'margin-top': 'margin',
|
||||
'margin-right': 'margin',
|
||||
'margin-bottom': 'margin',
|
||||
'margin-left': 'margin',
|
||||
|
||||
'padding': 'padding',
|
||||
'padding-top': 'padding',
|
||||
'padding-right': 'padding',
|
||||
'padding-bottom': 'padding',
|
||||
'padding-left': 'padding',
|
||||
|
||||
'border-color': 'border-color',
|
||||
'border-top-color': 'border-color',
|
||||
'border-right-color': 'border-color',
|
||||
'border-bottom-color': 'border-color',
|
||||
'border-left-color': 'border-color',
|
||||
'border-width': 'border-width',
|
||||
'border-top-width': 'border-width',
|
||||
'border-right-width': 'border-width',
|
||||
'border-bottom-width': 'border-width',
|
||||
'border-left-width': 'border-width',
|
||||
'border-style': 'border-style',
|
||||
'border-top-style': 'border-style',
|
||||
'border-right-style': 'border-style',
|
||||
'border-bottom-style': 'border-style',
|
||||
'border-left-style': 'border-style'
|
||||
};
|
||||
|
||||
function TRBL(name) {
|
||||
this.name = name;
|
||||
this.loc = null;
|
||||
this.iehack = undefined;
|
||||
this.sides = {
|
||||
'top': null,
|
||||
'right': null,
|
||||
'bottom': null,
|
||||
'left': null
|
||||
};
|
||||
}
|
||||
|
||||
TRBL.prototype.getValueSequence = function(declaration, count) {
|
||||
var values = [];
|
||||
var iehack = '';
|
||||
var hasBadValues = declaration.value.children.some(function(child) {
|
||||
var special = false;
|
||||
|
||||
switch (child.type) {
|
||||
case 'Identifier':
|
||||
switch (child.name) {
|
||||
case '\\0':
|
||||
case '\\9':
|
||||
iehack = child.name;
|
||||
return;
|
||||
|
||||
case 'inherit':
|
||||
case 'initial':
|
||||
case 'unset':
|
||||
case 'revert':
|
||||
special = child.name;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Dimension':
|
||||
switch (child.unit) {
|
||||
// is not supported until IE11
|
||||
case 'rem':
|
||||
|
||||
// v* units is too buggy across browsers and better
|
||||
// don't merge values with those units
|
||||
case 'vw':
|
||||
case 'vh':
|
||||
case 'vmin':
|
||||
case 'vmax':
|
||||
case 'vm': // IE9 supporting "vm" instead of "vmin".
|
||||
special = child.unit;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'HexColor': // color
|
||||
case 'Number':
|
||||
case 'Percentage':
|
||||
break;
|
||||
|
||||
case 'Function':
|
||||
special = child.name;
|
||||
break;
|
||||
|
||||
case 'WhiteSpace':
|
||||
return false; // ignore space
|
||||
|
||||
default:
|
||||
return true; // bad value
|
||||
}
|
||||
|
||||
values.push({
|
||||
node: child,
|
||||
special: special,
|
||||
important: declaration.important
|
||||
});
|
||||
});
|
||||
|
||||
if (hasBadValues || values.length > count) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof this.iehack === 'string' && this.iehack !== iehack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.iehack = iehack; // move outside
|
||||
|
||||
return values;
|
||||
};
|
||||
|
||||
TRBL.prototype.canOverride = function(side, value) {
|
||||
var currentValue = this.sides[side];
|
||||
|
||||
return !currentValue || (value.important && !currentValue.important);
|
||||
};
|
||||
|
||||
TRBL.prototype.add = function(name, declaration) {
|
||||
function attemptToAdd() {
|
||||
var sides = this.sides;
|
||||
var side = SIDE[name];
|
||||
|
||||
if (side) {
|
||||
if (side in sides === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var values = this.getValueSequence(declaration, 1);
|
||||
|
||||
if (!values || !values.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// can mix only if specials are equal
|
||||
for (var key in sides) {
|
||||
if (sides[key] !== null && sides[key].special !== values[0].special) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.canOverride(side, values[0])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
sides[side] = values[0];
|
||||
return true;
|
||||
} else if (name === this.name) {
|
||||
var values = this.getValueSequence(declaration, 4);
|
||||
|
||||
if (!values || !values.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (values.length) {
|
||||
case 1:
|
||||
values[RIGHT] = values[TOP];
|
||||
values[BOTTOM] = values[TOP];
|
||||
values[LEFT] = values[TOP];
|
||||
break;
|
||||
|
||||
case 2:
|
||||
values[BOTTOM] = values[TOP];
|
||||
values[LEFT] = values[RIGHT];
|
||||
break;
|
||||
|
||||
case 3:
|
||||
values[LEFT] = values[RIGHT];
|
||||
break;
|
||||
}
|
||||
|
||||
// can mix only if specials are equal
|
||||
for (var i = 0; i < 4; i++) {
|
||||
for (var key in sides) {
|
||||
if (sides[key] !== null && sides[key].special !== values[i].special) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
if (this.canOverride(SIDES[i], values[i])) {
|
||||
sides[SIDES[i]] = values[i];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!attemptToAdd.call(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: use it when we can refer to several points in source
|
||||
// if (this.loc) {
|
||||
// this.loc = {
|
||||
// primary: this.loc,
|
||||
// merged: declaration.loc
|
||||
// };
|
||||
// } else {
|
||||
// this.loc = declaration.loc;
|
||||
// }
|
||||
if (!this.loc) {
|
||||
this.loc = declaration.loc;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
TRBL.prototype.isOkToMinimize = function() {
|
||||
var top = this.sides.top;
|
||||
var right = this.sides.right;
|
||||
var bottom = this.sides.bottom;
|
||||
var left = this.sides.left;
|
||||
|
||||
if (top && right && bottom && left) {
|
||||
var important =
|
||||
top.important +
|
||||
right.important +
|
||||
bottom.important +
|
||||
left.important;
|
||||
|
||||
return important === 0 || important === 4;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
TRBL.prototype.getValue = function() {
|
||||
var result = new List();
|
||||
var sides = this.sides;
|
||||
var values = [
|
||||
sides.top,
|
||||
sides.right,
|
||||
sides.bottom,
|
||||
sides.left
|
||||
];
|
||||
var stringValues = [
|
||||
generate(sides.top.node),
|
||||
generate(sides.right.node),
|
||||
generate(sides.bottom.node),
|
||||
generate(sides.left.node)
|
||||
];
|
||||
|
||||
if (stringValues[LEFT] === stringValues[RIGHT]) {
|
||||
values.pop();
|
||||
if (stringValues[BOTTOM] === stringValues[TOP]) {
|
||||
values.pop();
|
||||
if (stringValues[RIGHT] === stringValues[TOP]) {
|
||||
values.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
if (i) {
|
||||
result.appendData({ type: 'WhiteSpace', value: ' ' });
|
||||
}
|
||||
|
||||
result.appendData(values[i].node);
|
||||
}
|
||||
|
||||
if (this.iehack) {
|
||||
result.appendData({ type: 'WhiteSpace', value: ' ' });
|
||||
result.appendData({
|
||||
type: 'Identifier',
|
||||
loc: null,
|
||||
name: this.iehack
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Value',
|
||||
loc: null,
|
||||
children: result
|
||||
};
|
||||
};
|
||||
|
||||
TRBL.prototype.getDeclaration = function() {
|
||||
return {
|
||||
type: 'Declaration',
|
||||
loc: this.loc,
|
||||
important: this.sides.top.important,
|
||||
property: this.name,
|
||||
value: this.getValue()
|
||||
};
|
||||
};
|
||||
|
||||
function processRule(rule, shorts, shortDeclarations, lastShortSelector) {
|
||||
var declarations = rule.block.children;
|
||||
var selector = rule.prelude.children.first().id;
|
||||
|
||||
rule.block.children.eachRight(function(declaration, item) {
|
||||
var property = declaration.property;
|
||||
|
||||
if (!MAIN_PROPERTY.hasOwnProperty(property)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var key = MAIN_PROPERTY[property];
|
||||
var shorthand;
|
||||
var operation;
|
||||
|
||||
if (!lastShortSelector || selector === lastShortSelector) {
|
||||
if (key in shorts) {
|
||||
operation = REMOVE;
|
||||
shorthand = shorts[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (!shorthand || !shorthand.add(property, declaration)) {
|
||||
operation = REPLACE;
|
||||
shorthand = new TRBL(key);
|
||||
|
||||
// if can't parse value ignore it and break shorthand children
|
||||
if (!shorthand.add(property, declaration)) {
|
||||
lastShortSelector = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
shorts[key] = shorthand;
|
||||
shortDeclarations.push({
|
||||
operation: operation,
|
||||
block: declarations,
|
||||
item: item,
|
||||
shorthand: shorthand
|
||||
});
|
||||
|
||||
lastShortSelector = selector;
|
||||
});
|
||||
|
||||
return lastShortSelector;
|
||||
}
|
||||
|
||||
function processShorthands(shortDeclarations, markDeclaration) {
|
||||
shortDeclarations.forEach(function(item) {
|
||||
var shorthand = item.shorthand;
|
||||
|
||||
if (!shorthand.isOkToMinimize()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.operation === REPLACE) {
|
||||
item.item.data = markDeclaration(shorthand.getDeclaration());
|
||||
} else {
|
||||
item.block.remove(item.item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function restructBlock(ast, indexer) {
|
||||
var stylesheetMap = {};
|
||||
var shortDeclarations = [];
|
||||
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
reverse: true,
|
||||
enter: function(node) {
|
||||
var stylesheet = this.block || this.stylesheet;
|
||||
var ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first().id;
|
||||
var ruleMap;
|
||||
var shorts;
|
||||
|
||||
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) {
|
||||
ruleMap = {
|
||||
lastShortSelector: null
|
||||
};
|
||||
stylesheetMap[stylesheet.id] = ruleMap;
|
||||
} else {
|
||||
ruleMap = stylesheetMap[stylesheet.id];
|
||||
}
|
||||
|
||||
if (ruleMap.hasOwnProperty(ruleId)) {
|
||||
shorts = ruleMap[ruleId];
|
||||
} else {
|
||||
shorts = {};
|
||||
ruleMap[ruleId] = shorts;
|
||||
}
|
||||
|
||||
ruleMap.lastShortSelector = processRule.call(this, node, shorts, shortDeclarations, ruleMap.lastShortSelector);
|
||||
}
|
||||
});
|
||||
|
||||
processShorthands(shortDeclarations, indexer.declaration);
|
||||
};
|
||||
296
node_modules/csso/lib/restructure/6-restructBlock.js
generated
vendored
Normal file
296
node_modules/csso/lib/restructure/6-restructBlock.js
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
var resolveProperty = require('css-tree').property;
|
||||
var resolveKeyword = require('css-tree').keyword;
|
||||
var walk = require('css-tree').walk;
|
||||
var generate = require('css-tree').generate;
|
||||
var fingerprintId = 1;
|
||||
var dontRestructure = {
|
||||
'src': 1 // https://github.com/afelix/csso/issues/50
|
||||
};
|
||||
|
||||
var DONT_MIX_VALUE = {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/display#Browser_compatibility
|
||||
'display': /table|ruby|flex|-(flex)?box$|grid|contents|run-in/i,
|
||||
// https://developer.mozilla.org/en/docs/Web/CSS/text-align
|
||||
'text-align': /^(start|end|match-parent|justify-all)$/i
|
||||
};
|
||||
|
||||
var CURSOR_SAFE_VALUE = [
|
||||
'auto', 'crosshair', 'default', 'move', 'text', 'wait', 'help',
|
||||
'n-resize', 'e-resize', 's-resize', 'w-resize',
|
||||
'ne-resize', 'nw-resize', 'se-resize', 'sw-resize',
|
||||
'pointer', 'progress', 'not-allowed', 'no-drop', 'vertical-text', 'all-scroll',
|
||||
'col-resize', 'row-resize'
|
||||
];
|
||||
|
||||
var POSITION_SAFE_VALUE = [
|
||||
'static', 'relative', 'absolute', 'fixed'
|
||||
];
|
||||
|
||||
var NEEDLESS_TABLE = {
|
||||
'border-width': ['border'],
|
||||
'border-style': ['border'],
|
||||
'border-color': ['border'],
|
||||
'border-top': ['border'],
|
||||
'border-right': ['border'],
|
||||
'border-bottom': ['border'],
|
||||
'border-left': ['border'],
|
||||
'border-top-width': ['border-top', 'border-width', 'border'],
|
||||
'border-right-width': ['border-right', 'border-width', 'border'],
|
||||
'border-bottom-width': ['border-bottom', 'border-width', 'border'],
|
||||
'border-left-width': ['border-left', 'border-width', 'border'],
|
||||
'border-top-style': ['border-top', 'border-style', 'border'],
|
||||
'border-right-style': ['border-right', 'border-style', 'border'],
|
||||
'border-bottom-style': ['border-bottom', 'border-style', 'border'],
|
||||
'border-left-style': ['border-left', 'border-style', 'border'],
|
||||
'border-top-color': ['border-top', 'border-color', 'border'],
|
||||
'border-right-color': ['border-right', 'border-color', 'border'],
|
||||
'border-bottom-color': ['border-bottom', 'border-color', 'border'],
|
||||
'border-left-color': ['border-left', 'border-color', 'border'],
|
||||
'margin-top': ['margin'],
|
||||
'margin-right': ['margin'],
|
||||
'margin-bottom': ['margin'],
|
||||
'margin-left': ['margin'],
|
||||
'padding-top': ['padding'],
|
||||
'padding-right': ['padding'],
|
||||
'padding-bottom': ['padding'],
|
||||
'padding-left': ['padding'],
|
||||
'font-style': ['font'],
|
||||
'font-variant': ['font'],
|
||||
'font-weight': ['font'],
|
||||
'font-size': ['font'],
|
||||
'font-family': ['font'],
|
||||
'list-style-type': ['list-style'],
|
||||
'list-style-position': ['list-style'],
|
||||
'list-style-image': ['list-style']
|
||||
};
|
||||
|
||||
function getPropertyFingerprint(propertyName, declaration, fingerprints) {
|
||||
var realName = resolveProperty(propertyName).basename;
|
||||
|
||||
if (realName === 'background') {
|
||||
return propertyName + ':' + generate(declaration.value);
|
||||
}
|
||||
|
||||
var declarationId = declaration.id;
|
||||
var fingerprint = fingerprints[declarationId];
|
||||
|
||||
if (!fingerprint) {
|
||||
switch (declaration.value.type) {
|
||||
case 'Value':
|
||||
var vendorId = '';
|
||||
var iehack = '';
|
||||
var special = {};
|
||||
var raw = false;
|
||||
|
||||
declaration.value.children.each(function walk(node) {
|
||||
switch (node.type) {
|
||||
case 'Value':
|
||||
case 'Brackets':
|
||||
case 'Parentheses':
|
||||
node.children.each(walk);
|
||||
break;
|
||||
|
||||
case 'Raw':
|
||||
raw = true;
|
||||
break;
|
||||
|
||||
case 'Identifier':
|
||||
var name = node.name;
|
||||
|
||||
if (!vendorId) {
|
||||
vendorId = resolveKeyword(name).vendor;
|
||||
}
|
||||
|
||||
if (/\\[09]/.test(name)) {
|
||||
iehack = RegExp.lastMatch;
|
||||
}
|
||||
|
||||
if (realName === 'cursor') {
|
||||
if (CURSOR_SAFE_VALUE.indexOf(name) === -1) {
|
||||
special[name] = true;
|
||||
}
|
||||
} else if (realName === 'position') {
|
||||
if (POSITION_SAFE_VALUE.indexOf(name) === -1) {
|
||||
special[name] = true;
|
||||
}
|
||||
} else if (DONT_MIX_VALUE.hasOwnProperty(realName)) {
|
||||
if (DONT_MIX_VALUE[realName].test(name)) {
|
||||
special[name] = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'Function':
|
||||
var name = node.name;
|
||||
|
||||
if (!vendorId) {
|
||||
vendorId = resolveKeyword(name).vendor;
|
||||
}
|
||||
|
||||
if (name === 'rect') {
|
||||
// there are 2 forms of rect:
|
||||
// rect(<top>, <right>, <bottom>, <left>) - standart
|
||||
// rect(<top> <right> <bottom> <left>) – backwards compatible syntax
|
||||
// only the same form values can be merged
|
||||
var hasComma = node.children.some(function(node) {
|
||||
return node.type === 'Operator' && node.value === ',';
|
||||
});
|
||||
if (!hasComma) {
|
||||
name = 'rect-backward';
|
||||
}
|
||||
}
|
||||
|
||||
special[name + '()'] = true;
|
||||
|
||||
// check nested tokens too
|
||||
node.children.each(walk);
|
||||
|
||||
break;
|
||||
|
||||
case 'Dimension':
|
||||
var unit = node.unit;
|
||||
|
||||
switch (unit) {
|
||||
// is not supported until IE11
|
||||
case 'rem':
|
||||
|
||||
// v* units is too buggy across browsers and better
|
||||
// don't merge values with those units
|
||||
case 'vw':
|
||||
case 'vh':
|
||||
case 'vmin':
|
||||
case 'vmax':
|
||||
case 'vm': // IE9 supporting "vm" instead of "vmin".
|
||||
special[unit] = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
fingerprint = raw
|
||||
? '!' + fingerprintId++
|
||||
: '!' + Object.keys(special).sort() + '|' + iehack + vendorId;
|
||||
break;
|
||||
|
||||
case 'Raw':
|
||||
fingerprint = '!' + declaration.value.value;
|
||||
break;
|
||||
|
||||
default:
|
||||
fingerprint = generate(declaration.value);
|
||||
}
|
||||
|
||||
fingerprints[declarationId] = fingerprint;
|
||||
}
|
||||
|
||||
return propertyName + fingerprint;
|
||||
}
|
||||
|
||||
function needless(props, declaration, fingerprints) {
|
||||
var property = resolveProperty(declaration.property);
|
||||
|
||||
if (NEEDLESS_TABLE.hasOwnProperty(property.basename)) {
|
||||
var table = NEEDLESS_TABLE[property.basename];
|
||||
|
||||
for (var i = 0; i < table.length; i++) {
|
||||
var ppre = getPropertyFingerprint(property.prefix + table[i], declaration, fingerprints);
|
||||
var prev = props.hasOwnProperty(ppre) ? props[ppre] : null;
|
||||
|
||||
if (prev && (!declaration.important || prev.item.data.important)) {
|
||||
return prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processRule(rule, item, list, props, fingerprints) {
|
||||
var declarations = rule.block.children;
|
||||
|
||||
declarations.eachRight(function(declaration, declarationItem) {
|
||||
var property = declaration.property;
|
||||
var fingerprint = getPropertyFingerprint(property, declaration, fingerprints);
|
||||
var prev = props[fingerprint];
|
||||
|
||||
if (prev && !dontRestructure.hasOwnProperty(property)) {
|
||||
if (declaration.important && !prev.item.data.important) {
|
||||
props[fingerprint] = {
|
||||
block: declarations,
|
||||
item: declarationItem
|
||||
};
|
||||
|
||||
prev.block.remove(prev.item);
|
||||
|
||||
// TODO: use it when we can refer to several points in source
|
||||
// declaration.loc = {
|
||||
// primary: declaration.loc,
|
||||
// merged: prev.item.data.loc
|
||||
// };
|
||||
} else {
|
||||
declarations.remove(declarationItem);
|
||||
|
||||
// TODO: use it when we can refer to several points in source
|
||||
// prev.item.data.loc = {
|
||||
// primary: prev.item.data.loc,
|
||||
// merged: declaration.loc
|
||||
// };
|
||||
}
|
||||
} else {
|
||||
var prev = needless(props, declaration, fingerprints);
|
||||
|
||||
if (prev) {
|
||||
declarations.remove(declarationItem);
|
||||
|
||||
// TODO: use it when we can refer to several points in source
|
||||
// prev.item.data.loc = {
|
||||
// primary: prev.item.data.loc,
|
||||
// merged: declaration.loc
|
||||
// };
|
||||
} else {
|
||||
declaration.fingerprint = fingerprint;
|
||||
|
||||
props[fingerprint] = {
|
||||
block: declarations,
|
||||
item: declarationItem
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (declarations.isEmpty()) {
|
||||
list.remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function restructBlock(ast) {
|
||||
var stylesheetMap = {};
|
||||
var fingerprints = Object.create(null);
|
||||
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
reverse: true,
|
||||
enter: function(node, item, list) {
|
||||
var stylesheet = this.block || this.stylesheet;
|
||||
var ruleId = (node.pseudoSignature || '') + '|' + node.prelude.children.first().id;
|
||||
var ruleMap;
|
||||
var props;
|
||||
|
||||
if (!stylesheetMap.hasOwnProperty(stylesheet.id)) {
|
||||
ruleMap = {};
|
||||
stylesheetMap[stylesheet.id] = ruleMap;
|
||||
} else {
|
||||
ruleMap = stylesheetMap[stylesheet.id];
|
||||
}
|
||||
|
||||
if (ruleMap.hasOwnProperty(ruleId)) {
|
||||
props = ruleMap[ruleId];
|
||||
} else {
|
||||
props = {};
|
||||
ruleMap[ruleId] = props;
|
||||
}
|
||||
|
||||
processRule.call(this, node, item, list, props, fingerprints);
|
||||
}
|
||||
});
|
||||
};
|
||||
86
node_modules/csso/lib/restructure/7-mergeRuleset.js
generated
vendored
Normal file
86
node_modules/csso/lib/restructure/7-mergeRuleset.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
var walk = require('css-tree').walk;
|
||||
var utils = require('./utils');
|
||||
|
||||
/*
|
||||
At this step all rules has single simple selector. We try to join by equal
|
||||
declaration blocks to first rule, e.g.
|
||||
|
||||
.a { color: red }
|
||||
b { ... }
|
||||
.b { color: red }
|
||||
->
|
||||
.a, .b { color: red }
|
||||
b { ... }
|
||||
*/
|
||||
|
||||
function processRule(node, item, list) {
|
||||
var selectors = node.prelude.children;
|
||||
var declarations = node.block.children;
|
||||
var nodeCompareMarker = selectors.first().compareMarker;
|
||||
var skippedCompareMarkers = {};
|
||||
|
||||
list.nextUntil(item.next, function(next, nextItem) {
|
||||
// skip non-ruleset node if safe
|
||||
if (next.type !== 'Rule') {
|
||||
return utils.unsafeToSkipNode.call(selectors, next);
|
||||
}
|
||||
|
||||
if (node.pseudoSignature !== next.pseudoSignature) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var nextFirstSelector = next.prelude.children.head;
|
||||
var nextDeclarations = next.block.children;
|
||||
var nextCompareMarker = nextFirstSelector.data.compareMarker;
|
||||
|
||||
// if next ruleset has same marked as one of skipped then stop joining
|
||||
if (nextCompareMarker in skippedCompareMarkers) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to join by selectors
|
||||
if (selectors.head === selectors.tail) {
|
||||
if (selectors.first().id === nextFirstSelector.data.id) {
|
||||
declarations.appendList(nextDeclarations);
|
||||
list.remove(nextItem);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// try to join by properties
|
||||
if (utils.isEqualDeclarations(declarations, nextDeclarations)) {
|
||||
var nextStr = nextFirstSelector.data.id;
|
||||
|
||||
selectors.some(function(data, item) {
|
||||
var curStr = data.id;
|
||||
|
||||
if (nextStr < curStr) {
|
||||
selectors.insert(nextFirstSelector, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!item.next) {
|
||||
selectors.insert(nextFirstSelector);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
list.remove(nextItem);
|
||||
return;
|
||||
}
|
||||
|
||||
// go to next ruleset if current one can be skipped (has no equal specificity nor element selector)
|
||||
if (nextCompareMarker === nodeCompareMarker) {
|
||||
return true;
|
||||
}
|
||||
|
||||
skippedCompareMarkers[nextCompareMarker] = true;
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function mergeRule(ast) {
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
enter: processRule
|
||||
});
|
||||
};
|
||||
157
node_modules/csso/lib/restructure/8-restructRuleset.js
generated
vendored
Normal file
157
node_modules/csso/lib/restructure/8-restructRuleset.js
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
var List = require('css-tree').List;
|
||||
var walk = require('css-tree').walk;
|
||||
var utils = require('./utils');
|
||||
|
||||
function calcSelectorLength(list) {
|
||||
var length = 0;
|
||||
|
||||
list.each(function(data) {
|
||||
length += data.id.length + 1;
|
||||
});
|
||||
|
||||
return length - 1;
|
||||
}
|
||||
|
||||
function calcDeclarationsLength(tokens) {
|
||||
var length = 0;
|
||||
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
length += tokens[i].length;
|
||||
}
|
||||
|
||||
return (
|
||||
length + // declarations
|
||||
tokens.length - 1 // delimeters
|
||||
);
|
||||
}
|
||||
|
||||
function processRule(node, item, list) {
|
||||
var avoidRulesMerge = this.block !== null ? this.block.avoidRulesMerge : false;
|
||||
var selectors = node.prelude.children;
|
||||
var block = node.block;
|
||||
var disallowDownMarkers = Object.create(null);
|
||||
var allowMergeUp = true;
|
||||
var allowMergeDown = true;
|
||||
|
||||
list.prevUntil(item.prev, function(prev, prevItem) {
|
||||
// skip non-ruleset node if safe
|
||||
if (prev.type !== 'Rule') {
|
||||
return utils.unsafeToSkipNode.call(selectors, prev);
|
||||
}
|
||||
|
||||
var prevSelectors = prev.prelude.children;
|
||||
var prevBlock = prev.block;
|
||||
|
||||
if (node.pseudoSignature !== prev.pseudoSignature) {
|
||||
return true;
|
||||
}
|
||||
|
||||
allowMergeDown = !prevSelectors.some(function(selector) {
|
||||
return selector.compareMarker in disallowDownMarkers;
|
||||
});
|
||||
|
||||
// try prev ruleset if simpleselectors has no equal specifity and element selector
|
||||
if (!allowMergeDown && !allowMergeUp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to join by selectors
|
||||
if (allowMergeUp && utils.isEqualSelectors(prevSelectors, selectors)) {
|
||||
prevBlock.children.appendList(block.children);
|
||||
list.remove(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
// try to join by properties
|
||||
var diff = utils.compareDeclarations(block.children, prevBlock.children);
|
||||
|
||||
// console.log(diff.eq, diff.ne1, diff.ne2);
|
||||
|
||||
if (diff.eq.length) {
|
||||
if (!diff.ne1.length && !diff.ne2.length) {
|
||||
// equal blocks
|
||||
if (allowMergeDown) {
|
||||
utils.addSelectors(selectors, prevSelectors);
|
||||
list.remove(prevItem);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if (!avoidRulesMerge) { /* probably we don't need to prevent those merges for @keyframes
|
||||
TODO: need to be checked */
|
||||
|
||||
if (diff.ne1.length && !diff.ne2.length) {
|
||||
// prevBlock is subset block
|
||||
var selectorLength = calcSelectorLength(selectors);
|
||||
var blockLength = calcDeclarationsLength(diff.eq); // declarations length
|
||||
|
||||
if (allowMergeUp && selectorLength < blockLength) {
|
||||
utils.addSelectors(prevSelectors, selectors);
|
||||
block.children = new List().fromArray(diff.ne1);
|
||||
}
|
||||
} else if (!diff.ne1.length && diff.ne2.length) {
|
||||
// node is subset of prevBlock
|
||||
var selectorLength = calcSelectorLength(prevSelectors);
|
||||
var blockLength = calcDeclarationsLength(diff.eq); // declarations length
|
||||
|
||||
if (allowMergeDown && selectorLength < blockLength) {
|
||||
utils.addSelectors(selectors, prevSelectors);
|
||||
prevBlock.children = new List().fromArray(diff.ne2);
|
||||
}
|
||||
} else {
|
||||
// diff.ne1.length && diff.ne2.length
|
||||
// extract equal block
|
||||
var newSelector = {
|
||||
type: 'SelectorList',
|
||||
loc: null,
|
||||
children: utils.addSelectors(prevSelectors.copy(), selectors)
|
||||
};
|
||||
var newBlockLength = calcSelectorLength(newSelector.children) + 2; // selectors length + curly braces length
|
||||
var blockLength = calcDeclarationsLength(diff.eq); // declarations length
|
||||
|
||||
// create new ruleset if declarations length greater than
|
||||
// ruleset description overhead
|
||||
if (allowMergeDown && blockLength >= newBlockLength) {
|
||||
var newRule = {
|
||||
type: 'Rule',
|
||||
loc: null,
|
||||
prelude: newSelector,
|
||||
block: {
|
||||
type: 'Block',
|
||||
loc: null,
|
||||
children: new List().fromArray(diff.eq)
|
||||
},
|
||||
pseudoSignature: node.pseudoSignature
|
||||
};
|
||||
|
||||
block.children = new List().fromArray(diff.ne1);
|
||||
prevBlock.children = new List().fromArray(diff.ne2.concat(diff.ne2overrided));
|
||||
list.insert(list.createItem(newRule), prevItem);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allowMergeUp) {
|
||||
// TODO: disallow up merge only if any property interception only (i.e. diff.ne2overrided.length > 0);
|
||||
// await property families to find property interception correctly
|
||||
allowMergeUp = !prevSelectors.some(function(prevSelector) {
|
||||
return selectors.some(function(selector) {
|
||||
return selector.compareMarker === prevSelector.compareMarker;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
prevSelectors.each(function(data) {
|
||||
disallowDownMarkers[data.compareMarker] = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function restructRule(ast) {
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
reverse: true,
|
||||
enter: processRule
|
||||
});
|
||||
};
|
||||
35
node_modules/csso/lib/restructure/index.js
generated
vendored
Normal file
35
node_modules/csso/lib/restructure/index.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
var prepare = require('./prepare/index');
|
||||
var mergeAtrule = require('./1-mergeAtrule');
|
||||
var initialMergeRuleset = require('./2-initialMergeRuleset');
|
||||
var disjoinRuleset = require('./3-disjoinRuleset');
|
||||
var restructShorthand = require('./4-restructShorthand');
|
||||
var restructBlock = require('./6-restructBlock');
|
||||
var mergeRuleset = require('./7-mergeRuleset');
|
||||
var restructRuleset = require('./8-restructRuleset');
|
||||
|
||||
module.exports = function(ast, options) {
|
||||
// prepare ast for restructing
|
||||
var indexer = prepare(ast, options);
|
||||
options.logger('prepare', ast);
|
||||
|
||||
mergeAtrule(ast, options);
|
||||
options.logger('mergeAtrule', ast);
|
||||
|
||||
initialMergeRuleset(ast);
|
||||
options.logger('initialMergeRuleset', ast);
|
||||
|
||||
disjoinRuleset(ast);
|
||||
options.logger('disjoinRuleset', ast);
|
||||
|
||||
restructShorthand(ast, indexer);
|
||||
options.logger('restructShorthand', ast);
|
||||
|
||||
restructBlock(ast);
|
||||
options.logger('restructBlock', ast);
|
||||
|
||||
mergeRuleset(ast);
|
||||
options.logger('mergeRuleset', ast);
|
||||
|
||||
restructRuleset(ast);
|
||||
options.logger('restructRuleset', ast);
|
||||
};
|
||||
31
node_modules/csso/lib/restructure/prepare/createDeclarationIndexer.js
generated
vendored
Normal file
31
node_modules/csso/lib/restructure/prepare/createDeclarationIndexer.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
var generate = require('css-tree').generate;
|
||||
|
||||
function Index() {
|
||||
this.seed = 0;
|
||||
this.map = Object.create(null);
|
||||
}
|
||||
|
||||
Index.prototype.resolve = function(str) {
|
||||
var index = this.map[str];
|
||||
|
||||
if (!index) {
|
||||
index = ++this.seed;
|
||||
this.map[str] = index;
|
||||
}
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
module.exports = function createDeclarationIndexer() {
|
||||
var ids = new Index();
|
||||
|
||||
return function markDeclaration(node) {
|
||||
var id = generate(node);
|
||||
|
||||
node.id = ids.resolve(id);
|
||||
node.length = id.length;
|
||||
node.fingerprint = null;
|
||||
|
||||
return node;
|
||||
};
|
||||
};
|
||||
43
node_modules/csso/lib/restructure/prepare/index.js
generated
vendored
Normal file
43
node_modules/csso/lib/restructure/prepare/index.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
var resolveKeyword = require('css-tree').keyword;
|
||||
var walk = require('css-tree').walk;
|
||||
var generate = require('css-tree').generate;
|
||||
var createDeclarationIndexer = require('./createDeclarationIndexer');
|
||||
var processSelector = require('./processSelector');
|
||||
|
||||
module.exports = function prepare(ast, options) {
|
||||
var markDeclaration = createDeclarationIndexer();
|
||||
|
||||
walk(ast, {
|
||||
visit: 'Rule',
|
||||
enter: function processRule(node) {
|
||||
node.block.children.each(markDeclaration);
|
||||
processSelector(node, options.usage);
|
||||
}
|
||||
});
|
||||
|
||||
walk(ast, {
|
||||
visit: 'Atrule',
|
||||
enter: function(node) {
|
||||
if (node.prelude) {
|
||||
node.prelude.id = null; // pre-init property to avoid multiple hidden class for generate
|
||||
node.prelude.id = generate(node.prelude);
|
||||
}
|
||||
|
||||
// compare keyframe selectors by its values
|
||||
// NOTE: still no clarification about problems with keyframes selector grouping (issue #197)
|
||||
if (resolveKeyword(node.name).basename === 'keyframes') {
|
||||
node.block.avoidRulesMerge = true; /* probably we don't need to prevent those merges for @keyframes
|
||||
TODO: need to be checked */
|
||||
node.block.children.each(function(rule) {
|
||||
rule.prelude.children.each(function(simpleselector) {
|
||||
simpleselector.compareMarker = simpleselector.id;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
declaration: markDeclaration
|
||||
};
|
||||
};
|
||||
94
node_modules/csso/lib/restructure/prepare/processSelector.js
generated
vendored
Normal file
94
node_modules/csso/lib/restructure/prepare/processSelector.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
var generate = require('css-tree').generate;
|
||||
var specificity = require('./specificity');
|
||||
|
||||
var nonFreezePseudoElements = {
|
||||
'first-letter': true,
|
||||
'first-line': true,
|
||||
'after': true,
|
||||
'before': true
|
||||
};
|
||||
var nonFreezePseudoClasses = {
|
||||
'link': true,
|
||||
'visited': true,
|
||||
'hover': true,
|
||||
'active': true,
|
||||
'first-letter': true,
|
||||
'first-line': true,
|
||||
'after': true,
|
||||
'before': true
|
||||
};
|
||||
|
||||
module.exports = function freeze(node, usageData) {
|
||||
var pseudos = Object.create(null);
|
||||
var hasPseudo = false;
|
||||
|
||||
node.prelude.children.each(function(simpleSelector) {
|
||||
var tagName = '*';
|
||||
var scope = 0;
|
||||
|
||||
simpleSelector.children.each(function(node) {
|
||||
switch (node.type) {
|
||||
case 'ClassSelector':
|
||||
if (usageData && usageData.scopes) {
|
||||
var classScope = usageData.scopes[node.name] || 0;
|
||||
|
||||
if (scope !== 0 && classScope !== scope) {
|
||||
throw new Error('Selector can\'t has classes from different scopes: ' + generate(simpleSelector));
|
||||
}
|
||||
|
||||
scope = classScope;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PseudoClassSelector':
|
||||
var name = node.name.toLowerCase();
|
||||
|
||||
if (!nonFreezePseudoClasses.hasOwnProperty(name)) {
|
||||
pseudos[name] = true;
|
||||
hasPseudo = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PseudoElementSelector':
|
||||
var name = node.name.toLowerCase();
|
||||
|
||||
if (!nonFreezePseudoElements.hasOwnProperty(name)) {
|
||||
pseudos[name] = true;
|
||||
hasPseudo = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'TypeSelector':
|
||||
tagName = node.name.toLowerCase();
|
||||
break;
|
||||
|
||||
case 'AttributeSelector':
|
||||
if (node.flags) {
|
||||
pseudos['[' + node.flags.toLowerCase() + ']'] = true;
|
||||
hasPseudo = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'WhiteSpace':
|
||||
case 'Combinator':
|
||||
tagName = '*';
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
simpleSelector.compareMarker = specificity(simpleSelector).toString();
|
||||
simpleSelector.id = null; // pre-init property to avoid multiple hidden class
|
||||
simpleSelector.id = generate(simpleSelector);
|
||||
|
||||
if (scope) {
|
||||
simpleSelector.compareMarker += ':' + scope;
|
||||
}
|
||||
|
||||
if (tagName !== '*') {
|
||||
simpleSelector.compareMarker += ',' + tagName;
|
||||
}
|
||||
});
|
||||
|
||||
// add property to all rule nodes to avoid multiple hidden class
|
||||
node.pseudoSignature = hasPseudo && Object.keys(pseudos).sort().join(',');
|
||||
};
|
||||
57
node_modules/csso/lib/restructure/prepare/specificity.js
generated
vendored
Normal file
57
node_modules/csso/lib/restructure/prepare/specificity.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
module.exports = function specificity(simpleSelector) {
|
||||
var A = 0;
|
||||
var B = 0;
|
||||
var C = 0;
|
||||
|
||||
simpleSelector.children.each(function walk(node) {
|
||||
switch (node.type) {
|
||||
case 'SelectorList':
|
||||
case 'Selector':
|
||||
node.children.each(walk);
|
||||
break;
|
||||
|
||||
case 'IdSelector':
|
||||
A++;
|
||||
break;
|
||||
|
||||
case 'ClassSelector':
|
||||
case 'AttributeSelector':
|
||||
B++;
|
||||
break;
|
||||
|
||||
case 'PseudoClassSelector':
|
||||
switch (node.name.toLowerCase()) {
|
||||
case 'not':
|
||||
node.children.each(walk);
|
||||
break;
|
||||
|
||||
case 'before':
|
||||
case 'after':
|
||||
case 'first-line':
|
||||
case 'first-letter':
|
||||
C++;
|
||||
break;
|
||||
|
||||
// TODO: support for :nth-*(.. of <SelectorList>), :matches(), :has()
|
||||
|
||||
default:
|
||||
B++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'PseudoElementSelector':
|
||||
C++;
|
||||
break;
|
||||
|
||||
case 'TypeSelector':
|
||||
// ignore universal selector
|
||||
if (node.name.charAt(node.name.length - 1) !== '*') {
|
||||
C++;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
return [A, B, C];
|
||||
};
|
||||
151
node_modules/csso/lib/restructure/utils.js
generated
vendored
Normal file
151
node_modules/csso/lib/restructure/utils.js
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
function isEqualSelectors(a, b) {
|
||||
var cursor1 = a.head;
|
||||
var cursor2 = b.head;
|
||||
|
||||
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
|
||||
cursor1 = cursor1.next;
|
||||
cursor2 = cursor2.next;
|
||||
}
|
||||
|
||||
return cursor1 === null && cursor2 === null;
|
||||
}
|
||||
|
||||
function isEqualDeclarations(a, b) {
|
||||
var cursor1 = a.head;
|
||||
var cursor2 = b.head;
|
||||
|
||||
while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
|
||||
cursor1 = cursor1.next;
|
||||
cursor2 = cursor2.next;
|
||||
}
|
||||
|
||||
return cursor1 === null && cursor2 === null;
|
||||
}
|
||||
|
||||
function compareDeclarations(declarations1, declarations2) {
|
||||
var result = {
|
||||
eq: [],
|
||||
ne1: [],
|
||||
ne2: [],
|
||||
ne2overrided: []
|
||||
};
|
||||
|
||||
var fingerprints = Object.create(null);
|
||||
var declarations2hash = Object.create(null);
|
||||
|
||||
for (var cursor = declarations2.head; cursor; cursor = cursor.next) {
|
||||
declarations2hash[cursor.data.id] = true;
|
||||
}
|
||||
|
||||
for (var cursor = declarations1.head; cursor; cursor = cursor.next) {
|
||||
var data = cursor.data;
|
||||
|
||||
if (data.fingerprint) {
|
||||
fingerprints[data.fingerprint] = data.important;
|
||||
}
|
||||
|
||||
if (declarations2hash[data.id]) {
|
||||
declarations2hash[data.id] = false;
|
||||
result.eq.push(data);
|
||||
} else {
|
||||
result.ne1.push(data);
|
||||
}
|
||||
}
|
||||
|
||||
for (var cursor = declarations2.head; cursor; cursor = cursor.next) {
|
||||
var data = cursor.data;
|
||||
|
||||
if (declarations2hash[data.id]) {
|
||||
// if declarations1 has overriding declaration, this is not a difference
|
||||
// but take in account !important - prev should be equal or greater than follow
|
||||
if (hasOwnProperty.call(fingerprints, data.fingerprint) &&
|
||||
Number(fingerprints[data.fingerprint]) >= Number(data.important)) {
|
||||
result.ne2overrided.push(data);
|
||||
} else {
|
||||
result.ne2.push(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function addSelectors(dest, source) {
|
||||
source.each(function(sourceData) {
|
||||
var newStr = sourceData.id;
|
||||
var cursor = dest.head;
|
||||
|
||||
while (cursor) {
|
||||
var nextStr = cursor.data.id;
|
||||
|
||||
if (nextStr === newStr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextStr > newStr) {
|
||||
break;
|
||||
}
|
||||
|
||||
cursor = cursor.next;
|
||||
}
|
||||
|
||||
dest.insert(dest.createItem(sourceData), cursor);
|
||||
});
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
// check if simpleselectors has no equal specificity and element selector
|
||||
function hasSimilarSelectors(selectors1, selectors2) {
|
||||
var cursor1 = selectors1.head;
|
||||
|
||||
while (cursor1 !== null) {
|
||||
var cursor2 = selectors2.head;
|
||||
|
||||
while (cursor2 !== null) {
|
||||
if (cursor1.data.compareMarker === cursor2.data.compareMarker) {
|
||||
return true;
|
||||
}
|
||||
|
||||
cursor2 = cursor2.next;
|
||||
}
|
||||
|
||||
cursor1 = cursor1.next;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// test node can't to be skipped
|
||||
function unsafeToSkipNode(node) {
|
||||
switch (node.type) {
|
||||
case 'Rule':
|
||||
// unsafe skip ruleset with selector similarities
|
||||
return hasSimilarSelectors(node.prelude.children, this);
|
||||
|
||||
case 'Atrule':
|
||||
// can skip at-rules with blocks
|
||||
if (node.block) {
|
||||
// unsafe skip at-rule if block contains something unsafe to skip
|
||||
return node.block.children.some(unsafeToSkipNode, this);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Declaration':
|
||||
return false;
|
||||
}
|
||||
|
||||
// unsafe by default
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isEqualSelectors: isEqualSelectors,
|
||||
isEqualDeclarations: isEqualDeclarations,
|
||||
compareDeclarations: compareDeclarations,
|
||||
addSelectors: addSelectors,
|
||||
hasSimilarSelectors: hasSimilarSelectors,
|
||||
unsafeToSkipNode: unsafeToSkipNode
|
||||
};
|
||||
79
node_modules/csso/lib/usage.js
generated
vendored
Normal file
79
node_modules/csso/lib/usage.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
function buildMap(list, caseInsensitive) {
|
||||
var map = Object.create(null);
|
||||
|
||||
if (!Array.isArray(list)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var name = list[i];
|
||||
|
||||
if (caseInsensitive) {
|
||||
name = name.toLowerCase();
|
||||
}
|
||||
|
||||
map[name] = true;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
function buildList(data) {
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var tags = buildMap(data.tags, true);
|
||||
var ids = buildMap(data.ids);
|
||||
var classes = buildMap(data.classes);
|
||||
|
||||
if (tags === null &&
|
||||
ids === null &&
|
||||
classes === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
tags: tags,
|
||||
ids: ids,
|
||||
classes: classes
|
||||
};
|
||||
}
|
||||
|
||||
function buildIndex(data) {
|
||||
var scopes = false;
|
||||
|
||||
if (data.scopes && Array.isArray(data.scopes)) {
|
||||
scopes = Object.create(null);
|
||||
|
||||
for (var i = 0; i < data.scopes.length; i++) {
|
||||
var list = data.scopes[i];
|
||||
|
||||
if (!list || !Array.isArray(list)) {
|
||||
throw new Error('Wrong usage format');
|
||||
}
|
||||
|
||||
for (var j = 0; j < list.length; j++) {
|
||||
var name = list[j];
|
||||
|
||||
if (hasOwnProperty.call(scopes, name)) {
|
||||
throw new Error('Class can\'t be used for several scopes: ' + name);
|
||||
}
|
||||
|
||||
scopes[name] = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
whitelist: buildList(data),
|
||||
blacklist: buildList(data.blacklist),
|
||||
scopes: scopes
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildIndex: buildIndex
|
||||
};
|
||||
441
node_modules/csso/node_modules/css-tree/CHANGELOG.md
generated
vendored
Normal file
441
node_modules/csso/node_modules/css-tree/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,441 @@
|
||||
## 1.0.0-alpha.29 (May 30, 2018)
|
||||
|
||||
- Lexer
|
||||
- Syntax matching was completely reworked. Now it's token-based and uses state machine. Public API has not changed. However, some internal data structures have changed. Most significal change in syntax match result tree structure, it's became token-based instead of node-based.
|
||||
- Grammar
|
||||
- Changed grammar tree format:
|
||||
- Added `Token` node type to represent a single code point (`<delim-token>`)
|
||||
- Added `Multiplier` that wraps a single node (`term` property)
|
||||
- Added `AtKeyword` to represent `<at-keyword-token>`
|
||||
- Removed `Slash` and `Percent` node types, they are replaced for a node with `Token` type
|
||||
- Changed `Function` to represent `<function-token>` with no children
|
||||
- Removed `multiplier` property from `Group`
|
||||
- Changed `generate()` method:
|
||||
- Method takes an `options` as second argument now (`generate(node, forceBraces, decorator)` -> `generate(node, options)`). Two options are supported: `forceBraces` and `decorator`
|
||||
- When a second parameter is a function it treats as `decorate` option value, i.e. `generate(node, fn)` -> `generate(node, { decorate: fn })`
|
||||
- Decorate function invokes with additional parameter – a reference to a node
|
||||
- Tokenizer
|
||||
- Renamed `Atrule` const to `AtKeyword`
|
||||
|
||||
## 1.0.0-alpha.28 (February 19, 2018)
|
||||
|
||||
- Renamed `lexer.grammar.translate()` method into `generate()`
|
||||
- Fixed `<'-webkit-font-smoothing'>` and `<'-moz-osx-font-smoothing'>` syntaxes (#75)
|
||||
- Added vendor keywords for `<'overflow'>` property syntax (#76)
|
||||
- Pinned `mdn-data` to `~1.1.0` and fixed issues with some updated property syntaxes
|
||||
|
||||
## 1.0.0-alpha.27 (January 14, 2018)
|
||||
|
||||
- Generator
|
||||
- Changed node's `generate()` methods invocation, methods now take a node as a single argument and context (i.e. `this`) that have methods: `chunk()`, `node()` and `children()`
|
||||
- Renamed `translate()` to `generate()` and changed to take `options` argument
|
||||
- Removed `translateMarkup(ast, enter, leave)` method, use `generate(ast, { decorator: (handlers) => { ... }})` instead
|
||||
- Removed `translateWithSourceMap(ast)`, use `generate(ast, { sourceMap: true })` instead
|
||||
- Changed to support for children as an array
|
||||
- Walker
|
||||
- Changed `walk()` to take an `options` argument instead of handler, with `enter`, `leave`, `visit` and `reverse` options (`walk(ast, fn)` is still works and equivalent to `walk(ast, { enter: fn })`)
|
||||
- Removed `walkUp(ast, fn)`, use `walk(ast, { leave: fn })`
|
||||
- Removed `walkRules(ast, fn)`, use `walk(ast, { visit: 'Rule', enter: fn })` instead
|
||||
- Removed `walkRulesRight(ast, fn)`, use `walk(ast, { visit: 'Rule', reverse: true, enter: fn })` instead
|
||||
- Removed `walkDeclarations(ast, fn)`, use `walk(ast, { visit: 'Declaration', enter: fn })` instead
|
||||
- Changed to support for children as array in most cases (`reverse: true` will fail on arrays since they have no `forEachRight()` method)
|
||||
- Misc
|
||||
- List
|
||||
- Added `List#forEach()` method
|
||||
- Added `List#forEachRight()` method
|
||||
- Added `List#filter()` method
|
||||
- Changed `List#map()` method to return a `List` instance instead of `Array`
|
||||
- Added `List#push()` method, similar to `List#appendData()` but returns nothing
|
||||
- Added `List#pop()` method
|
||||
- Added `List#unshift()` method, similar to `List#prependData()` but returns nothing
|
||||
- Added `List#shift()` method
|
||||
- Added `List#prependList()` method
|
||||
- Changed `List#insert()`, `List#insertData()`, `List#appendList()` and `List#insertList()` methods to return a list that performed an operation
|
||||
- Changed `keyword()` method
|
||||
- Changed `name` field to include a vendor prefix
|
||||
- Added `basename` field to contain a name without a vendor prefix
|
||||
- Added `custom` field that contain a `true` when keyword is a custom property reference
|
||||
- Changed `property()` method
|
||||
- Changed `name` field to include a vendor prefix
|
||||
- Added `basename` field to contain a name without any prefixes, i.e. a hack and a vendor prefix
|
||||
- Added `vendorPrefix()` method
|
||||
- Added `isCustomProperty()` method
|
||||
|
||||
## 1.0.0-alpha.26 (November 9, 2017)
|
||||
|
||||
- Tokenizer
|
||||
- Added `Tokenizer#isBalanceEdge()` method
|
||||
- Removed `Tokenizer.endsWith()` method
|
||||
- Parser
|
||||
- Made the parser tolerant to errors by default
|
||||
- Removed `tolerant` parser option (no parsing modes anymore)
|
||||
- Removed `property` parser option (a value parsing does not depend on property name anymore)
|
||||
- Canceled error for a handing semicolon in a block
|
||||
- Canceled error for unclosed `Brackets`, `Function` and `Parentheses` when EOF is reached
|
||||
- Fixed error when prelude ends with a comment for at-rules with custom prelude consumer
|
||||
- Relaxed at-rule parsing:
|
||||
- Canceled error when EOF is reached after a prelude
|
||||
- Canceled error for an at-rule with custom block consumer when at-rule has no block (just don't apply consumer in that case)
|
||||
- Canceled error on at-rule parsing when it occurs outside prelude or block (at-rule is converting to `Raw` node)
|
||||
- Allowed for any at-rule to have a prelude and a block, even if it's invalid per at-rule syntax (the responsibility for this check is moved to lexer, since it's possible to construct a AST with such errors)
|
||||
- Made a declaration value a safe parsing point (i.e. error on value parsing lead to a value is turning into `Raw` node, not a declaration as before)
|
||||
- Excluded surrounding white spaces and comments from a `Raw` node that represents a declaration value
|
||||
- Changed `Value` parse handler to return a node only with type `Value` (previously it returned a `Raw` node in some cases)
|
||||
- Fixed issue with `onParseError()` is not invoked for errors occured on selector or declaration value parsing in some cases
|
||||
- Changed using of `onParseError()` to stop parsing if handler throws an exception
|
||||
- Lexer
|
||||
- Changed `grammar.walk()` to invoke passed handler on entering to node rather than on leaving the node
|
||||
- Improved `grammar.walk()` to take a walk handler pair as an object, i.e. `walk(node, { enter: fn, leave: fn })`
|
||||
- Changed `Lexer#match*()` methods to take a node of any type, but with a `children` field
|
||||
- Added `Lexer#match(syntax, node)` method
|
||||
- Fixed `Lexer#matchType()` method to stop return a positive result for the CSS wide keywords
|
||||
|
||||
## 1.0.0-alpha25 (October 9, 2017)
|
||||
|
||||
- Parser
|
||||
- Added fallback node as argument to `onParseError()` handler
|
||||
- Fixed raw consuming in tolerant mode when selector is invalid (greedy consuming and redundant warnings)
|
||||
- Fixed exception in tolerant mode caused by unknown at-rule with unclosed block
|
||||
- Changed handling of semicolons:
|
||||
- Hanging semicolon inside declaration blocks raise an error or turns into a `Raw` node in tolerant mode instead of being ignored
|
||||
- Semicolon outside of declaration blocks opens a `Rule` node as part of selector instead of being ignored
|
||||
- Aligned `parseAtrulePrelude` behaviour to `parseRulePrelude`
|
||||
- Removed `Raw` node wraping into `AtrulePrelude` when `parseAtrulePrelude` is disabled
|
||||
- Removed error emitting when at-rule has a custom prelude customer but no prelude is found (it should be validated by a lexer later)
|
||||
- Generator
|
||||
- Fixed performance issue with `translateWithSourceMap()`, flattening the string (because of mixing building string and indexing into it) turned it into a quadratic algorithm (approximate numbers can be found in [the quiz created by this case](https://gist.github.com/lahmatiy/ea25d0e623d88ca9848384b5707d52d9))
|
||||
- Added support for a single solidus hack for `property()`
|
||||
- Minor fixes for custom errors
|
||||
|
||||
## 1.0.0-alpha24 (September 14, 2017)
|
||||
|
||||
- Improved CSSTree to be stable for standart build-in objects extension (#58)
|
||||
- Parser
|
||||
- Renamed rule's `selector` to `prelude`. The reasons: [spec names this part so](https://www.w3.org/TR/css-syntax-3/#qualified-rule), and this branch can contain not only a selector (`SelectorList`) but also a raw payload (`Raw`). What's changed:
|
||||
- Renamed `Rule.selector` to `Rule.prelude`
|
||||
- Renamed `parseSelector` parser option to `parseRulePrelude`
|
||||
- Removed option for selector parse in `SelectorList`
|
||||
- Lexer
|
||||
- Fixed undefined positions in a error when match a syntax to empty or white space only value
|
||||
- Improved `Lexer#checkStructure()`
|
||||
- Return a warning as an object with node reference and message
|
||||
- No exception on unknown node type, return a warning instead
|
||||
|
||||
## 1.0.0-alpha23 (September 10, 2017)
|
||||
|
||||
- Fixed `Tokenizer#getRawLength()`'s false positive balance match to the end of input in some cases (#56)
|
||||
- Rename walker's entry point methods to be the same as CSSTree exposed methods (i.e. `walk()`, `walkUp()` etc)
|
||||
- Rename at-rule's `expression` to `prelude` (since [spec names it so](https://www.w3.org/TR/css-syntax-3/#at-rule))
|
||||
- `AtruleExpression` node type → `AtrulePrelude`
|
||||
- `Atrule.expression` field → `Atrule.prelude`
|
||||
- `parseAtruleExpression` parser's option → `parseAtrulePrelude`
|
||||
- `atruleExpression` parse context → `atrulePrelude`
|
||||
- `atruleExpression` walk context reference → `atrulePrelude`
|
||||
|
||||
## 1.0.0-alpha22 (September 8, 2017)
|
||||
|
||||
- Parser
|
||||
- Fixed exception on parsing of unclosed `{}-block` in tolerant mode
|
||||
- Added tolerant mode support for `DeclarationList`
|
||||
- Added standalone entry point, i.e. default parser can be used via `require('css-tree/lib/parser')` (#47)
|
||||
- Generator
|
||||
- Changed generator to produce `+n` when `AnPlusB.a` is `+1` to be "round-trip" with parser
|
||||
- Added standalone entry point, i.e. default generators can be used via `require('css-tree/lib/generator')`
|
||||
- Walker
|
||||
- Added standalone entry point, i.e. default walkers can be used via `require('css-tree/lib/walker')` (#47)
|
||||
- Lexer
|
||||
- Added `default` keyword to the list of invalid values for `<custom-ident>` (since it reversed per [spec](https://www.w3.org/TR/css-values/#custom-idents))
|
||||
- Convertors (`toPlainObject()` and `fromPlainObject()`) moved to `lib/convertor` (entry point is `require('css-tree/lib/convertor')`)
|
||||
|
||||
## 1.0.0-alpha21 (September 5, 2017)
|
||||
|
||||
- Tokenizer
|
||||
- Added `Raw` token type
|
||||
- Improved tokenization of `url()` with raw as url to be more spec complient
|
||||
- Added `Tokenizer#balance` array computation on token layout
|
||||
- Added `Tokenizer#getRawLength()` to compute a raw length with respect of block balance
|
||||
- Added `Tokenizer#getTokenStart(offset)` method to get token start offset by token index
|
||||
- Added `idx` and `balance` fields to each token of `Tokenizer#dump()` method result
|
||||
- Parser
|
||||
- Added `onParseError` option
|
||||
- Reworked node parsers that consume a `Raw` node to use a new approach. Since now a `Raw` node builds in `parser#Raw()` function only
|
||||
- Changed semantic of `parser#Raw()`, it takes 5 parameters now (it might to be changed in future)
|
||||
- Changed `parser#tolerantParse()` to pass a start token index to fallback function instead of source offset
|
||||
- Fixed `AtruleExpression` consuming in tolerant mode
|
||||
- Atrule handler to convert an empty `AtruleExpression` node into `null`
|
||||
- Changed `AtruleExpression` handler to always return a node (before it could return a `null` in some cases)
|
||||
- Lexer
|
||||
- Fixed comma match node for `#` multiplier
|
||||
- Added reference name to `SyntaxReferenceError`
|
||||
- Additional fixes on custom errors
|
||||
- Reduced possible corruption of base config by `syntax.fork()`
|
||||
|
||||
## 1.0.0-alpha20 (August 28, 2017)
|
||||
|
||||
- Tokenizer
|
||||
- Added `Atrule` token type (`<at-rule-token>` per spec)
|
||||
- Added `Function` token type (`<function-token>` per spec)
|
||||
- Added `Url` token type
|
||||
- Replaced `Tokenizer#getTypes()` method with `Tokenizer#dump()` to get all tokens as an array
|
||||
- Renamed `Tokenizer.TYPE.Whitespace` to `Tokenizer.TYPE.WhiteSpace`
|
||||
- Renamed `Tokenizer.findWhitespaceEnd()` to `Tokenizer.findWhiteSpaceEnd()`
|
||||
- Parser
|
||||
- Added initial implementation of tollerant mode (turn on by passing `tolerant: true` option). In this mode parse errors are never occour and any invalid part of CSS turns into a `Raw` node. Current safe points: `Atrule`, `AtruleExpression`, `Rule`, `Selector` and `Declaration`. Feature is experimental and further improvements are planned.
|
||||
- Changed `Atrule.expression` to contain a `AtruleExpression` node or `null` only (other node types is wrapping into a `AtruleExpression` node)
|
||||
- Renamed `AttributeSelector.operator` to `AttributeSelector.matcher`
|
||||
- Generator
|
||||
- `translate()` method is now can take a function as second argument, that recieves every generated chunk. When no function is passed, default handler is used, it concats all the chunks and method returns a string.
|
||||
- Lexer
|
||||
- Used [mdn/data](https://github.com/mdn/data) package as source of lexer's grammar instead of local dictionaries
|
||||
- Added `x` unit to `<resolution>` generic type
|
||||
- Improved match tree:
|
||||
- Omited Group (sequences) match nodes
|
||||
- Omited empty match nodes (for terms with `zero or more` multipliers)
|
||||
- Added `ASTNode` node type to contain a reference to AST node
|
||||
- Fixed node duplication (uncompleted match were added to tree)
|
||||
- Added AST node reference in match nodes
|
||||
- Added comma match node by `#` multiplier
|
||||
- Grammar
|
||||
- Changed `translate()` function to get a handler as third argument (optional). That handler recieves result of node traslation and can be used for decoration purposes. See [example](https://github.com/csstree/docs/blob/04c65af44477b5ea05feb373482898122b2a4528/docs/syntax.html#L619-L627)
|
||||
- Added `SyntaxParseError` to grammar export
|
||||
- Reworked group and multipliers representation in syntax tree:
|
||||
- Replaced `Sequence` for `Group` node type (`Sequence` node type removed)
|
||||
- Added `explicit` boolean property for `Group`
|
||||
- Only groups can have a multiplier now (other node types is wrapping into a single term implicit group when multiplier is applied)
|
||||
- Renamed `nonEmpty` Group's property to `disallowEmpty`
|
||||
- Added optimisation for syntax tree by dropping redundant root `Group` when it contains a single `Group` term (return this `Group` as a result)
|
||||
- Changed lexer's match functionality
|
||||
- Changed `Lexer#matchProperty()` and `Lexer#matchType()` to return an object instead of match tree. A match tree stores in `matched` field when AST is matched to grammar successfully, otherwise an error in `error` field. The result object also has some methods to test AST node against a match tree: `getTrace()`, `isType()`, `isProperty()` and `isKeyword()`
|
||||
- Added `Lexer#matchDeclaration()` method
|
||||
- Removed `Lexer#lastMatchError` (error stores in match result object in `error` field)
|
||||
- Added initial implementation of search for AST segments (new lexer methods: `Lexer#findValueSegments()`, `Lexer#findDeclarationValueSegments()` and `Lexer#findAllSegments`)
|
||||
- Implemented `SyntaxReferenceError` for unknown property and type references
|
||||
- Renamed field in resulting object of `property()` function: `variable` → `custom`
|
||||
- Fixed issue with readonly properties (e.g. `line` and `column`) of `Error` and exception on attempt to write in iOS Safari
|
||||
|
||||
## 1.0.0-alpha19 (April 24, 2017)
|
||||
|
||||
- Extended `List` class with new methods:
|
||||
- `List#prepend(item)`
|
||||
- `List#prependData(data)`
|
||||
- `List#insertData(data)`
|
||||
- `List#insertList(list)`
|
||||
- `List#replace(item, itemOrList)`
|
||||
|
||||
## 1.0.0-alpha18 (April 3, 2017)
|
||||
|
||||
- Added `atrule` walk context (#39)
|
||||
- Changed a result of generate method for `AnPlusB`, `AttributeSelector`, `Function`, `MediaFeature` and `Ratio` ([1e95877](https://github.com/csstree/csstree/commit/1e9587710efa8e9338bcf0bc794b4b45f286231d))
|
||||
- Fixed typo in `List` exception messages (@strarsis, #42)
|
||||
- Improved tokenizer to convert an input to a string
|
||||
|
||||
## 1.0.0-alpha17 (March 13, 2017)
|
||||
|
||||
- Implemented new concept of `syntax`
|
||||
- Changed main `exports` to expose a default syntax
|
||||
- Defined initial [CSS syntax](lib/syntax/default.js)
|
||||
- Implemented `createSyntax()` method to create a new syntax from scratch
|
||||
- Implemented `fork()` method to create a new syntax based on given via extension
|
||||
- Parser
|
||||
- Implemented `mediaQueryList` and `mediaQuery` parsing contexts
|
||||
- Implemented `CDO` and `CDC` node types
|
||||
- Implemented additional declaration property prefix hacks (`#` and `+`)
|
||||
- Added support for UTF-16LE BOM
|
||||
- Added support for `@font-face` at-rule
|
||||
- Added `chroma()` to legacy IE filter functions
|
||||
- Improved `HexColor` to consume hex only
|
||||
- Improved support for `\0` and `\9` hacks (#2)
|
||||
- Relaxed number check for `Ratio` terms
|
||||
- Allowed fractal values as a `Ratio` term
|
||||
- Disallowed zero number as a `Ratio` term
|
||||
- Changed important clause parsing
|
||||
- Allowed any identifier for important (to support hacks like `!ie`)
|
||||
- Store `true` for `important` field in case identifier equals to `important` and string otherwise
|
||||
- Fixed parse error formatted message rendering to take into account tabs
|
||||
- Removed exposing of `Parser` class
|
||||
- Removed `readSelectorSequence()`, `readSequenceFallback()` and `readSelectorSequenceFallback` methods
|
||||
- Used single universal sequence consumer for `AtruleExpression`, `Selector` and `Value`
|
||||
- Generator
|
||||
- Reworked generator to use auto-generated functions based on syntax definition (additional work to be done in next releases)
|
||||
- Implemented `translateMarkup(ast, before, after)` method for complex cases
|
||||
- Reworked `translateWithSourceMap` to be more flexible (based on `translateMarkup`, additional work to be done in next releases)
|
||||
- Walker
|
||||
- Reworked walker to use auto-generated function based on syntax definition (additional work to be done in next releases)
|
||||
- Lexer
|
||||
- Prepared for better extensibility (additional work to be done in next releases)
|
||||
- Implemented `checkStructure(ast)` method to check AST structure based on syntax definition
|
||||
- Update syntax dictionaries to latest `mdn/data`
|
||||
- Add missing `<'offset-position'>` syntax
|
||||
- Extended `<position>` property with `-webkit-sticky` (@sergejmueller, #37)
|
||||
- Improved mismatch error position
|
||||
- Implemented script (`gen:syntax`) to generate AST format reference page (`docs/ast.md`) using syntax definition
|
||||
|
||||
## 1.0.0-alpha16 (February 12, 2017)
|
||||
|
||||
- Exposed `Parser` class
|
||||
- Added `startOffset` option to `Tokenizer` (constructor and `setSource()` method)
|
||||
- Added fallback functions for default (`readSequenceFallback`) and selector (`readSelectorSequenceFallback`) sequence readers
|
||||
- Fixed edge cases for `AnPlusB`
|
||||
- Fixed wrong whitespace ignoring in `Selector` consumer
|
||||
|
||||
## 1.0.0-alpha15 (February 8, 2017)
|
||||
|
||||
- Fixed broken `atruleExpression` context
|
||||
- Fixed vendor prefix detection in `keyword()` and `property()`
|
||||
- Fixed `property()` to not lowercase custom property names
|
||||
- Added `variable` boolean flag in `property()` result
|
||||
- Renamed `scanner` into `tokenizer`
|
||||
- Ranamed `syntax` into `lexer`
|
||||
- Moved `docs/*.html` files to [csstree/docs](https://github.com/csstree/docs) repo
|
||||
- Added `element()` function for `Value` context (`-moz-element()` supported as well)
|
||||
- Merged `Universal` node type into `Type`
|
||||
- Renamed node types:
|
||||
- `Id` -> `IdSelector`
|
||||
- `Class` -> `ClassSelector`
|
||||
- `Type` -> `TypeSelector`
|
||||
- `Attribute` -> `AttributeSelector`
|
||||
- `PseudoClass` -> `PseudoClassSelector`
|
||||
- `PseudoElement` -> `PseudoElementSelector`
|
||||
- `Hash` -> `HexColor`
|
||||
- `Space` -> `WhiteSpace`
|
||||
- `An+B` -> `AnPlusB`
|
||||
- Removed `Progid` node type
|
||||
- Relaxed `MediaQuery` consumer to not validate syntax on parse and to include whitespaces in children sequence as is
|
||||
- Added `WhiteSpace.value` property to store whitespace sequence
|
||||
- Implemented parser options to specify what should be parsed in details (when option is `false` some part of CSS represents as balanced `Raw`):
|
||||
- `parseAtruleExpression` – to parse at-rule expressions (`true` by default)
|
||||
- `parseSelector` – to parse rule's selector (`true` by default)
|
||||
- `parseValue` - to parse declaration's value (`true` by default)
|
||||
- `parseCustomProperty` – to parse value and fallback of custom property (`false` by default)
|
||||
- Changed tokenization to stick leading hyphen minus to identifier token
|
||||
- Changed selector parsing:
|
||||
- Don't convert spaces into descendant combinator
|
||||
- Don't validate selector structure on parsing (selectors may be checked by lexer later)
|
||||
- Initial refactoring of [docs](https://github.com/csstree/csstree/blob/master/docs)
|
||||
- Various improvements and fixes
|
||||
|
||||
## 1.0.0-alpha14 (February 3, 2017)
|
||||
|
||||
- Implemented `DeclarationList`, `MediaQueryList`, `MediaQuery`, `MediaFeature` and `Ratio` node types
|
||||
- Implemented `declarationList` context (useful to parse HTML `style` attribute content)
|
||||
- Implemented custom consumers for `@import`, `@media`, `@page` and `@supports` at-rules
|
||||
- Implemented `atrule` option for `parse()` config, is used for `atruleExpession` context to specify custom consumer for at-rule if any
|
||||
- Added `Scanner#skipWS()`, `Scanner#eatNonWS()`, `Scanner#consume()` and `Scanner#consumeNonWS()` helper methods
|
||||
- Added custom consumers for known functional-pseudos, consume unknown functional-pseudo content as balanced `Raw`
|
||||
- Allowed any `PseudoElement` to be a functional-pseudo (#33)
|
||||
- Improved walker implementations to reduce GC thrashing by reusing cursors
|
||||
- Changed `Atrule.block` to contain a `Block` node type only if any
|
||||
- Changed `Block.loc` positions to include curly brackets
|
||||
- Changed `Atrule.expression` to store a `null` if no expression
|
||||
- Changed parser to use `StyleSheet` node type only for top level node (when context is `stylesheet`, that's by default)
|
||||
- Changed `Parentheses`, `Brackets` and `Function` consumers to use passed sequence reader instead of its own
|
||||
- Changed `Value` and `AtruleExpression` consumers to use common sequence reader (that reader was used by `Value` consumer before)
|
||||
- Changed default sequence reader to exclude storage of spaces around `Comma`
|
||||
- Changed processing of custom properties:
|
||||
- Consume declaration value as balanced `Raw`
|
||||
- Consume `var()` fallback value as balanced `Raw`
|
||||
- Validate first argument of `var()` starts with double dash
|
||||
- Custom property's value and fallback includes spaces around
|
||||
- Fixed `Nth` to have a `loc` property
|
||||
- Fixed `SelectorList.loc` and `Selector.loc` positions to exclude spaces
|
||||
- Fixed issue Browserify build fail with `default-syntax.json` is not found error (#32, @philschatz)
|
||||
- Disallowed `Type` selector starting with dash (parser throws an error in this case now)
|
||||
- Disallowed empty selectors for `Rule` (not sure if it's correct but looks reasonable)
|
||||
- Removed `>>` combinator support until any browser support (no signals about that yet)
|
||||
- Removed `PseudoElement.legacy` property
|
||||
- Removed special case for `:before`, `:after`, `:first-letter` and `:first-line` to represent them as `PseudoElement`, now those pseudos are represented as `PseudoClass` nodes
|
||||
- Removed deprecated `Syntax#match()` method
|
||||
- Parser was splitted into modules and related changes, one step closer to an extensible parser
|
||||
- Various fixes and improvements, all changes have negligible impact on performance
|
||||
|
||||
## 1.0.0-alpha13 (January 19, 2017)
|
||||
|
||||
- Changed location storing in `SyntaxMatchError`
|
||||
- Changed property to store mismatch offset to `mismatchOffset`
|
||||
- Changed `offset` property to store bad node offset in source CSS if any
|
||||
- Added `loc` property that stores bad node `loc` if any
|
||||
|
||||
## 1.0.0-alpha12 (January 19, 2017)
|
||||
|
||||
- Fixed `Syntax#matchProperty()` method to always return a positive result for custom properties since syntax is never defined for them (#31)
|
||||
- Implemented `fromPlainObject()` and `toPlainObject()` to convert plain object to AST or AST to plain object (currently converts `List` <-> `Array`)
|
||||
|
||||
## 1.0.0-alpha11 (January 18, 2017)
|
||||
|
||||
- Added support for `:matches(<selector-list>)` (#28)
|
||||
- Added support for `:has(<relative-selector-list>)`
|
||||
- Added support for `::slotted(<compound-selector>)`
|
||||
- Implemented `Brackets` node type
|
||||
- Implemented basic support for at-rule inside rule block (#24)
|
||||
- Renamed `Selector` node type to `SelectorList`
|
||||
- Renamed `SimpleSelector` node type to `Selector`
|
||||
- Renamed `UnicodeRange.name` property to `UnicodeRange.value`
|
||||
- Replaced `Negation` node type for regular `PseudoClass`
|
||||
- Unified name of node property to store nested nodes, it always `children` now:
|
||||
- `StyleSheet.rules` -> `StyleSheet.children`
|
||||
- `SelectorList.selectors` -> `SelectorList.children`
|
||||
- `Block.declarations` -> `Block.children`
|
||||
- `*.sequence` -> `*.children`
|
||||
- Fixed edge cases in parsing `Hex` and `UnicodeRange` when number not an integer
|
||||
- Changed `nth-` pseudos parsing
|
||||
- Implemented `An+B` node type to represent expressions like `2n + 1` or `-3n`
|
||||
- Fixed edge cases when `a` or `b` is not an integer
|
||||
- Changed `odd` and `even` keywords processing, keywords are storing as `Identifier` node type now
|
||||
- Changed `Nth` node type format to store a `nth`-query and an optional `selector`
|
||||
- Implemented `of` clause for `nth-` pseudos (a.e. `:nth-child(2n + 1 of li, img)`)
|
||||
- Limited `Nth` parsing rules to `:nth-child()`, `:nth-last-child()`, `:nth-of-type()` and `:nth-last-of-type()` pseudos
|
||||
- Changed the way to store locations
|
||||
- Renamed `info` node property to `loc`
|
||||
- Changed format of `loc` to store `start` and `end` positions
|
||||
|
||||
## 1.0.0-alpha10 (January 11, 2017)
|
||||
|
||||
- Reworked `Scanner` to be a single point to its functionality
|
||||
- Exposed `Scanner` class to be useful for external projects
|
||||
- Changed `walk()` function behaviour to traverse AST nodes in natural order
|
||||
- Implemented `walkUp()` function to traverse AST nodes from deepest to parent (behaves as `walk()` before)
|
||||
|
||||
## 1.0.0-alpha9 (December 21, 2016)
|
||||
|
||||
- Fixed `<angle>` generic according to specs that allow a `<number>` equals to zero to be used as valid value (#30)
|
||||
|
||||
## 1.0.0-alpha8 (November 11, 2016)
|
||||
|
||||
- Fixed `Scanner#skip()` issue method when cursor is moving to the end of source
|
||||
- Simplified `Progid` node
|
||||
- Changed behaviour for bad selector processing, now parsing fails instead of selector ignoring
|
||||
- Fixed `<id-selector>` generic syntax
|
||||
- Added `q` unit for `<length>` generic syntax
|
||||
- Refactored syntax parser (performance)
|
||||
- Reduced startup time by implementing lazy syntax parsing (default syntax doesn't parse on module load)
|
||||
- Updated syntax dictionaries and used [`mdn/data`](https://github.com/mdn/data) instead of `Template:CSSData`
|
||||
- Renamed `syntax.stringify()` method to `syntax.translate()`
|
||||
- Simplified generic syntax functions, those functions receive a single AST node for checking and should return `true` or `false`
|
||||
- Added exception for values that contains `var()`, those values are always valid for now
|
||||
- Added more tests and increase code coverage to `98.5%`
|
||||
|
||||
## 1.0.0-alpha7 (October 7, 2016)
|
||||
|
||||
- Added support for explicit descendant combinator (`>>`)
|
||||
- Implemented `Type` and `Universal` type nodes
|
||||
- Improved `Number` parsing by including sign and exponent (#26)
|
||||
- Parse `before`, `after`, `first-letter` and `first-line` pseudos with single colon as `PseudoElement`
|
||||
- Changed `FunctionalPseudo` node type to `PseudoClass`
|
||||
- Fixed attribute selector name parsing (namespace edge cases)
|
||||
- Fixed location calculation for specified offset when `eof` is reached
|
||||
- Added more non-standard colors (#25)
|
||||
- Removed obsolete `Syntax#getAll()` method
|
||||
- Fixed various edge cases, code clean up and performance improvements
|
||||
|
||||
## 1.0.0-alpha6 (September 23, 2016)
|
||||
|
||||
- More accurate positions for syntax mismatch errors
|
||||
- Added [`apple`](https://webkit.org/blog/3709/using-the-system-font-in-web-content/) specific font keywords (#20)
|
||||
- Changed `Property` node stucture from object to string
|
||||
- Renamed `Ruleset` node type to `Rule`
|
||||
- Removed `Argument` node type
|
||||
- Fixed `Dimension` and `Percentage` position computation
|
||||
- Fixed bad selector parsing (temporary solution)
|
||||
- Fixed location computation for CSS with very long lines that may lead to really long parsing with `positions:true` (even freeze)
|
||||
- Fixed `line` and `column` computation for `SyntaxMatch` error
|
||||
- Improved performance of parsing and translation. Now CSSTree is under 10ms in [PostCSS benchmark](https://github.com/postcss/benchmark).
|
||||
19
node_modules/csso/node_modules/css-tree/LICENSE
generated
vendored
Normal file
19
node_modules/csso/node_modules/css-tree/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2016 by Roman Dvornov
|
||||
|
||||
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.
|
||||
90
node_modules/csso/node_modules/css-tree/README.md
generated
vendored
Normal file
90
node_modules/csso/node_modules/css-tree/README.md
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<img align="right" width="111" height="111"
|
||||
alt="CSSTree logo"
|
||||
src="https://cloud.githubusercontent.com/assets/270491/19243723/6f9136c6-8f21-11e6-82ac-eeeee4c6c452.png"/>
|
||||
|
||||
# CSSTree
|
||||
|
||||
[](https://www.npmjs.com/package/css-tree)
|
||||
[](https://travis-ci.org/csstree/csstree)
|
||||
[](https://coveralls.io/github/csstree/csstree?branch=master)
|
||||
[](https://www.npmjs.com/package/css-tree)
|
||||
[](https://twitter.com/csstree)
|
||||
|
||||
CSSTree is a tool set to work with CSS, including [fast](https://github.com/postcss/benchmark) detailed parser (string->AST), walker (AST traversal), generator (AST->string) and lexer (validation and matching) based on knowledge of spec and browser implementations. The main goal is to be efficient and W3C spec compliant, with focus on CSS analyzing and source-to-source transforming tasks.
|
||||
|
||||
> NOTE: The project is in alpha stage since some parts need further improvements, AST format and API are subjects to change. However it's stable enough and used by packages like [CSSO](https://github.com/css/csso) (CSS minifier) and [SVGO](https://github.com/svg/svgo) (SVG optimizer) in production.
|
||||
|
||||
## Features
|
||||
|
||||
- **Detailed parsing with an adjustable level of detail**
|
||||
|
||||
By default CSSTree parses CSS as detailed as possible, i.e. each single logical part is representing with its own AST node (see [AST format](docs/ast.md) for all possible node types). The parsing detail level can be changed through [parser options](docs/parsing.md#parsesource-options), for example, you can disable parsing of selectors or declarations for component parts.
|
||||
|
||||
- **Tolerant to errors by design**
|
||||
|
||||
Parser behaves as [spec says](https://www.w3.org/TR/css-syntax-3/#error-handling): "When errors occur in CSS, the parser attempts to recover gracefully, throwing away only the minimum amount of content before returning to parsing as normal". The only thing the parser departs from the specification is that it doesn't throw away bad content, but wraps it in the special nodes, which allows processing it later.
|
||||
|
||||
- **Fast and efficient**
|
||||
|
||||
CSSTree is created with focus on performance and effective memory consumption. Therefore it's [one of the fastest CSS parsers](https://github.com/postcss/benchmark) at the moment.
|
||||
|
||||
- **Syntax validation**
|
||||
|
||||
The build-in lexer can test CSS against syntaxes defined by W3C. CSSTree uses [mdn/data](https://github.com/mdn/data/) as a basis for lexer's dictionaries and extends them with vendor specific and legacy syntaxes. Lexer can only check the declaration values currently, but this feature will be extended to other parts of the CSS in the future.
|
||||
|
||||
## Docs
|
||||
|
||||
- [Parsing CSS into AST](docs/parsing.md)
|
||||
- [AST format](docs/ast.md)
|
||||
- [Generate CSS from AST](docs/generate.md)
|
||||
- [AST traversal](docs/traversal.md)
|
||||
- [Utils to work with AST](docs/utils.md)
|
||||
|
||||
## Tools
|
||||
|
||||
* [AST Explorer](https://astexplorer.net/#/gist/244e2fb4da940df52bf0f4b94277db44/e79aff44611020b22cfd9708f3a99ce09b7d67a8) – explore CSSTree AST format with zero setup
|
||||
* [CSS syntax reference](https://csstree.github.io/docs/syntax.html)
|
||||
* [CSS syntax validator](https://csstree.github.io/docs/validator.html)
|
||||
|
||||
## Related projects
|
||||
|
||||
* [csstree-validator](https://github.com/csstree/validator) – NPM package to validate CSS
|
||||
* [stylelint-csstree-validator](https://github.com/csstree/stylelint-validator) – plugin for stylelint to validate CSS
|
||||
* [Grunt plugin](https://github.com/sergejmueller/grunt-csstree-validator)
|
||||
* [Gulp plugin](https://github.com/csstree/gulp-csstree)
|
||||
* [Sublime plugin](https://github.com/csstree/SublimeLinter-contrib-csstree)
|
||||
* [VS Code plugin](https://github.com/csstree/vscode-plugin)
|
||||
* [Atom plugin](https://github.com/csstree/atom-plugin)
|
||||
|
||||
## Usage
|
||||
|
||||
Install with npm:
|
||||
|
||||
|
||||
```
|
||||
> npm install css-tree
|
||||
```
|
||||
|
||||
Use in your code:
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = csstree.parse('.example { world: "!" }');
|
||||
|
||||
csstree.walk(ast, function(node) {
|
||||
if (node.type === 'ClassSelector' && node.name === 'example') {
|
||||
node.name = 'hello';
|
||||
}
|
||||
});
|
||||
|
||||
console.log(csstree.generate(ast));
|
||||
// .hello{world:"!"}
|
||||
```
|
||||
|
||||
## Top level API
|
||||
|
||||

|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
34
node_modules/csso/node_modules/css-tree/data/index.js
generated
vendored
Normal file
34
node_modules/csso/node_modules/css-tree/data/index.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
var mdnProperties = require('mdn-data/css/properties.json');
|
||||
var mdnSyntaxes = require('mdn-data/css/syntaxes.json');
|
||||
var patch = require('./patch.json');
|
||||
|
||||
function buildDictionary(dict, patchDict) {
|
||||
var result = {};
|
||||
|
||||
// copy all syntaxes for an original dict
|
||||
for (var key in dict) {
|
||||
result[key] = dict[key].syntax;
|
||||
}
|
||||
|
||||
// apply a patch
|
||||
for (var key in patchDict) {
|
||||
if (key in dict) {
|
||||
if (patchDict[key].syntax) {
|
||||
result[key] = patchDict[key].syntax;
|
||||
} else {
|
||||
delete result[key];
|
||||
}
|
||||
} else {
|
||||
if (patchDict[key].syntax) {
|
||||
result[key] = patchDict[key].syntax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
properties: buildDictionary(mdnProperties, patch.properties),
|
||||
types: buildDictionary(mdnSyntaxes, patch.syntaxes)
|
||||
};
|
||||
802
node_modules/csso/node_modules/css-tree/data/patch.json
generated
vendored
Normal file
802
node_modules/csso/node_modules/css-tree/data/patch.json
generated
vendored
Normal file
@@ -0,0 +1,802 @@
|
||||
{
|
||||
"properties": {
|
||||
"--*": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"-moz-background-clip": {
|
||||
"comment": "deprecated syntax in old Firefox, https://developer.mozilla.org/en/docs/Web/CSS/background-clip",
|
||||
"syntax": "padding | border"
|
||||
},
|
||||
"-moz-border-radius-bottomleft": {
|
||||
"comment": "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-left-radius",
|
||||
"syntax": "<'border-bottom-left-radius'>"
|
||||
},
|
||||
"-moz-border-radius-bottomright": {
|
||||
"comment": "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius",
|
||||
"syntax": "<'border-bottom-right-radius'>"
|
||||
},
|
||||
"-moz-border-radius-topleft": {
|
||||
"comment": "https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-left-radius",
|
||||
"syntax": "<'border-top-left-radius'>"
|
||||
},
|
||||
"-moz-border-radius-topright": {
|
||||
"comment": "https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-right-radius",
|
||||
"syntax": "<'border-bottom-right-radius'>"
|
||||
},
|
||||
"-moz-osx-font-smoothing": {
|
||||
"comment": "misssed old syntax https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth",
|
||||
"syntax": "auto | grayscale"
|
||||
},
|
||||
"-moz-user-select": {
|
||||
"comment": "https://developer.mozilla.org/en-US/docs/Web/CSS/user-select",
|
||||
"syntax": "none | text | all | -moz-none"
|
||||
},
|
||||
"-ms-flex-align": {
|
||||
"comment": "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align",
|
||||
"syntax": "start | end | center | baseline | stretch"
|
||||
},
|
||||
"-ms-flex-item-align": {
|
||||
"comment": "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-align",
|
||||
"syntax": "auto | start | end | center | baseline | stretch"
|
||||
},
|
||||
"-ms-flex-line-pack": {
|
||||
"comment": "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-line-pack",
|
||||
"syntax": "start | end | center | justify | distribute | stretch"
|
||||
},
|
||||
"-ms-flex-negative": {
|
||||
"comment": "misssed old syntax implemented in IE; TODO: find references for comfirmation",
|
||||
"syntax": "<'flex-shrink'>"
|
||||
},
|
||||
"-ms-flex-pack": {
|
||||
"comment": "misssed old syntax implemented in IE, https://www.w3.org/TR/2012/WD-css3-flexbox-20120322/#flex-pack",
|
||||
"syntax": "start | end | center | justify | distribute"
|
||||
},
|
||||
"-ms-flex-order": {
|
||||
"comment": "misssed old syntax implemented in IE; https://msdn.microsoft.com/en-us/library/jj127303(v=vs.85).aspx",
|
||||
"syntax": "<integer>"
|
||||
},
|
||||
"-ms-flex-positive": {
|
||||
"comment": "misssed old syntax implemented in IE; TODO: find references for comfirmation",
|
||||
"syntax": "<'flex-grow'>"
|
||||
},
|
||||
"-ms-flex-preferred-size": {
|
||||
"comment": "misssed old syntax implemented in IE; TODO: find references for comfirmation",
|
||||
"syntax": "<'flex-basis'>"
|
||||
},
|
||||
"-ms-interpolation-mode": {
|
||||
"comment": "https://msdn.microsoft.com/en-us/library/ff521095(v=vs.85).aspx",
|
||||
"syntax": "nearest-neighbor | bicubic"
|
||||
},
|
||||
"-ms-grid-column-align": {
|
||||
"comment": "add this property first since it uses as fallback for flexbox, https://msdn.microsoft.com/en-us/library/windows/apps/hh466338.aspx",
|
||||
"syntax": "start | end | center | stretch"
|
||||
},
|
||||
"-ms-grid-row-align": {
|
||||
"comment": "add this property first since it uses as fallback for flexbox, https://msdn.microsoft.com/en-us/library/windows/apps/hh466348.aspx",
|
||||
"syntax": "start | end | center | stretch"
|
||||
},
|
||||
"-webkit-appearance": {
|
||||
"comment": "webkit specific keywords",
|
||||
"references": [
|
||||
"http://css-infos.net/property/-webkit-appearance"
|
||||
],
|
||||
"syntax": "none | button | button-bevel | caps-lock-indicator | caret | checkbox | default-button | listbox | listitem | media-fullscreen-button | media-mute-button | media-play-button | media-seek-back-button | media-seek-forward-button | media-slider | media-sliderthumb | menulist | menulist-button | menulist-text | menulist-textfield | push-button | radio | scrollbarbutton-down | scrollbarbutton-left | scrollbarbutton-right | scrollbarbutton-up | scrollbargripper-horizontal | scrollbargripper-vertical | scrollbarthumb-horizontal | scrollbarthumb-vertical | scrollbartrack-horizontal | scrollbartrack-vertical | searchfield | searchfield-cancel-button | searchfield-decoration | searchfield-results-button | searchfield-results-decoration | slider-horizontal | slider-vertical | sliderthumb-horizontal | sliderthumb-vertical | square-button | textarea | textfield"
|
||||
},
|
||||
"-webkit-background-clip": {
|
||||
"comment": "https://developer.mozilla.org/en/docs/Web/CSS/background-clip",
|
||||
"syntax": "[ <box> | border | padding | content | text ]#"
|
||||
},
|
||||
"-webkit-column-break-after": {
|
||||
"comment": "added, http://help.dottoro.com/lcrthhhv.php",
|
||||
"syntax": "always | auto | avoid"
|
||||
},
|
||||
"-webkit-column-break-before": {
|
||||
"comment": "added, http://help.dottoro.com/lcxquvkf.php",
|
||||
"syntax": "always | auto | avoid"
|
||||
},
|
||||
"-webkit-column-break-inside": {
|
||||
"comment": "added, http://help.dottoro.com/lclhnthl.php",
|
||||
"syntax": "always | auto | avoid"
|
||||
},
|
||||
"-webkit-font-smoothing": {
|
||||
"comment": "https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth",
|
||||
"syntax": "auto | none | antialiased | subpixel-antialiased"
|
||||
},
|
||||
"-webkit-line-clamp": {
|
||||
"comment": "non-standard and deprecated but may still using by some sites",
|
||||
"syntax": "<positive-integer>"
|
||||
},
|
||||
"-webkit-mask-box-image": {
|
||||
"comment": "missed; https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image",
|
||||
"syntax": "[ <url> | <gradient> | none ] [ <length-percentage>{4} <-webkit-mask-box-repeat>{2} ]?"
|
||||
},
|
||||
"-webkit-mask-clip": {
|
||||
"comment": "change type to <-webkit-mask-clip-style> since it differ from <mask-clip>, extra space between [ and ,",
|
||||
"syntax": "<-webkit-mask-clip-style> [, <-webkit-mask-clip-style> ]*"
|
||||
},
|
||||
"-webkit-print-color-adjust": {
|
||||
"comment": "missed",
|
||||
"references": [
|
||||
"https://developer.mozilla.org/en/docs/Web/CSS/-webkit-print-color-adjust"
|
||||
],
|
||||
"syntax": "economy | exact"
|
||||
},
|
||||
"-webkit-text-security": {
|
||||
"comment": "missed; http://help.dottoro.com/lcbkewgt.php",
|
||||
"syntax": "none | circle | disc | square"
|
||||
},
|
||||
"-webkit-user-drag": {
|
||||
"comment": "missed; http://help.dottoro.com/lcbixvwm.php",
|
||||
"syntax": "none | element | auto"
|
||||
},
|
||||
"-webkit-user-select": {
|
||||
"comment": "auto is supported by old webkit, https://developer.mozilla.org/en-US/docs/Web/CSS/user-select",
|
||||
"syntax": "auto | none | text | all"
|
||||
},
|
||||
"alignment-baseline": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#AlignmentBaselineProperty"
|
||||
],
|
||||
"syntax": "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical"
|
||||
},
|
||||
"baseline-shift": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#BaselineShiftProperty"
|
||||
],
|
||||
"syntax": "baseline | sub | super | <svg-length>"
|
||||
},
|
||||
"behavior": {
|
||||
"comment": "added old IE property https://msdn.microsoft.com/en-us/library/ms530723(v=vs.85).aspx",
|
||||
"syntax": "<url>+"
|
||||
},
|
||||
"clip-rule": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/masking.html#ClipRuleProperty"
|
||||
],
|
||||
"syntax": "nonzero | evenodd"
|
||||
},
|
||||
"cue": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<'cue-before'> <'cue-after'>?"
|
||||
},
|
||||
"cue-after": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<url> <decibel>? | none"
|
||||
},
|
||||
"cue-before": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<url> <decibel>? | none"
|
||||
},
|
||||
"cursor": {
|
||||
"comment": "added legacy keywords: hand, -webkit-grab. -webkit-grabbing, -webkit-zoom-in, -webkit-zoom-out, -moz-grab, -moz-grabbing, -moz-zoom-in, -moz-zoom-out",
|
||||
"refenrences": [
|
||||
"https://www.sitepoint.com/css3-cursor-styles/"
|
||||
],
|
||||
"syntax": "[ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
|
||||
},
|
||||
"display": {
|
||||
"comment": "extended with -ms-flexbox",
|
||||
"syntax": "none | inline | block | list-item | inline-list-item | inline-block | inline-table | table | table-cell | table-column | table-column-group | table-footer-group | table-header-group | table-row | table-row-group | flex | inline-flex | grid | inline-grid | run-in | ruby | ruby-base | ruby-text | ruby-base-container | ruby-text-container | contents | -ms-flexbox | -ms-inline-flexbox | -ms-grid | -ms-inline-grid | -webkit-flex | -webkit-inline-flex | -webkit-box | -webkit-inline-box | -moz-inline-stack | -moz-box | -moz-inline-box"
|
||||
},
|
||||
"position": {
|
||||
"comment": "extended with -webkit-sticky",
|
||||
"syntax": "static | relative | absolute | sticky | fixed | -webkit-sticky"
|
||||
},
|
||||
"dominant-baseline": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#DominantBaselineProperty"
|
||||
],
|
||||
"syntax": "auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge"
|
||||
},
|
||||
"image-rendering": {
|
||||
"comment": "extended with <-non-standard-image-rendering>, added SVG keywords optimizeSpeed and optimizeQuality",
|
||||
"references": [
|
||||
"https://developer.mozilla.org/en/docs/Web/CSS/image-rendering",
|
||||
"https://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty"
|
||||
],
|
||||
"syntax": "auto | crisp-edges | pixelated | optimizeSpeed | optimizeQuality | <-non-standard-image-rendering>"
|
||||
},
|
||||
"fill": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
|
||||
],
|
||||
"syntax": "<paint>"
|
||||
},
|
||||
"fill-opacity": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
|
||||
],
|
||||
"syntax": "<number-zero-one>"
|
||||
},
|
||||
"fill-rule": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#FillProperty"
|
||||
],
|
||||
"syntax": "nonzero | evenodd"
|
||||
},
|
||||
"filter": {
|
||||
"comment": "extend with IE legacy syntaxes",
|
||||
"syntax": "none | <filter-function-list> | <-ms-filter>"
|
||||
},
|
||||
"font": {
|
||||
"comment": "extend with non-standard fonts",
|
||||
"syntax": "[ [ <'font-style'> || <font-variant-css21> || <'font-weight'> || <'font-stretch'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | <-non-standard-font>"
|
||||
},
|
||||
"glyph-orientation-horizontal": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#GlyphOrientationHorizontalProperty"
|
||||
],
|
||||
"syntax": "<angle>"
|
||||
},
|
||||
"glyph-orientation-vertical": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#GlyphOrientationVerticalProperty"
|
||||
],
|
||||
"syntax": "<angle>"
|
||||
},
|
||||
"kerning": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#KerningProperty"
|
||||
],
|
||||
"syntax": "auto | <svg-length>"
|
||||
},
|
||||
"letter-spacing": {
|
||||
"comment": "fix syntax <length> -> <length-percentage>",
|
||||
"references": [
|
||||
"https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/letter-spacing"
|
||||
],
|
||||
"syntax": "normal | <length-percentage>"
|
||||
},
|
||||
"line-height-step": {
|
||||
"comment": "fix extra spaces around",
|
||||
"syntax": "none | <length>"
|
||||
},
|
||||
"marker": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
|
||||
],
|
||||
"syntax": "none | <url>"
|
||||
},
|
||||
"marker-end": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
|
||||
],
|
||||
"syntax": "none | <url>"
|
||||
},
|
||||
"marker-mid": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
|
||||
],
|
||||
"syntax": "none | <url>"
|
||||
},
|
||||
"marker-start": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#MarkerProperties"
|
||||
],
|
||||
"syntax": "none | <url>"
|
||||
},
|
||||
"max-width": {
|
||||
"comment": "extend by non-standard width keywords https://developer.mozilla.org/en-US/docs/Web/CSS/max-width",
|
||||
"syntax": "<length> | <percentage> | none | max-content | min-content | fit-content | fill-available | <-non-standard-width>"
|
||||
},
|
||||
"min-width": {
|
||||
"comment": "extend by non-standard width keywords https://developer.mozilla.org/en-US/docs/Web/CSS/width",
|
||||
"syntax": "<length> | <percentage> | auto | max-content | min-content | fit-content | fill-available | <-non-standard-width>"
|
||||
},
|
||||
"opacity": {
|
||||
"comment": "strict to 0..1 <number> -> <number-zero-one>",
|
||||
"syntax": "<number-zero-one>"
|
||||
},
|
||||
"overflow": {
|
||||
"comment": "extend by vendor keywords https://developer.mozilla.org/en-US/docs/Web/CSS/overflow",
|
||||
"syntax": "visible | hidden | scroll | auto | <-non-standard-overflow>"
|
||||
},
|
||||
"pause": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<'pause-before'> <'pause-after'>?"
|
||||
},
|
||||
"pause-after": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<time> | none | x-weak | weak | medium | strong | x-strong"
|
||||
},
|
||||
"pause-before": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<time> | none | x-weak | weak | medium | strong | x-strong"
|
||||
},
|
||||
"rest": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<'rest-before'> <'rest-after'>?"
|
||||
},
|
||||
"rest-after": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<time> | none | x-weak | weak | medium | strong | x-strong"
|
||||
},
|
||||
"rest-before": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<time> | none | x-weak | weak | medium | strong | x-strong"
|
||||
},
|
||||
"shape-rendering": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#ShapeRenderingPropert"
|
||||
],
|
||||
"syntax": "auto | optimizeSpeed | crispEdges | geometricPrecision"
|
||||
},
|
||||
"src": {
|
||||
"comment": "added @font-face's src property https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src",
|
||||
"syntax": "[ <url> [ format( <string># ) ]? | local( <family-name> ) ]#"
|
||||
},
|
||||
"speak": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "auto | none | normal"
|
||||
},
|
||||
"speak-as": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "normal | spell-out || digits || [ literal-punctuation | no-punctuation ]"
|
||||
},
|
||||
"stroke": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "<paint>"
|
||||
},
|
||||
"stroke-dasharray": {
|
||||
"comment": "added SVG property; a list of comma and/or white space separated <length>s and <percentage>s",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "none | [ <svg-length>+ ]#"
|
||||
},
|
||||
"stroke-dashoffset": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "<svg-length>"
|
||||
},
|
||||
"stroke-linecap": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "butt | round | square"
|
||||
},
|
||||
"stroke-linejoin": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "miter | round | bevel"
|
||||
},
|
||||
"stroke-miterlimit": {
|
||||
"comment": "added SVG property (<miterlimit> = <number-one-or-greater>) ",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "<number-one-or-greater>"
|
||||
},
|
||||
"stroke-opacity": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "<number-zero-one>"
|
||||
},
|
||||
"stroke-width": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/painting.html#StrokeProperties"
|
||||
],
|
||||
"syntax": "<svg-length>"
|
||||
},
|
||||
"text-anchor": {
|
||||
"comment": "added SVG property",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG/text.html#TextAlignmentProperties"
|
||||
],
|
||||
"syntax": "start | middle | end"
|
||||
},
|
||||
"transform-origin": {
|
||||
"comment": "move first group to the end since less collecting",
|
||||
"syntax": "[ [ <length-percentage> | left | center | right ] && [ <length-percentage> | top | center | bottom ] ] <length>? | [ <length-percentage> | left | center | right | top | bottom ]"
|
||||
},
|
||||
"unicode-bidi": {
|
||||
"comment": "added prefixed keywords https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi",
|
||||
"syntax": "normal | embed | isolate | bidi-override | isolate-override | plaintext | -moz-isolate | -moz-isolate-override | -moz-plaintext | -webkit-isolate"
|
||||
},
|
||||
"unicode-range": {
|
||||
"comment": "added missed property https://developer.mozilla.org/en-US/docs/Web/CSS/%40font-face/unicode-range",
|
||||
"syntax": "<unicode-range>#"
|
||||
},
|
||||
"voice-balance": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<number> | left | center | right | leftwards | rightwards"
|
||||
},
|
||||
"voice-duration": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "auto | <time>"
|
||||
},
|
||||
"voice-family": {
|
||||
"comment": "<name> -> <family-name>, https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "[ [ <family-name> | <generic-voice> ] , ]* [ <family-name> | <generic-voice> ] | preserve"
|
||||
},
|
||||
"voice-pitch": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]"
|
||||
},
|
||||
"voice-range": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "<frequency> && absolute | [ [ x-low | low | medium | high | x-high ] || [ <frequency> | <semitones> | <percentage> ] ]"
|
||||
},
|
||||
"voice-rate": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "[ normal | x-slow | slow | medium | fast | x-fast ] || <percentage>"
|
||||
},
|
||||
"voice-stress": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "normal | strong | moderate | none | reduced"
|
||||
},
|
||||
"voice-volume": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#property-index",
|
||||
"syntax": "silent | [ [ x-soft | soft | medium | loud | x-loud ] || <decibel> ]"
|
||||
},
|
||||
"word-break": {
|
||||
"comment": "extend with non-standard keywords",
|
||||
"syntax": "normal | break-all | keep-all | <-non-standard-word-break>"
|
||||
},
|
||||
"writing-mode": {
|
||||
"comment": "extend with SVG keywords",
|
||||
"syntax": "horizontal-tb | vertical-rl | vertical-lr | sideways-rl | sideways-lr | <svg-writing-mode>"
|
||||
}
|
||||
},
|
||||
"syntaxes": {
|
||||
"-legacy-gradient": {
|
||||
"comment": "added collection of legacy gradient syntaxes",
|
||||
"syntax": "<-webkit-gradient()> | <-legacy-linear-gradient> | <-legacy-repeating-linear-gradient> | <-legacy-radial-gradient> | <-legacy-repeating-radial-gradient>"
|
||||
},
|
||||
"-legacy-linear-gradient": {
|
||||
"comment": "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
|
||||
"syntax": "-moz-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-linear-gradient( <-legacy-linear-gradient-arguments> )"
|
||||
},
|
||||
"-legacy-repeating-linear-gradient": {
|
||||
"comment": "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
|
||||
"syntax": "-moz-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -webkit-repeating-linear-gradient( <-legacy-linear-gradient-arguments> ) | -o-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )"
|
||||
},
|
||||
"-legacy-linear-gradient-arguments": {
|
||||
"comment": "like standard syntax but w/o `to` keyword https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient",
|
||||
"syntax": "[ <angle> | <side-or-corner> ]? , <color-stop-list>"
|
||||
},
|
||||
"-legacy-radial-gradient": {
|
||||
"comment": "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
|
||||
"syntax": "-moz-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-radial-gradient( <-legacy-radial-gradient-arguments> )"
|
||||
},
|
||||
"-legacy-repeating-radial-gradient": {
|
||||
"comment": "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
|
||||
"syntax": "-moz-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -webkit-repeating-radial-gradient( <-legacy-radial-gradient-arguments> ) | -o-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )"
|
||||
},
|
||||
"-legacy-radial-gradient-arguments": {
|
||||
"comment": "deprecated syntax that implemented by some browsers https://www.w3.org/TR/2011/WD-css3-images-20110908/#radial-gradients",
|
||||
"syntax": "[ <position> , ]? [ [ [ <-legacy-radial-gradient-shape> || <-legacy-radial-gradient-size> ] | [ <length> | <percentage> ]{2} ] , ]? <color-stop-list>"
|
||||
},
|
||||
"-legacy-radial-gradient-size": {
|
||||
"comment": "before a standard it contains 2 extra keywords (`contain` and `cover`) https://www.w3.org/TR/2011/WD-css3-images-20110908/#ltsize",
|
||||
"syntax": "closest-side | closest-corner | farthest-side | farthest-corner | contain | cover"
|
||||
},
|
||||
"-legacy-radial-gradient-shape": {
|
||||
"comment": "define to duoble sure it doesn't extends in future https://www.w3.org/TR/2011/WD-css3-images-20110908/#ltshape",
|
||||
"syntax": "circle | ellipse"
|
||||
},
|
||||
"-non-standard-font": {
|
||||
"comment": "non standard fonts",
|
||||
"preferences": [
|
||||
"https://webkit.org/blog/3709/using-the-system-font-in-web-content/"
|
||||
],
|
||||
"syntax": "-apple-system-body | -apple-system-headline | -apple-system-subheadline | -apple-system-caption1 | -apple-system-caption2 | -apple-system-footnote | -apple-system-short-body | -apple-system-short-headline | -apple-system-short-subheadline | -apple-system-short-caption1 | -apple-system-short-footnote | -apple-system-tall-body"
|
||||
},
|
||||
"-non-standard-color": {
|
||||
"comment": "non standard colors",
|
||||
"references": [
|
||||
"http://cssdot.ru/%D0%A1%D0%BF%D1%80%D0%B0%D0%B2%D0%BE%D1%87%D0%BD%D0%B8%D0%BA_CSS/color-i305.html",
|
||||
"https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Mozilla_Color_Preference_Extensions"
|
||||
],
|
||||
"syntax": "-moz-ButtonDefault | -moz-ButtonHoverFace | -moz-ButtonHoverText | -moz-CellHighlight | -moz-CellHighlightText | -moz-Combobox | -moz-ComboboxText | -moz-Dialog | -moz-DialogText | -moz-dragtargetzone | -moz-EvenTreeRow | -moz-Field | -moz-FieldText | -moz-html-CellHighlight | -moz-html-CellHighlightText | -moz-mac-accentdarkestshadow | -moz-mac-accentdarkshadow | -moz-mac-accentface | -moz-mac-accentlightesthighlight | -moz-mac-accentlightshadow | -moz-mac-accentregularhighlight | -moz-mac-accentregularshadow | -moz-mac-chrome-active | -moz-mac-chrome-inactive | -moz-mac-focusring | -moz-mac-menuselect | -moz-mac-menushadow | -moz-mac-menutextselect | -moz-MenuHover | -moz-MenuHoverText | -moz-MenuBarText | -moz-MenuBarHoverText | -moz-nativehyperlinktext | -moz-OddTreeRow | -moz-win-communicationstext | -moz-win-mediatext | -moz-activehyperlinktext | -moz-default-background-color | -moz-default-color | -moz-hyperlinktext | -moz-visitedhyperlinktext | -webkit-activelink | -webkit-focus-ring-color | -webkit-link | -webkit-text"
|
||||
},
|
||||
"-non-standard-image-rendering": {
|
||||
"comment": "non-standard keywords http://phrogz.net/tmp/canvas_image_zoom.html",
|
||||
"syntax": "optimize-contrast | -moz-crisp-edges | -o-crisp-edges | -webkit-optimize-contrast"
|
||||
},
|
||||
"-non-standard-overflow": {
|
||||
"comment": "non-standard keywords https://developer.mozilla.org/en-US/docs/Web/CSS/overflow",
|
||||
"syntax": "-moz-scrollbars-none | -moz-scrollbars-horizontal | -moz-scrollbars-vertical | -moz-hidden-unscrollable"
|
||||
},
|
||||
"-non-standard-width": {
|
||||
"comment": "non-standard keywords https://developer.mozilla.org/en-US/docs/Web/CSS/width",
|
||||
"syntax": "min-intrinsic | intrinsic | -moz-min-content | -moz-max-content | -webkit-min-content | -webkit-max-content"
|
||||
},
|
||||
"-non-standard-word-break": {
|
||||
"comment": "non-standard keywords https://css-tricks.com/almanac/properties/w/word-break/",
|
||||
"syntax": "break-word"
|
||||
},
|
||||
"-webkit-gradient()": {
|
||||
"comment": "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/ - TODO: simplify when after match algorithm improvement ( [, point, radius | , point] -> [, radius]? , point )",
|
||||
"syntax": "-webkit-gradient( <-webkit-gradient-type>, <-webkit-gradient-point> [, <-webkit-gradient-point> | , <-webkit-gradient-radius>, <-webkit-gradient-point> ] [, <-webkit-gradient-radius>]? [, <-webkit-gradient-color-stop>]* )"
|
||||
},
|
||||
"-webkit-gradient-color-stop": {
|
||||
"comment": "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
|
||||
"syntax": "from( <color> ) | color-stop( [ <number-zero-one> | <percentage> ] , <color> ) | to( <color> )"
|
||||
},
|
||||
"-webkit-gradient-point": {
|
||||
"comment": "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
|
||||
"syntax": "[ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]"
|
||||
},
|
||||
"-webkit-gradient-radius": {
|
||||
"comment": "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
|
||||
"syntax": "<length> | <percentage>"
|
||||
},
|
||||
"-webkit-gradient-type": {
|
||||
"comment": "first Apple proposal gradient syntax https://webkit.org/blog/175/introducing-css-gradients/",
|
||||
"syntax": "linear | radial"
|
||||
},
|
||||
"-webkit-mask-box-repeat": {
|
||||
"comment": "missed; https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-mask-box-image",
|
||||
"syntax": "repeat | stretch | round"
|
||||
},
|
||||
"-webkit-mask-clip-style": {
|
||||
"comment": "missed; there is no enough information about `-webkit-mask-clip` property, but looks like all those keywords are working",
|
||||
"syntax": "border | border-box | padding | padding-box | content | content-box | text"
|
||||
},
|
||||
"-ms-filter": {
|
||||
"syntax": "[ <progid> | FlipH | FlipV ]+"
|
||||
},
|
||||
"age": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#voice-family",
|
||||
"syntax": "child | young | old"
|
||||
},
|
||||
"attr()": {
|
||||
"comment": "drop it since it's a generic",
|
||||
"syntax": null
|
||||
},
|
||||
"border-radius": {
|
||||
"comment": "missed, https://drafts.csswg.org/css-backgrounds-3/#the-border-radius",
|
||||
"syntax": "<length-percentage>{1,2}"
|
||||
},
|
||||
"bottom": {
|
||||
"comment": "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
|
||||
"syntax": "<length> | auto"
|
||||
},
|
||||
"content-list": {
|
||||
"comment": "missed -> https://drafts.csswg.org/css-content/#typedef-content-list (document-url, <target> and leader() is omitted util stabilization)",
|
||||
"syntax": "[ <string> | contents | <url> | <quote> | <attr()> | counter( <ident>, <'list-style-type'>? ) ]+"
|
||||
},
|
||||
"inset()": {
|
||||
"comment": "changed <border-radius> to <'border-radius'>",
|
||||
"syntax": "inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )"
|
||||
},
|
||||
"generic-voice": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#voice-family",
|
||||
"syntax": "[ <age>? <gender> <integer>? ]"
|
||||
},
|
||||
"gender": {
|
||||
"comment": "https://www.w3.org/TR/css3-speech/#voice-family",
|
||||
"syntax": "male | female | neutral"
|
||||
},
|
||||
"generic-family": {
|
||||
"comment": "added -apple-system",
|
||||
"references": [
|
||||
"https://webkit.org/blog/3709/using-the-system-font-in-web-content/"
|
||||
],
|
||||
"syntax": "serif | sans-serif | cursive | fantasy | monospace | -apple-system"
|
||||
},
|
||||
"gradient": {
|
||||
"comment": "added -webkit-gradient() since may to be used for legacy support",
|
||||
"syntax": "<-legacy-gradient> | <linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()>"
|
||||
},
|
||||
"left": {
|
||||
"comment": "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
|
||||
"syntax": "<length> | auto"
|
||||
},
|
||||
"mask-image": {
|
||||
"comment": "missed; https://drafts.fxtf.org/css-masking-1/#the-mask-image",
|
||||
"syntax": "<mask-reference>#"
|
||||
},
|
||||
"matrix()": {
|
||||
"comment": "redundant max",
|
||||
"syntax": "matrix( <number> [, <number> ]{5} )"
|
||||
},
|
||||
"matrix3d()": {
|
||||
"comment": "redundant max",
|
||||
"syntax": "matrix3d( <number> [, <number> ]{15} )"
|
||||
},
|
||||
"name-repeat": {
|
||||
"comment": "missed, and looks like obsolete, keep it as is since other property syntaxes should be changed too; https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-name-repeat",
|
||||
"syntax": "repeat( [ <positive-integer> | auto-fill ], <line-names>+)"
|
||||
},
|
||||
"named-color": {
|
||||
"comment": "replaced <ident> to list of colors according to https://www.w3.org/TR/css-color-4/#named-colors",
|
||||
"syntax": "transparent | aliceblue | antiquewhite | aqua | aquamarine | azure | beige | bisque | black | blanchedalmond | blue | blueviolet | brown | burlywood | cadetblue | chartreuse | chocolate | coral | cornflowerblue | cornsilk | crimson | cyan | darkblue | darkcyan | darkgoldenrod | darkgray | darkgreen | darkgrey | darkkhaki | darkmagenta | darkolivegreen | darkorange | darkorchid | darkred | darksalmon | darkseagreen | darkslateblue | darkslategray | darkslategrey | darkturquoise | darkviolet | deeppink | deepskyblue | dimgray | dimgrey | dodgerblue | firebrick | floralwhite | forestgreen | fuchsia | gainsboro | ghostwhite | gold | goldenrod | gray | green | greenyellow | grey | honeydew | hotpink | indianred | indigo | ivory | khaki | lavender | lavenderblush | lawngreen | lemonchiffon | lightblue | lightcoral | lightcyan | lightgoldenrodyellow | lightgray | lightgreen | lightgrey | lightpink | lightsalmon | lightseagreen | lightskyblue | lightslategray | lightslategrey | lightsteelblue | lightyellow | lime | limegreen | linen | magenta | maroon | mediumaquamarine | mediumblue | mediumorchid | mediumpurple | mediumseagreen | mediumslateblue | mediumspringgreen | mediumturquoise | mediumvioletred | midnightblue | mintcream | mistyrose | moccasin | navajowhite | navy | oldlace | olive | olivedrab | orange | orangered | orchid | palegoldenrod | palegreen | paleturquoise | palevioletred | papayawhip | peachpuff | peru | pink | plum | powderblue | purple | rebeccapurple | red | rosybrown | royalblue | saddlebrown | salmon | sandybrown | seagreen | seashell | sienna | silver | skyblue | slateblue | slategray | slategrey | snow | springgreen | steelblue | tan | teal | thistle | tomato | turquoise | violet | wheat | white | whitesmoke | yellow | yellowgreen | <-non-standard-color>"
|
||||
},
|
||||
"outline-radius": {
|
||||
"comment": "missed, looks like it's a similar to <border-radius> https://developer.mozilla.org/en/docs/Web/CSS/-moz-outline-radius",
|
||||
"syntax": "<border-radius>"
|
||||
},
|
||||
"paint": {
|
||||
"comment": "simplified SVG syntax (omit <icccolor>, replace <funciri> for <url>) https://www.w3.org/TR/SVG/painting.html#SpecifyingPaint",
|
||||
"syntax": "none | currentColor | <color> | <url> [ none | currentColor | <color> ]?"
|
||||
},
|
||||
"path()": {
|
||||
"comment": "missed, `motion` property was renamed, but left it as is for now; path() syntax was get from last draft https://drafts.fxtf.org/motion-1/#funcdef-offset-path-path",
|
||||
"syntax": "path( <string> )"
|
||||
},
|
||||
"right": {
|
||||
"comment": "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
|
||||
"syntax": "<length> | auto"
|
||||
},
|
||||
"shape": {
|
||||
"comment": "missed spaces in function body and add backwards compatible syntax",
|
||||
"syntax": "rect( [ [ <top>, <right>, <bottom>, <left> ] | [ <top> <right> <bottom> <left> ] ] )"
|
||||
},
|
||||
"single-transition": {
|
||||
"comment": "moved <single-transition-timing-function> in the beginning to avoid wrong match to <single-transition-property>",
|
||||
"syntax": "<single-transition-timing-function> || [ none | <single-transition-property> ] || <time> || <time>"
|
||||
},
|
||||
"svg-length": {
|
||||
"comment": "All coordinates and lengths in SVG can be specified with or without a unit identifier",
|
||||
"references": [
|
||||
"https://www.w3.org/TR/SVG11/coords.html#Units"
|
||||
],
|
||||
"syntax": "<percentage> | <length> | <number>"
|
||||
},
|
||||
"svg-writing-mode": {
|
||||
"comment": "SVG specific keywords (deprecated for CSS)",
|
||||
"references": [
|
||||
"https://developer.mozilla.org/en/docs/Web/CSS/writing-mode",
|
||||
"https://www.w3.org/TR/SVG/text.html#WritingModeProperty"
|
||||
],
|
||||
"syntax": "lr-tb | rl-tb | tb-rl | lr | rl | tb"
|
||||
},
|
||||
"top": {
|
||||
"comment": "missed; not sure we should add it, but no others except `shape` is using it so it's ok for now; https://drafts.fxtf.org/css-masking-1/#funcdef-clip-rect",
|
||||
"syntax": "<length> | auto"
|
||||
},
|
||||
"x": {
|
||||
"comment": "missed; not sure we should add it, but no others except `cursor` is using it so it's ok for now; https://drafts.csswg.org/css-ui-3/#cursor",
|
||||
"syntax": "<number>"
|
||||
},
|
||||
"y": {
|
||||
"comment": "missed; not sure we should add it, but no others except `cursor` is using so it's ok for now; https://drafts.csswg.org/css-ui-3/#cursor",
|
||||
"syntax": "<number>"
|
||||
},
|
||||
"var()": {
|
||||
"comment": "drop it since it's a generic (also syntax is incorrect and can't be parsed)",
|
||||
"syntax": null
|
||||
},
|
||||
"an-plus-b": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"feature-type": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"feature-value-block": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"feature-value-declaration": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"feature-value-block-list": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"feature-value-declaration-list": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"general-enclosed": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"keyframe-block": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"keyframe-block-list": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"mf-plain": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"mf-range": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"mf-value": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-and": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-condition": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-not": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-or": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-in-parens": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-feature": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-condition-without-or": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-query": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"media-query-list": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"nth": {
|
||||
"comment": "syntax has <an-plus-b> that doesn't support currently, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"page-selector": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"page-selector-list": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"page-body": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"page-margin-box": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"page-margin-box-type": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
},
|
||||
"pseudo-page": {
|
||||
"comment": "syntax is incorrect and can't be parsed, drop for now",
|
||||
"syntax": null
|
||||
}
|
||||
}
|
||||
}
|
||||
6
node_modules/csso/node_modules/css-tree/dist/csstree.js
generated
vendored
Normal file
6
node_modules/csso/node_modules/css-tree/dist/csstree.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/csso/node_modules/css-tree/dist/default-syntax.json
generated
vendored
Normal file
1
node_modules/csso/node_modules/css-tree/dist/default-syntax.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
node_modules/csso/node_modules/css-tree/docs/.DS_Store
generated
vendored
Normal file
BIN
node_modules/csso/node_modules/css-tree/docs/.DS_Store
generated
vendored
Normal file
Binary file not shown.
3
node_modules/csso/node_modules/css-tree/docs/Lexer.md
generated
vendored
Normal file
3
node_modules/csso/node_modules/css-tree/docs/Lexer.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Lexer
|
||||
|
||||
> To be done
|
||||
132
node_modules/csso/node_modules/css-tree/docs/List.md
generated
vendored
Normal file
132
node_modules/csso/node_modules/css-tree/docs/List.md
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
# List
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [Static methods](#static-methods)
|
||||
- [List.createItem](#listcreateitem)
|
||||
- [Properties](#properties)
|
||||
- [List#head](#listhead)
|
||||
- [List#tail](#listtail)
|
||||
- [List#cursor](#listcursor)
|
||||
- [Methods](#methods)
|
||||
- [List#createItem\(\)](#listcreateitem-1)
|
||||
- [List#updateCursors\(\)](#listupdatecursors)
|
||||
- [List#getSize\(\)](#listgetsize)
|
||||
- [List#fromArray\(\)](#listfromarray)
|
||||
- [List#toArray\(\)](#listtoarray)
|
||||
- [List#toJSON\(\)](#listtojson)
|
||||
- [List#isEmpty\(\)](#listisempty)
|
||||
- [List#first\(\)](#listfirst)
|
||||
- [List#last\(\)](#listlast)
|
||||
- [List#each\(\)](#listeach)
|
||||
- [List#forEach\(\)](#listforeach)
|
||||
- [List#eachRight\(\)](#listeachright)
|
||||
- [List#forEachRight\(\)](#listforeachright)
|
||||
- [List#nextUntil\(\)](#listnextuntil)
|
||||
- [List#prevUntil\(\)](#listprevuntil)
|
||||
- [List#some\(\)](#listsome)
|
||||
- [List#map\(\)](#listmap)
|
||||
- [List#filter\(\)](#listfilter)
|
||||
- [List#clear\(\)](#listclear)
|
||||
- [List#copy\(\)](#listcopy)
|
||||
- [List#prepend\(\)](#listprepend)
|
||||
- [List#prependData\(\)](#listprependdata)
|
||||
- [List#append\(\)](#listappend)
|
||||
- [List#appendData\(\)](#listappenddata)
|
||||
- [List#insert\(\)](#listinsert)
|
||||
- [List#insertData\(\)](#listinsertdata)
|
||||
- [List#remove\(\)](#listremove)
|
||||
- [List#push\(\)](#listpush)
|
||||
- [List#pop\(\)](#listpop)
|
||||
- [List#unshift\(\)](#listunshift)
|
||||
- [List#shift\(\)](#listshift)
|
||||
- [List#prependList\(\)](#listprependlist)
|
||||
- [List#appendList\(\)](#listappendlist)
|
||||
- [List#insertList\(\)](#listinsertlist)
|
||||
- [List#replace\(\)](#listreplace)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Static methods
|
||||
|
||||
### List.createItem
|
||||
|
||||
## Properties
|
||||
|
||||
### List#head
|
||||
|
||||
### List#tail
|
||||
|
||||
### List#cursor
|
||||
|
||||
## Methods
|
||||
|
||||
### List#createItem()
|
||||
|
||||
### List#updateCursors()
|
||||
|
||||
### List#getSize()
|
||||
|
||||
### List#fromArray()
|
||||
|
||||
### List#toArray()
|
||||
|
||||
### List#toJSON()
|
||||
|
||||
### List#isEmpty()
|
||||
|
||||
### List#first()
|
||||
|
||||
### List#last()
|
||||
|
||||
### List#each()
|
||||
|
||||
### List#forEach()
|
||||
|
||||
### List#eachRight()
|
||||
|
||||
### List#forEachRight()
|
||||
|
||||
### List#nextUntil()
|
||||
|
||||
### List#prevUntil()
|
||||
|
||||
### List#some()
|
||||
|
||||
### List#map()
|
||||
|
||||
### List#filter()
|
||||
|
||||
### List#clear()
|
||||
|
||||
### List#copy()
|
||||
|
||||
### List#prepend()
|
||||
|
||||
### List#prependData()
|
||||
|
||||
### List#append()
|
||||
|
||||
### List#appendData()
|
||||
|
||||
### List#insert()
|
||||
|
||||
### List#insertData()
|
||||
|
||||
### List#remove()
|
||||
|
||||
### List#push()
|
||||
|
||||
### List#pop()
|
||||
|
||||
### List#unshift()
|
||||
|
||||
### List#shift()
|
||||
|
||||
### List#prependList()
|
||||
|
||||
### List#appendList()
|
||||
|
||||
### List#insertList()
|
||||
|
||||
### List#replace()
|
||||
131
node_modules/csso/node_modules/css-tree/docs/Tokenizer.md
generated
vendored
Normal file
131
node_modules/csso/node_modules/css-tree/docs/Tokenizer.md
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
# Tokenizer
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [Static properties](#static-properties)
|
||||
- [CssSyntaxError](#csssyntaxerror)
|
||||
- [TYPE](#type)
|
||||
- [NAME](#name)
|
||||
- [SYMBOL_TYPE](#symbol_type)
|
||||
- [PUNCTUATION](#punctuation)
|
||||
- [Static methods](#static-methods)
|
||||
- [firstCharOffset\(source\)](#firstcharoffsetsource)
|
||||
- [isHex\(code\)](#ishexcode)
|
||||
- [isNumber\(code\)](#isnumbercode)
|
||||
- [isNewline\(source, offset, code\)](#isnewlinesource-offset-code)
|
||||
- [cmpChar\(testStr, offset, referenceCode\)](#cmpcharteststr-offset-referencecode)
|
||||
- [cmpStr\(testStr, start, end, referenceStr\)](#cmpstrteststr-start-end-referencestr)
|
||||
- [endsWith\(testStr, referenceStr\)](#endswithteststr-referencestr)
|
||||
- [findLastNonSpaceLocation\(scanner\)](#findlastnonspacelocationscanner)
|
||||
- [findWhitespaceEnd\(source, offset\)](#findwhitespaceendsource-offset)
|
||||
- [findCommentEnd\(source, offset\)](#findcommentendsource-offset)
|
||||
- [findStringEnd\(source, offset, quote\)](#findstringendsource-offset-quote)
|
||||
- [findDecimalNumberEnd\(source, offset\)](#finddecimalnumberendsource-offset)
|
||||
- [findNumberEnd\(source, offset, allowFraction\)](#findnumberendsource-offset-allowfraction)
|
||||
- [findEscaseEnd\(source, offset\)](#findescaseendsource-offset)
|
||||
- [findIdentifierEnd\(source, offset\)](#findidentifierendsource-offset)
|
||||
- [Methods](#methods)
|
||||
- [setSource\(source, startOffset, startLine, startColumn\)](#setsourcesource-startoffset-startline-startcolumn)
|
||||
- [lookupType\(offset\)](#lookuptypeoffset)
|
||||
- [lookupNonWSType\(offset\)](#lookupnonwstypeoffset)
|
||||
- [lookupValue\(offset, referenceStr\)](#lookupvalueoffset-referencestr)
|
||||
- [getTokenValue\(\)](#gettokenvalue)
|
||||
- [substrToCursor\(start\)](#substrtocursorstart)
|
||||
- [skipWS\(\)](#skipws)
|
||||
- [skip\(tokenCount\)](#skiptokencount)
|
||||
- [next\(\)](#next)
|
||||
- [eat\(tokenType\)](#eattokentype)
|
||||
- [eatNonWS\(tokenType\)](#eatnonwstokentype)
|
||||
- [consume\(tokenType\)](#consumetokentype)
|
||||
- [consumeNonWS\(tokenType\)](#consumenonwstokentype)
|
||||
- [expectIdentifier\(name\)](#expectidentifiername)
|
||||
- [getLocation\(offset, filename\)](#getlocationoffset-filename)
|
||||
- [getLocationRange\(start, end, filename\)](#getlocationrangestart-end-filename)
|
||||
- [error\(message, offset\)](#errormessage-offset)
|
||||
- [getTypes\(\)](#gettypes)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Static properties
|
||||
|
||||
### CssSyntaxError
|
||||
|
||||
### TYPE
|
||||
|
||||
### NAME
|
||||
|
||||
### SYMBOL_TYPE
|
||||
|
||||
### PUNCTUATION
|
||||
|
||||
|
||||
## Static methods
|
||||
|
||||
### firstCharOffset(source)
|
||||
|
||||
### isHex(code)
|
||||
|
||||
### isNumber(code)
|
||||
|
||||
### isNewline(source, offset, code)
|
||||
|
||||
### cmpChar(testStr, offset, referenceCode)
|
||||
|
||||
### cmpStr(testStr, start, end, referenceStr)
|
||||
|
||||
### endsWith(testStr, referenceStr)
|
||||
|
||||
### findLastNonSpaceLocation(scanner)
|
||||
|
||||
### findWhitespaceEnd(source, offset)
|
||||
|
||||
### findCommentEnd(source, offset)
|
||||
|
||||
### findStringEnd(source, offset, quote)
|
||||
|
||||
### findDecimalNumberEnd(source, offset)
|
||||
|
||||
### findNumberEnd(source, offset, allowFraction)
|
||||
|
||||
### findEscaseEnd(source, offset)
|
||||
|
||||
### findIdentifierEnd(source, offset)
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
### setSource(source, startOffset, startLine, startColumn)
|
||||
|
||||
### lookupType(offset)
|
||||
|
||||
### lookupNonWSType(offset)
|
||||
|
||||
### lookupValue(offset, referenceStr)
|
||||
|
||||
### getTokenValue()
|
||||
|
||||
### substrToCursor(start)
|
||||
|
||||
### skipWS()
|
||||
|
||||
### skip(tokenCount)
|
||||
|
||||
### next()
|
||||
|
||||
### eat(tokenType)
|
||||
|
||||
### eatNonWS(tokenType)
|
||||
|
||||
### consume(tokenType)
|
||||
|
||||
### consumeNonWS(tokenType)
|
||||
|
||||
### expectIdentifier(name)
|
||||
|
||||
### getLocation(offset, filename)
|
||||
|
||||
### getLocationRange(start, end, filename)
|
||||
|
||||
### error(message, offset)
|
||||
|
||||
### getTypes()
|
||||
3
node_modules/csso/node_modules/css-tree/docs/api-map.svg
generated
vendored
Normal file
3
node_modules/csso/node_modules/css-tree/docs/api-map.svg
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 42 KiB |
567
node_modules/csso/node_modules/css-tree/docs/ast.md
generated
vendored
Normal file
567
node_modules/csso/node_modules/css-tree/docs/ast.md
generated
vendored
Normal file
@@ -0,0 +1,567 @@
|
||||
# AST format
|
||||
|
||||
CSSTree's AST consists of nodes (leafs). Each node is an object with a set of properties that depends on node's type. Nodes can refers to other nodes and contain a list of nested nodes.
|
||||
|
||||
Interactively explore the AST with [AST Explorer](https://astexplorer.net/#/gist/244e2fb4da940df52bf0f4b94277db44/e79aff44611020b22cfd9708f3a99ce09b7d67a8).
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [Example](#example)
|
||||
- [Common node's properties](#common-nodes-properties)
|
||||
- [type](#type)
|
||||
- [loc](#loc)
|
||||
- [children](#children)
|
||||
- [Node types](#node-types)
|
||||
- [AnPlusB](#anplusb)
|
||||
- [Atrule](#atrule)
|
||||
- [AtrulePrelude](#atruleprelude)
|
||||
- [AttributeSelector](#attributeselector)
|
||||
- [Block](#block)
|
||||
- [Brackets](#brackets)
|
||||
- [CDC](#cdc)
|
||||
- [CDO](#cdo)
|
||||
- [ClassSelector](#classselector)
|
||||
- [Combinator](#combinator)
|
||||
- [Comment](#comment)
|
||||
- [Declaration](#declaration)
|
||||
- [DeclarationList](#declarationlist)
|
||||
- [Dimension](#dimension)
|
||||
- [Function](#function)
|
||||
- [HexColor](#hexcolor)
|
||||
- [IdSelector](#idselector)
|
||||
- [Identifier](#identifier)
|
||||
- [MediaFeature](#mediafeature)
|
||||
- [MediaQuery](#mediaquery)
|
||||
- [MediaQueryList](#mediaquerylist)
|
||||
- [Nth](#nth)
|
||||
- [Number](#number)
|
||||
- [Operator](#operator)
|
||||
- [Parentheses](#parentheses)
|
||||
- [Percentage](#percentage)
|
||||
- [PseudoClassSelector](#pseudoclassselector)
|
||||
- [PseudoElementSelector](#pseudoelementselector)
|
||||
- [Ratio](#ratio)
|
||||
- [Raw](#raw)
|
||||
- [Rule](#rule)
|
||||
- [Selector](#selector)
|
||||
- [SelectorList](#selectorlist)
|
||||
- [String](#string)
|
||||
- [StyleSheet](#stylesheet)
|
||||
- [TypeSelector](#typeselector)
|
||||
- [UnicodeRange](#unicoderange)
|
||||
- [Url](#url)
|
||||
- [Value](#value)
|
||||
- [WhiteSpace](#whitespace)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Example
|
||||
|
||||
Assume we have a CSS:
|
||||
|
||||
```css
|
||||
body {
|
||||
color: red;
|
||||
}
|
||||
```
|
||||
|
||||
An AST for this CSS might look like:
|
||||
|
||||
```js
|
||||
{
|
||||
type: 'StyleSheet',
|
||||
loc: null,
|
||||
children: [
|
||||
{
|
||||
type: 'Rule',
|
||||
loc: null,
|
||||
prelude: {
|
||||
type: 'SelectorList',
|
||||
loc: null,
|
||||
children: [
|
||||
{
|
||||
type: 'Selector',
|
||||
loc: null,
|
||||
children: [
|
||||
{
|
||||
type: 'TypeSelector',
|
||||
loc: null,
|
||||
name: 'body'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
block: {
|
||||
type: 'Block',
|
||||
loc: null,
|
||||
children: [
|
||||
{
|
||||
type: 'Declaration',
|
||||
loc: null,
|
||||
important: false,
|
||||
property: 'color',
|
||||
value: {
|
||||
type: 'Value',
|
||||
loc: null,
|
||||
children: [
|
||||
{
|
||||
type: 'Identifier',
|
||||
loc: null,
|
||||
name: 'red'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> NOTE: The example uses arrays for the values of the property `children`. In fact, the values of this property are instances of the [`List`](List.md) class.
|
||||
|
||||
An AST structure (i.e. details level, include positions or not) is depend on options passed to parser. See [Parsing CSS into AST](parsing.md) for details.
|
||||
|
||||
## Common node's properties
|
||||
|
||||
All nodes have the following properties.
|
||||
|
||||
### type
|
||||
|
||||
Type: `String`
|
||||
|
||||
Indicates the type of a node. The possible values are the ones listed in the [Node types](#node-types) below.
|
||||
|
||||
### loc
|
||||
|
||||
Type: `Object` or `null`
|
||||
|
||||
Information about the position in the source string that corresponds to the node. It has the following structure:
|
||||
|
||||
```js
|
||||
{
|
||||
source: String,
|
||||
start: {
|
||||
offset: Number,
|
||||
line: Number,
|
||||
column: Number
|
||||
},
|
||||
end: {
|
||||
offset: Number,
|
||||
line: Number,
|
||||
column: Number
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `source` property contains value of `options.filename` if passed to `csstree.parse()`, otherwise `"<unknown>"`.
|
||||
|
||||
The `offset` number is zero-based, indicates the index in a source string passed to the parser.
|
||||
|
||||
The `line` and `column` numbers are 1-based: the first line is `1` and the first column of a line is `1`.
|
||||
|
||||
The `loc` property lets you know from which source file the node comes from (if available) and what part of that file was parsed into the node. By default parser doesn't include `loc` data into the AST (sets `null` for this property), you should pass `options.positions` equal to `true` to make `loc` filled.
|
||||
|
||||
### children
|
||||
|
||||
Type: `List` or `null`
|
||||
|
||||
Only certain types of nodes can contain this property, such as [`StyleSheet`](#stylesheet) or [`Block`](#block). However, this is the only property that can store a list of nested nodes.
|
||||
|
||||
Most node types always store an instance of the `List` in this property, even if there is no nested nodes (the list is empty). Only some node types, such as `PseudoClassSelector` and `PseudoElementSelector`, can store a `null` instead of a list. This is due to the fact that in the absence of a list such node types is represent a pseudo-selector, and in the presence of a list, a functional pseudo-selector. See definition of each node type for details.
|
||||
|
||||
## Node types
|
||||
|
||||
> NOTE: Despite every node has a `loc` property, this property is excluded from definitions to reduce a noise.
|
||||
|
||||
<!-- node types -->
|
||||
|
||||
### AnPlusB
|
||||
|
||||
Used for [the An+B microsyntax](https://drafts.csswg.org/css-syntax/#anb-microsyntax).
|
||||
|
||||
```js
|
||||
{
|
||||
type: "AnPlusB",
|
||||
a: String | null,
|
||||
b: String | null
|
||||
}
|
||||
```
|
||||
|
||||
`a` or `b` fields may have no value (equals to `null`) but not both at the same time. Parser normalizes `a` value to store a valid integer, i.e. parser will store `-1` for `-n` and `1` for `n`.
|
||||
|
||||
### Atrule
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Atrule",
|
||||
name: String,
|
||||
prelude: <AtrulePrelude> | <Raw> | null,
|
||||
block: <Block> | null
|
||||
}
|
||||
```
|
||||
|
||||
### AtrulePrelude
|
||||
|
||||
```js
|
||||
{
|
||||
type: "AtrulePrelude",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### AttributeSelector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "AttributeSelector",
|
||||
name: <Identifier>,
|
||||
matcher: String | null,
|
||||
value: <String> | <Identifier> | null,
|
||||
flags: String | null
|
||||
}
|
||||
```
|
||||
|
||||
### Block
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Block",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### Brackets
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Brackets",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### CDC
|
||||
|
||||
```js
|
||||
{
|
||||
type: "CDC"
|
||||
}
|
||||
```
|
||||
|
||||
### CDO
|
||||
|
||||
```js
|
||||
{
|
||||
type: "CDO"
|
||||
}
|
||||
```
|
||||
|
||||
### ClassSelector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "ClassSelector",
|
||||
name: String
|
||||
}
|
||||
```
|
||||
|
||||
### Combinator
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Combinator",
|
||||
name: String
|
||||
}
|
||||
```
|
||||
|
||||
### Comment
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Comment",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### Declaration
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Declaration",
|
||||
important: Boolean | String,
|
||||
property: String,
|
||||
value: <Value> | <Raw>
|
||||
}
|
||||
```
|
||||
|
||||
### DeclarationList
|
||||
|
||||
```js
|
||||
{
|
||||
type: "DeclarationList",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### Dimension
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Dimension",
|
||||
value: String,
|
||||
unit: String
|
||||
}
|
||||
```
|
||||
|
||||
### Function
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Function",
|
||||
name: String,
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### HexColor
|
||||
|
||||
```js
|
||||
{
|
||||
type: "HexColor",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### IdSelector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "IdSelector",
|
||||
name: String
|
||||
}
|
||||
```
|
||||
|
||||
### Identifier
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Identifier",
|
||||
name: String
|
||||
}
|
||||
```
|
||||
|
||||
### MediaFeature
|
||||
|
||||
```js
|
||||
{
|
||||
type: "MediaFeature",
|
||||
name: String,
|
||||
value: <Identifier> | <Number> | <Dimension> | <Ratio> | null
|
||||
}
|
||||
```
|
||||
|
||||
### MediaQuery
|
||||
|
||||
```js
|
||||
{
|
||||
type: "MediaQuery",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### MediaQueryList
|
||||
|
||||
```js
|
||||
{
|
||||
type: "MediaQueryList",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### Nth
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Nth",
|
||||
nth: <AnPlusB> | <Identifier>,
|
||||
selector: <SelectorList> | null
|
||||
}
|
||||
```
|
||||
|
||||
### Number
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Number",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### Operator
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Operator",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### Parentheses
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Parentheses",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### Percentage
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Percentage",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### PseudoClassSelector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "PseudoClassSelector",
|
||||
name: String,
|
||||
children: List | null
|
||||
}
|
||||
```
|
||||
|
||||
### PseudoElementSelector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "PseudoElementSelector",
|
||||
name: String,
|
||||
children: List | null
|
||||
}
|
||||
```
|
||||
|
||||
### Ratio
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Ratio",
|
||||
left: String,
|
||||
right: String
|
||||
}
|
||||
```
|
||||
|
||||
### Raw
|
||||
|
||||
A sequence of any characters. This node type is used for unparsed fragments of CSS, e.g. due to parse error or parser settings, and for quirk parts like content of some functions, such as `url()` or `expression()`.
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Raw",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### Rule
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Rule",
|
||||
prelude: <SelectorList> | <Raw>,
|
||||
block: <Block>
|
||||
}
|
||||
```
|
||||
|
||||
### Selector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Selector",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### SelectorList
|
||||
|
||||
```js
|
||||
{
|
||||
type: "SelectorList",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### String
|
||||
|
||||
A sequence of characters enclosed in double quotes or single quotes.
|
||||
|
||||
```js
|
||||
{
|
||||
type: "String",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### StyleSheet
|
||||
|
||||
```js
|
||||
{
|
||||
type: "StyleSheet",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### TypeSelector
|
||||
|
||||
```js
|
||||
{
|
||||
type: "TypeSelector",
|
||||
name: String
|
||||
}
|
||||
```
|
||||
|
||||
### UnicodeRange
|
||||
|
||||
Used for [the Unicode-Range microsyntax](https://drafts.csswg.org/css-syntax/#urange).
|
||||
|
||||
```js
|
||||
{
|
||||
type: "UnicodeRange",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
### Url
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Url",
|
||||
value: <String> | <Raw>
|
||||
}
|
||||
```
|
||||
|
||||
### Value
|
||||
|
||||
```js
|
||||
{
|
||||
type: "Value",
|
||||
children: List
|
||||
}
|
||||
```
|
||||
|
||||
### WhiteSpace
|
||||
|
||||
A sequence of one or more white spaces, i.e. ` ` (space), `\t`, `\r`, `\n` and `\f`.
|
||||
|
||||
```js
|
||||
{
|
||||
type: "WhiteSpace",
|
||||
value: String
|
||||
}
|
||||
```
|
||||
|
||||
<!-- /node types -->
|
||||
48
node_modules/csso/node_modules/css-tree/docs/generate.md
generated
vendored
Normal file
48
node_modules/csso/node_modules/css-tree/docs/generate.md
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# Translate AST to string
|
||||
|
||||
## generate(ast[, options])
|
||||
|
||||
Generates a CSS string for given AST.
|
||||
|
||||
```js
|
||||
// generate with default settings
|
||||
csstree.generate(ast);
|
||||
|
||||
// generate with options
|
||||
csstree.generate(ast, {
|
||||
sourceMap: true
|
||||
});
|
||||
```
|
||||
|
||||
Options (optional):
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [sourceMap](#sourcemap)
|
||||
- [decorator](#decorator)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
### sourceMap
|
||||
|
||||
Type: `boolean`
|
||||
Default: `false`
|
||||
|
||||
Generates a source map (nodes should contain positions in `loc` property). Note, that an object instead of string is returned in that case.
|
||||
|
||||
```js
|
||||
var ast = csstree.parse('.test { color: red }', {
|
||||
filename: 'my.css',
|
||||
positions: true
|
||||
});
|
||||
|
||||
var result = csstree.generate(ast, { sourceMap: true });
|
||||
// { css: '.test{color:red}', map: SourceMapGenerator {} }
|
||||
```
|
||||
|
||||
### decorator
|
||||
|
||||
Type: `function`
|
||||
Default: none
|
||||
|
||||
A function that a handlers used by a generator. TBD
|
||||
285
node_modules/csso/node_modules/css-tree/docs/parsing.md
generated
vendored
Normal file
285
node_modules/csso/node_modules/css-tree/docs/parsing.md
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
# Parsing CSS into AST
|
||||
|
||||
> NOTE: Currenly parser omits redundant separators, spaces and comments (except exclamation comments, i.e. `/*! comment */`) on AST build.
|
||||
|
||||
## parse(source[, options])
|
||||
|
||||
Parses CSS into AST.
|
||||
|
||||
```js
|
||||
// simple parsing with no options
|
||||
var ast = csstree.parse('.example { color: red }');
|
||||
|
||||
// parse with options
|
||||
var ast = csstree.parse('.foo.bar', {
|
||||
context: 'selector',
|
||||
positions: true
|
||||
});
|
||||
```
|
||||
|
||||
Options (optional):
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [context](#context)
|
||||
- [atrule](#atrule)
|
||||
- [positions](#positions)
|
||||
- [onParseError](#onparseerror)
|
||||
- [filename](#filename)
|
||||
- [offset](#offset)
|
||||
- [line](#line)
|
||||
- [column](#column)
|
||||
- [parseAtrulePrelude](#parseatruleprelude)
|
||||
- [parseRulePrelude](#parseruleprelude)
|
||||
- [parseValue](#parsevalue)
|
||||
- [parseCustomProperty](#parsecustomproperty)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
### context
|
||||
|
||||
Type: `string`
|
||||
Default: `'stylesheet'`
|
||||
|
||||
Defines what part of CSS is parsing.
|
||||
|
||||
Contexts:
|
||||
|
||||
- `stylesheet` (default) – regular stylesheet, should be suitable in most cases
|
||||
- `atrule` – at-rule (e.g. `@media screen, print { ... }`)
|
||||
- `atrulePrelude` – at-rule prelude (`screen, print` for example above)
|
||||
- `mediaQueryList` – used to parse comma separated media query list
|
||||
- `mediaQuery` – used to parse media query
|
||||
- `rule` – rule (e.g. `.foo, .bar:hover { color: red; border: 1px solid black; }`)
|
||||
- `selectorList` – selector group (`.foo, .bar:hover` for rule example)
|
||||
- `selector` – selector (`.foo` or `.bar:hover` for rule example)
|
||||
- `block` – block with curly braces (`{ color: red; border: 1px solid black; }` for rule example)
|
||||
- `declarationList` – block content w/o curly braces (`color: red; border: 1px solid black;` for rule example), useful for parsing HTML `style` attribute value
|
||||
- `declaration` – declaration (`color: red` or `border: 1px solid black` for rule example)
|
||||
- `value` – declaration value (`red` or `1px solid black` for rule example)
|
||||
|
||||
### atrule
|
||||
|
||||
Type: `string` or `null`
|
||||
Default: `null`
|
||||
|
||||
Using for `atrulePrelude` context to apply atrule specific parse rules.
|
||||
|
||||
### positions
|
||||
|
||||
Type: `boolean`
|
||||
Default: `false`
|
||||
|
||||
Specify to store locations of node content in original source. Location is storing as `loc` field of nodes. `loc` property is always `null` when option is `false`. The structure of `loc`:
|
||||
|
||||
```
|
||||
loc: {
|
||||
source: 'value of `filename` option or `<unknown>`',
|
||||
start: {
|
||||
offset: <number>,
|
||||
line: <number>,
|
||||
column: <number>
|
||||
},
|
||||
end: {
|
||||
offset: <number>,
|
||||
line: <number>,
|
||||
column: <number>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### onParseError
|
||||
|
||||
Type: `function(error, fallbackNode)` or `null`
|
||||
Default: `null`
|
||||
|
||||
Parsing is tolerant by default, i.e. any text may to be parsed with no an raised exception. However, mistakes in CSS may make it imposible to parse some part, e.g. a selector or declaration. In that case bad content is wrapping into a `Raw` node and `onParseError` is invoking.
|
||||
|
||||
```js
|
||||
csstree.parse('example { foo; bar: 1! }', {
|
||||
onParseError: function(error) {
|
||||
console.log(error.formattedMessage);
|
||||
}
|
||||
});
|
||||
// Parse error: Colon is expected
|
||||
// 1 |example { foo; bar: 1! }
|
||||
// --------------------^
|
||||
// Parse error: Identifier is expected
|
||||
// 1 |example { foo; bar: 1! }
|
||||
// ------------------------------^
|
||||
```
|
||||
|
||||
### filename
|
||||
|
||||
Type: `string`
|
||||
Default: `'<unknown>'`
|
||||
|
||||
Filename of source. This value adds to `loc` as `source` property when `positions` option is `true`. Using for source map generation.
|
||||
|
||||
### offset
|
||||
|
||||
Type: `number`
|
||||
Default: `0`
|
||||
|
||||
Start offset. Useful when parsing a fragment of CSS to store a correct positions for node's `loc` property.
|
||||
|
||||
### line
|
||||
|
||||
Type: `number`
|
||||
Default: `1`
|
||||
|
||||
Start line number. Useful when parsing fragment of CSS to store correct positions in node's `loc` property.
|
||||
|
||||
### column
|
||||
|
||||
Type: `number`
|
||||
Default: `1`
|
||||
|
||||
Start column number. Useful when parsing fragment of CSS to store correct positions in node's `loc` property.
|
||||
|
||||
### parseAtrulePrelude
|
||||
|
||||
Type: `boolean`
|
||||
Default: `true`
|
||||
|
||||
Defines to parse a at-rule prelude in details (represents as `AtruleExpresion`, `MediaQueryList` or `SelectorList` if any). Otherwise represents prelude as `Raw` node.
|
||||
|
||||
```js
|
||||
csstree.parse('@example 1 2;');
|
||||
// {
|
||||
// "type": "Atrule",
|
||||
// "prelude": {
|
||||
// "type": "AtrulePrelude",
|
||||
// "children": [
|
||||
// { "type": "Number", "value": "1" },
|
||||
// { "type": "WhiteSpace", "value": " " },
|
||||
// { "type": "Number", "value": "2" }
|
||||
// ]
|
||||
// },
|
||||
// "block": null
|
||||
// }
|
||||
|
||||
csstree.parse('@example 1 2;', { parseAtrulePrelude: false });
|
||||
// {
|
||||
// "type": "Atrule",
|
||||
// "prelude": {
|
||||
// "type": "Raw",
|
||||
// "value": "1 2"
|
||||
// },
|
||||
// "block": null
|
||||
// }
|
||||
```
|
||||
|
||||
### parseRulePrelude
|
||||
|
||||
Type: `boolean`
|
||||
Default: `true`
|
||||
|
||||
Defines to parse a rule prelude in details or left unparsed (represents as `Raw` node).
|
||||
|
||||
```js
|
||||
csstree.parse('.foo {}');
|
||||
// {
|
||||
// "type": "Rule",
|
||||
// "prelude": {
|
||||
// "type": "SelectorList",
|
||||
// "children": [
|
||||
// {
|
||||
// "type": "Selector",
|
||||
// "children": [
|
||||
// { "type": "ClassSelector", "name": "foo" }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// "block": {
|
||||
// "type": "Block",
|
||||
// "children": []
|
||||
// }
|
||||
// }
|
||||
|
||||
csstree.parse('.foo {}', { parseRulePrelude: false });
|
||||
// {
|
||||
// "type": "Rule",
|
||||
// "prelude": {
|
||||
// "type": "Raw",
|
||||
// "value": ".foo"
|
||||
// },
|
||||
// "block": {
|
||||
// "type": "Block",
|
||||
// "children": []
|
||||
// }
|
||||
// }
|
||||
```
|
||||
|
||||
### parseValue
|
||||
|
||||
Type: `boolean`
|
||||
Default: `true`
|
||||
|
||||
Defines to parse a declaration value in details (represents as `Value`). Otherwise represents value as `Raw` node.
|
||||
|
||||
```js
|
||||
csstree.parse('color: #aabbcc', { context: 'declaration' });
|
||||
// {
|
||||
// "type": "Declaration",
|
||||
// "important": false,
|
||||
// "property": "color",
|
||||
// "value": {
|
||||
// "type": "Value",
|
||||
// "children": [
|
||||
// {
|
||||
// "type": "HexColor",
|
||||
// "value": "aabbcc"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
|
||||
csstree.parse('color: #aabbcc', { context: 'declaration', parseValue: false });
|
||||
// {
|
||||
// "type": "Declaration",
|
||||
// "important": false,
|
||||
// "property": "color",
|
||||
// "value": {
|
||||
// "type": "Raw",
|
||||
// "value": " #aabbcc"
|
||||
// }
|
||||
// }
|
||||
```
|
||||
|
||||
### parseCustomProperty
|
||||
|
||||
Type: `boolean`
|
||||
Default: `false`
|
||||
|
||||
Defines to parse a custom property value and a `var()` fallback in details (represents as `Value`). Otherwise represents value as `Raw` node.
|
||||
|
||||
```js
|
||||
csstree.parse('--custom: #aabbcc', { context: 'declaration' });
|
||||
// {
|
||||
// "type": "Declaration",
|
||||
// "important": false,
|
||||
// "property": "--custom",
|
||||
// "value": {
|
||||
// "type": "Raw",
|
||||
// "value": " #aabbcc"
|
||||
// }
|
||||
// }
|
||||
|
||||
csstree.parse('--custom: #aabbcc', { context: 'declaration', parseCustomProperty: true });
|
||||
// {
|
||||
// "type": "Declaration",
|
||||
// "important": false,
|
||||
// "property": "--custom",
|
||||
// "value": {
|
||||
// "type": "Value",
|
||||
// "children": [
|
||||
// {
|
||||
// "type": "HexColor",
|
||||
// "value": "aabbcc"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
```
|
||||
15
node_modules/csso/node_modules/css-tree/docs/readme.md
generated
vendored
Normal file
15
node_modules/csso/node_modules/css-tree/docs/readme.md
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# API
|
||||
|
||||
## General
|
||||
|
||||
- [Parsing CSS into AST](parsing.md)
|
||||
- [AST format](ast.md)
|
||||
- [Generate CSS from AST](generate.md)
|
||||
- [AST traversal](traversal.md)
|
||||
- [Utils to work with AST](utils.md)
|
||||
|
||||
## Classes
|
||||
|
||||
- [Tokenizer](Tokenizer.md)
|
||||
- [Lexer](Lexer.md)
|
||||
- [List](List.md)
|
||||
573
node_modules/csso/node_modules/css-tree/docs/supported.md
generated
vendored
Normal file
573
node_modules/csso/node_modules/css-tree/docs/supported.md
generated
vendored
Normal file
@@ -0,0 +1,573 @@
|
||||
# Supported syntaxes
|
||||
|
||||
> ⚠️ This is a basic implementation of support reference. Further improvements are pending. See comments on each section for details.
|
||||
|
||||
> ⚠️ This page is auto-generated. Please, don't update any content between special comments.
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [Atrules](#atrules)
|
||||
- [Functional pseudos](#functional-pseudos)
|
||||
- [Properties](#properties)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Atrules
|
||||
|
||||
At-rules with a custom parsing rules. In fact, any at-rule is supported but prelude and block are parsing with default rules. Validation support isn't supported for at-rules at the moment.
|
||||
|
||||
<!-- gen:atrule -->
|
||||
|
||||
- `@font-face`
|
||||
- `@import`
|
||||
- `@media`
|
||||
- `@page`
|
||||
- `@supports`
|
||||
|
||||
<!-- /gen:atrule -->
|
||||
|
||||
## Functional pseudos
|
||||
|
||||
Functional pseudos with a custom parsing rule. Non-listed functional pseudos don't parse a content inside parentheses and represent it as a `Raw` node if any. There is no difference between pseudo class and pseudo element on parsing, like no validation for functional pseudos is supported at the moment.
|
||||
|
||||
<!-- gen:pseudo -->
|
||||
|
||||
- `:dir()`
|
||||
- `:has()`
|
||||
- `:lang()`
|
||||
- `:matches()`
|
||||
- `:not()`
|
||||
- `:nth-child()`
|
||||
- `:nth-last-child()`
|
||||
- `:nth-last-of-type()`
|
||||
- `:nth-of-type()`
|
||||
- `:slotted()`
|
||||
|
||||
<!-- /gen:pseudo -->
|
||||
|
||||
## Properties
|
||||
|
||||
Support for a property means CSSTree has a grammar for such property, so its value can be checked (validated) for complience to spec or browser inplementations (for non-standart properties). The validation doesn't perform on parsing stage and should be done as a separate step using Lexer API. In other words any property value can be parsed with default parsing rules, but validation is possible for listed properties only.
|
||||
|
||||
<!-- gen:properties -->
|
||||
|
||||
- `-moz-appearance`
|
||||
- `-moz-background-clip`
|
||||
- `-moz-binding`
|
||||
- `-moz-border-bottom-colors`
|
||||
- `-moz-border-left-colors`
|
||||
- `-moz-border-radius-bottomleft`
|
||||
- `-moz-border-radius-bottomright`
|
||||
- `-moz-border-radius-topleft`
|
||||
- `-moz-border-radius-topright`
|
||||
- `-moz-border-right-colors`
|
||||
- `-moz-border-top-colors`
|
||||
- `-moz-context-properties`
|
||||
- `-moz-float-edge`
|
||||
- `-moz-force-broken-image-icon`
|
||||
- `-moz-image-region`
|
||||
- `-moz-orient`
|
||||
- `-moz-osx-font-smoothing`
|
||||
- `-moz-outline-radius`
|
||||
- `-moz-outline-radius-bottomleft`
|
||||
- `-moz-outline-radius-bottomright`
|
||||
- `-moz-outline-radius-topleft`
|
||||
- `-moz-outline-radius-topright`
|
||||
- `-moz-stack-sizing`
|
||||
- `-moz-text-blink`
|
||||
- `-moz-user-focus`
|
||||
- `-moz-user-input`
|
||||
- `-moz-user-modify`
|
||||
- `-moz-user-select`
|
||||
- `-moz-window-dragging`
|
||||
- `-moz-window-shadow`
|
||||
- `-ms-accelerator`
|
||||
- `-ms-block-progression`
|
||||
- `-ms-content-zoom-chaining`
|
||||
- `-ms-content-zoom-limit`
|
||||
- `-ms-content-zoom-limit-max`
|
||||
- `-ms-content-zoom-limit-min`
|
||||
- `-ms-content-zoom-snap`
|
||||
- `-ms-content-zoom-snap-points`
|
||||
- `-ms-content-zoom-snap-type`
|
||||
- `-ms-content-zooming`
|
||||
- `-ms-filter`
|
||||
- `-ms-flex-align`
|
||||
- `-ms-flex-item-align`
|
||||
- `-ms-flex-line-pack`
|
||||
- `-ms-flex-negative`
|
||||
- `-ms-flex-order`
|
||||
- `-ms-flex-pack`
|
||||
- `-ms-flex-positive`
|
||||
- `-ms-flex-preferred-size`
|
||||
- `-ms-flow-from`
|
||||
- `-ms-flow-into`
|
||||
- `-ms-grid-column-align`
|
||||
- `-ms-grid-row-align`
|
||||
- `-ms-high-contrast-adjust`
|
||||
- `-ms-hyphenate-limit-chars`
|
||||
- `-ms-hyphenate-limit-lines`
|
||||
- `-ms-hyphenate-limit-zone`
|
||||
- `-ms-ime-align`
|
||||
- `-ms-interpolation-mode`
|
||||
- `-ms-overflow-style`
|
||||
- `-ms-scroll-chaining`
|
||||
- `-ms-scroll-limit`
|
||||
- `-ms-scroll-limit-x-max`
|
||||
- `-ms-scroll-limit-x-min`
|
||||
- `-ms-scroll-limit-y-max`
|
||||
- `-ms-scroll-limit-y-min`
|
||||
- `-ms-scroll-rails`
|
||||
- `-ms-scroll-snap-points-x`
|
||||
- `-ms-scroll-snap-points-y`
|
||||
- `-ms-scroll-snap-type`
|
||||
- `-ms-scroll-snap-x`
|
||||
- `-ms-scroll-snap-y`
|
||||
- `-ms-scroll-translation`
|
||||
- `-ms-scrollbar-3dlight-color`
|
||||
- `-ms-scrollbar-arrow-color`
|
||||
- `-ms-scrollbar-base-color`
|
||||
- `-ms-scrollbar-darkshadow-color`
|
||||
- `-ms-scrollbar-face-color`
|
||||
- `-ms-scrollbar-highlight-color`
|
||||
- `-ms-scrollbar-shadow-color`
|
||||
- `-ms-scrollbar-track-color`
|
||||
- `-ms-text-autospace`
|
||||
- `-ms-touch-select`
|
||||
- `-ms-user-select`
|
||||
- `-ms-wrap-flow`
|
||||
- `-ms-wrap-margin`
|
||||
- `-ms-wrap-through`
|
||||
- `-webkit-appearance`
|
||||
- `-webkit-background-clip`
|
||||
- `-webkit-border-before`
|
||||
- `-webkit-border-before-color`
|
||||
- `-webkit-border-before-style`
|
||||
- `-webkit-border-before-width`
|
||||
- `-webkit-box-reflect`
|
||||
- `-webkit-column-break-after`
|
||||
- `-webkit-column-break-before`
|
||||
- `-webkit-column-break-inside`
|
||||
- `-webkit-font-smoothing`
|
||||
- `-webkit-line-clamp`
|
||||
- `-webkit-mask`
|
||||
- `-webkit-mask-attachment`
|
||||
- `-webkit-mask-box-image`
|
||||
- `-webkit-mask-clip`
|
||||
- `-webkit-mask-composite`
|
||||
- `-webkit-mask-image`
|
||||
- `-webkit-mask-origin`
|
||||
- `-webkit-mask-position`
|
||||
- `-webkit-mask-position-x`
|
||||
- `-webkit-mask-position-y`
|
||||
- `-webkit-mask-repeat`
|
||||
- `-webkit-mask-repeat-x`
|
||||
- `-webkit-mask-repeat-y`
|
||||
- `-webkit-mask-size`
|
||||
- `-webkit-overflow-scrolling`
|
||||
- `-webkit-print-color-adjust`
|
||||
- `-webkit-tap-highlight-color`
|
||||
- `-webkit-text-fill-color`
|
||||
- `-webkit-text-security`
|
||||
- `-webkit-text-stroke`
|
||||
- `-webkit-text-stroke-color`
|
||||
- `-webkit-text-stroke-width`
|
||||
- `-webkit-touch-callout`
|
||||
- `-webkit-user-drag`
|
||||
- `-webkit-user-modify`
|
||||
- `-webkit-user-select`
|
||||
- `align-content`
|
||||
- `align-items`
|
||||
- `align-self`
|
||||
- `alignment-baseline`
|
||||
- `all`
|
||||
- `animation`
|
||||
- `animation-delay`
|
||||
- `animation-direction`
|
||||
- `animation-duration`
|
||||
- `animation-fill-mode`
|
||||
- `animation-iteration-count`
|
||||
- `animation-name`
|
||||
- `animation-play-state`
|
||||
- `animation-timing-function`
|
||||
- `appearance`
|
||||
- `azimuth`
|
||||
- `backdrop-filter`
|
||||
- `backface-visibility`
|
||||
- `background`
|
||||
- `background-attachment`
|
||||
- `background-blend-mode`
|
||||
- `background-clip`
|
||||
- `background-color`
|
||||
- `background-image`
|
||||
- `background-origin`
|
||||
- `background-position`
|
||||
- `background-position-x`
|
||||
- `background-position-y`
|
||||
- `background-repeat`
|
||||
- `background-size`
|
||||
- `baseline-shift`
|
||||
- `behavior`
|
||||
- `block-overflow`
|
||||
- `block-size`
|
||||
- `border`
|
||||
- `border-block-end`
|
||||
- `border-block-end-color`
|
||||
- `border-block-end-style`
|
||||
- `border-block-end-width`
|
||||
- `border-block-start`
|
||||
- `border-block-start-color`
|
||||
- `border-block-start-style`
|
||||
- `border-block-start-width`
|
||||
- `border-bottom`
|
||||
- `border-bottom-color`
|
||||
- `border-bottom-left-radius`
|
||||
- `border-bottom-right-radius`
|
||||
- `border-bottom-style`
|
||||
- `border-bottom-width`
|
||||
- `border-collapse`
|
||||
- `border-color`
|
||||
- `border-image`
|
||||
- `border-image-outset`
|
||||
- `border-image-repeat`
|
||||
- `border-image-slice`
|
||||
- `border-image-source`
|
||||
- `border-image-width`
|
||||
- `border-inline-end`
|
||||
- `border-inline-end-color`
|
||||
- `border-inline-end-style`
|
||||
- `border-inline-end-width`
|
||||
- `border-inline-start`
|
||||
- `border-inline-start-color`
|
||||
- `border-inline-start-style`
|
||||
- `border-inline-start-width`
|
||||
- `border-left`
|
||||
- `border-left-color`
|
||||
- `border-left-style`
|
||||
- `border-left-width`
|
||||
- `border-radius`
|
||||
- `border-right`
|
||||
- `border-right-color`
|
||||
- `border-right-style`
|
||||
- `border-right-width`
|
||||
- `border-spacing`
|
||||
- `border-style`
|
||||
- `border-top`
|
||||
- `border-top-color`
|
||||
- `border-top-left-radius`
|
||||
- `border-top-right-radius`
|
||||
- `border-top-style`
|
||||
- `border-top-width`
|
||||
- `border-width`
|
||||
- `bottom`
|
||||
- `box-align`
|
||||
- `box-decoration-break`
|
||||
- `box-direction`
|
||||
- `box-flex`
|
||||
- `box-flex-group`
|
||||
- `box-lines`
|
||||
- `box-ordinal-group`
|
||||
- `box-orient`
|
||||
- `box-pack`
|
||||
- `box-shadow`
|
||||
- `box-sizing`
|
||||
- `break-after`
|
||||
- `break-before`
|
||||
- `break-inside`
|
||||
- `caption-side`
|
||||
- `caret-color`
|
||||
- `clear`
|
||||
- `clip`
|
||||
- `clip-path`
|
||||
- `clip-rule`
|
||||
- `color`
|
||||
- `color-adjust`
|
||||
- `column-count`
|
||||
- `column-fill`
|
||||
- `column-gap`
|
||||
- `column-rule`
|
||||
- `column-rule-color`
|
||||
- `column-rule-style`
|
||||
- `column-rule-width`
|
||||
- `column-span`
|
||||
- `column-width`
|
||||
- `columns`
|
||||
- `contain`
|
||||
- `content`
|
||||
- `counter-increment`
|
||||
- `counter-reset`
|
||||
- `cue`
|
||||
- `cue-after`
|
||||
- `cue-before`
|
||||
- `cursor`
|
||||
- `direction`
|
||||
- `display`
|
||||
- `dominant-baseline`
|
||||
- `empty-cells`
|
||||
- `fill`
|
||||
- `fill-opacity`
|
||||
- `fill-rule`
|
||||
- `filter`
|
||||
- `flex`
|
||||
- `flex-basis`
|
||||
- `flex-direction`
|
||||
- `flex-flow`
|
||||
- `flex-grow`
|
||||
- `flex-shrink`
|
||||
- `flex-wrap`
|
||||
- `float`
|
||||
- `font`
|
||||
- `font-family`
|
||||
- `font-feature-settings`
|
||||
- `font-kerning`
|
||||
- `font-language-override`
|
||||
- `font-optical-sizing`
|
||||
- `font-size`
|
||||
- `font-size-adjust`
|
||||
- `font-stretch`
|
||||
- `font-style`
|
||||
- `font-synthesis`
|
||||
- `font-variant`
|
||||
- `font-variant-alternates`
|
||||
- `font-variant-caps`
|
||||
- `font-variant-east-asian`
|
||||
- `font-variant-ligatures`
|
||||
- `font-variant-numeric`
|
||||
- `font-variant-position`
|
||||
- `font-variation-settings`
|
||||
- `font-weight`
|
||||
- `gap`
|
||||
- `glyph-orientation-horizontal`
|
||||
- `glyph-orientation-vertical`
|
||||
- `grid`
|
||||
- `grid-area`
|
||||
- `grid-auto-columns`
|
||||
- `grid-auto-flow`
|
||||
- `grid-auto-rows`
|
||||
- `grid-column`
|
||||
- `grid-column-end`
|
||||
- `grid-column-gap`
|
||||
- `grid-column-start`
|
||||
- `grid-gap`
|
||||
- `grid-row`
|
||||
- `grid-row-end`
|
||||
- `grid-row-gap`
|
||||
- `grid-row-start`
|
||||
- `grid-template`
|
||||
- `grid-template-areas`
|
||||
- `grid-template-columns`
|
||||
- `grid-template-rows`
|
||||
- `hanging-punctuation`
|
||||
- `height`
|
||||
- `hyphens`
|
||||
- `image-orientation`
|
||||
- `image-rendering`
|
||||
- `image-resolution`
|
||||
- `ime-mode`
|
||||
- `initial-letter`
|
||||
- `initial-letter-align`
|
||||
- `inline-size`
|
||||
- `isolation`
|
||||
- `justify-content`
|
||||
- `justify-items`
|
||||
- `justify-self`
|
||||
- `kerning`
|
||||
- `left`
|
||||
- `letter-spacing`
|
||||
- `line-break`
|
||||
- `line-clamp`
|
||||
- `line-height`
|
||||
- `line-height-step`
|
||||
- `list-style`
|
||||
- `list-style-image`
|
||||
- `list-style-position`
|
||||
- `list-style-type`
|
||||
- `margin`
|
||||
- `margin-block-end`
|
||||
- `margin-block-start`
|
||||
- `margin-bottom`
|
||||
- `margin-inline-end`
|
||||
- `margin-inline-start`
|
||||
- `margin-left`
|
||||
- `margin-right`
|
||||
- `margin-top`
|
||||
- `marker`
|
||||
- `marker-end`
|
||||
- `marker-mid`
|
||||
- `marker-start`
|
||||
- `mask`
|
||||
- `mask-border`
|
||||
- `mask-border-mode`
|
||||
- `mask-border-outset`
|
||||
- `mask-border-repeat`
|
||||
- `mask-border-slice`
|
||||
- `mask-border-source`
|
||||
- `mask-border-width`
|
||||
- `mask-clip`
|
||||
- `mask-composite`
|
||||
- `mask-image`
|
||||
- `mask-mode`
|
||||
- `mask-origin`
|
||||
- `mask-position`
|
||||
- `mask-repeat`
|
||||
- `mask-size`
|
||||
- `mask-type`
|
||||
- `max-block-size`
|
||||
- `max-height`
|
||||
- `max-inline-size`
|
||||
- `max-lines`
|
||||
- `max-width`
|
||||
- `min-block-size`
|
||||
- `min-height`
|
||||
- `min-inline-size`
|
||||
- `min-width`
|
||||
- `mix-blend-mode`
|
||||
- `object-fit`
|
||||
- `object-position`
|
||||
- `offset`
|
||||
- `offset-anchor`
|
||||
- `offset-block-end`
|
||||
- `offset-block-start`
|
||||
- `offset-distance`
|
||||
- `offset-inline-end`
|
||||
- `offset-inline-start`
|
||||
- `offset-path`
|
||||
- `offset-position`
|
||||
- `offset-rotate`
|
||||
- `opacity`
|
||||
- `order`
|
||||
- `orphans`
|
||||
- `outline`
|
||||
- `outline-color`
|
||||
- `outline-offset`
|
||||
- `outline-style`
|
||||
- `outline-width`
|
||||
- `overflow`
|
||||
- `overflow-anchor`
|
||||
- `overflow-block`
|
||||
- `overflow-clip-box`
|
||||
- `overflow-inline`
|
||||
- `overflow-wrap`
|
||||
- `overflow-x`
|
||||
- `overflow-y`
|
||||
- `overscroll-behavior`
|
||||
- `overscroll-behavior-x`
|
||||
- `overscroll-behavior-y`
|
||||
- `padding`
|
||||
- `padding-block-end`
|
||||
- `padding-block-start`
|
||||
- `padding-bottom`
|
||||
- `padding-inline-end`
|
||||
- `padding-inline-start`
|
||||
- `padding-left`
|
||||
- `padding-right`
|
||||
- `padding-top`
|
||||
- `page-break-after`
|
||||
- `page-break-before`
|
||||
- `page-break-inside`
|
||||
- `paint-order`
|
||||
- `pause`
|
||||
- `pause-after`
|
||||
- `pause-before`
|
||||
- `perspective`
|
||||
- `perspective-origin`
|
||||
- `place-content`
|
||||
- `pointer-events`
|
||||
- `position`
|
||||
- `quotes`
|
||||
- `resize`
|
||||
- `rest`
|
||||
- `rest-after`
|
||||
- `rest-before`
|
||||
- `right`
|
||||
- `rotate`
|
||||
- `row-gap`
|
||||
- `ruby-align`
|
||||
- `ruby-merge`
|
||||
- `ruby-position`
|
||||
- `scale`
|
||||
- `scroll-behavior`
|
||||
- `scroll-snap-coordinate`
|
||||
- `scroll-snap-destination`
|
||||
- `scroll-snap-points-x`
|
||||
- `scroll-snap-points-y`
|
||||
- `scroll-snap-type`
|
||||
- `scroll-snap-type-x`
|
||||
- `scroll-snap-type-y`
|
||||
- `shape-image-threshold`
|
||||
- `shape-margin`
|
||||
- `shape-outside`
|
||||
- `shape-rendering`
|
||||
- `speak`
|
||||
- `speak-as`
|
||||
- `src`
|
||||
- `stroke`
|
||||
- `stroke-dasharray`
|
||||
- `stroke-dashoffset`
|
||||
- `stroke-linecap`
|
||||
- `stroke-linejoin`
|
||||
- `stroke-miterlimit`
|
||||
- `stroke-opacity`
|
||||
- `stroke-width`
|
||||
- `tab-size`
|
||||
- `table-layout`
|
||||
- `text-align`
|
||||
- `text-align-last`
|
||||
- `text-anchor`
|
||||
- `text-combine-upright`
|
||||
- `text-decoration`
|
||||
- `text-decoration-color`
|
||||
- `text-decoration-line`
|
||||
- `text-decoration-skip`
|
||||
- `text-decoration-skip-ink`
|
||||
- `text-decoration-style`
|
||||
- `text-emphasis`
|
||||
- `text-emphasis-color`
|
||||
- `text-emphasis-position`
|
||||
- `text-emphasis-style`
|
||||
- `text-indent`
|
||||
- `text-justify`
|
||||
- `text-orientation`
|
||||
- `text-overflow`
|
||||
- `text-rendering`
|
||||
- `text-shadow`
|
||||
- `text-size-adjust`
|
||||
- `text-transform`
|
||||
- `text-underline-position`
|
||||
- `top`
|
||||
- `touch-action`
|
||||
- `transform`
|
||||
- `transform-box`
|
||||
- `transform-origin`
|
||||
- `transform-style`
|
||||
- `transition`
|
||||
- `transition-delay`
|
||||
- `transition-duration`
|
||||
- `transition-property`
|
||||
- `transition-timing-function`
|
||||
- `translate`
|
||||
- `unicode-bidi`
|
||||
- `unicode-range`
|
||||
- `user-select`
|
||||
- `vertical-align`
|
||||
- `visibility`
|
||||
- `voice-balance`
|
||||
- `voice-duration`
|
||||
- `voice-family`
|
||||
- `voice-pitch`
|
||||
- `voice-range`
|
||||
- `voice-rate`
|
||||
- `voice-stress`
|
||||
- `voice-volume`
|
||||
- `white-space`
|
||||
- `widows`
|
||||
- `width`
|
||||
- `will-change`
|
||||
- `word-break`
|
||||
- `word-spacing`
|
||||
- `word-wrap`
|
||||
- `writing-mode`
|
||||
- `z-index`
|
||||
- `zoom`
|
||||
|
||||
<!-- /gen:properties -->
|
||||
3
node_modules/csso/node_modules/css-tree/docs/syntax.md
generated
vendored
Normal file
3
node_modules/csso/node_modules/css-tree/docs/syntax.md
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Working with syntax
|
||||
|
||||
> To be done...
|
||||
249
node_modules/csso/node_modules/css-tree/docs/traversal.md
generated
vendored
Normal file
249
node_modules/csso/node_modules/css-tree/docs/traversal.md
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
# AST traversal
|
||||
|
||||
AST traversal API is provided by `walk()` method.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = csstree.parse('.a { color: red; }');
|
||||
|
||||
csstree.walk(ast, function(node) {
|
||||
console.log(node.type);
|
||||
});
|
||||
// StyleSheet
|
||||
// Rule
|
||||
// SelectorList
|
||||
// Selector
|
||||
// ClassSelector
|
||||
// Block
|
||||
// Declaration
|
||||
// Value
|
||||
// Identifier
|
||||
```
|
||||
|
||||
The facts you should know about `walk()` internals:
|
||||
|
||||
- Method uses `structure` field value of every node type to define the way how to iterate the nodes:
|
||||
- A function-iterator is generating for every node type.
|
||||
- Node's properties iterates in the order it defined in `structure` ([reverse](#reverse) option can invert an order).
|
||||
- Properties that are not defined in `structure` are ignoring (doesn't interate).
|
||||
- An exception is possible when a tree is not following to expected structure (it may happen if AST was built outside the CSSTree parser or transformed in a wrong way). In case you are not sure about correctness of a tree structure, you can use `try/catch` or check the tree with `csstree.lexer.validateStructure(ast)` before iterate it.
|
||||
- Only `children` fields can contain a list of nodes. A list of nodes should be represented as a `List` instances. But for certain cases, `children` can be an array. Since `List` provides a similar to `Array` API, traversal can work in most cases, but without any guarantee. Therefore usings arrays in AST is not recomended, use them on your own risk.
|
||||
|
||||
## walk(ast, options)
|
||||
|
||||
Method visits each node of passed tree in a natural way and calls a handler for each one. It takes two arguments: a root node (`ast`) and an object (`options`). In simple case, it can take a function (handler) instead of `options` (`walk(ast, fn)` is equivalent to `walk(ast, { enter: fn })`).
|
||||
|
||||
Options:
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [enter](#enter)
|
||||
- [leave](#leave)
|
||||
- [visit](#visit)
|
||||
- [reverse](#reverse)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
### enter
|
||||
|
||||
Type: `function` or `undefined`
|
||||
Default: `undefined`
|
||||
|
||||
Handler on node entrance, i.e. before any nested node is processed.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = csstree.parse('.a { color: red; }');
|
||||
|
||||
csstree.walk(ast, {
|
||||
enter: function(node) {
|
||||
console.log(node.type);
|
||||
}
|
||||
});
|
||||
// StyleSheet
|
||||
// Rule
|
||||
// SelectorList
|
||||
// Selector
|
||||
// ClassSelector
|
||||
// Block
|
||||
// Declaration
|
||||
// Value
|
||||
// Identifier
|
||||
```
|
||||
|
||||
In case `options` has a single `enter` field, it can replaced for the handler passed as a value for `enter`, i.e. `walk(ast, { enter: fn })` → `walk(ast, fn)`.
|
||||
|
||||
Handler receives a three arguments:
|
||||
- `node` – the AST node a walker entering to
|
||||
- `item` – node wrapper, that contains references to `prev` and `next` nodes in a list, and `data` reference for the node
|
||||
- `list` – is a reference for the list; it's useful for list operations like `remove()` or `insert()`
|
||||
|
||||
> NOTE: If `children` is an array, the last two arguments are `index` and `array`, like for `Array#forEach()` or `Array#map()` methods.
|
||||
|
||||
```js
|
||||
const csstree = require('css-tree');
|
||||
const ast = csstree.parse(`
|
||||
.a { foo: 1; bar: 2; }
|
||||
.b { bar: 3; baz: 4; }
|
||||
`);
|
||||
|
||||
// remove declarations with `bar` property from the tree
|
||||
csstree.walk(ast, function(node, item, list) {
|
||||
if (node.type === 'Declaration' && node.property === 'bar' && list) {
|
||||
// remove a declaration from a list it
|
||||
list.remove(item);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(csstree.generate(ast));
|
||||
// .a{foo:1}.b{baz:4}
|
||||
```
|
||||
|
||||
> NOTE:
|
||||
> - `item` and `list` are not defined for nodes that are not in a list. Even `Declaration` can be outside of any list in case it is a root of tree or a part of `@supports` prelude, e.g. `@supports (bar: 123) { ... }`. Therefore, it's recomended to check `item` or `list` are defined before using of it (those values both are defined or both are undefined, so it's enough to test one of them)
|
||||
> - Only `List` instances are safe for tree transformations such as node removal. In case you perform such operations, you can ensure that all `children` in a tree is a `List` instances by calling `csstree.fromPlainObject(ast)` before traversal.
|
||||
> - It's better to use `visit` option when possible to reach better performance
|
||||
|
||||
Context (`this`) for a handler is an object with a references to the closest ancestor nodes:
|
||||
|
||||
- `root` – refers to AST root node (actually it's a node passed to `walk()` method)
|
||||
- `stylesheet` – refers to `StyleSheet` node, usually it's a root node
|
||||
- `atrule` – refers to closest `Atrule` node if any
|
||||
- `atrulePrelude` – refers to `AtrulePrelude` node if any
|
||||
- `rule` – refers to closest `Rule` node if any
|
||||
- `selector` – refers to `SelectorList` node if any
|
||||
- `block` - refers to closest `Block` node if any
|
||||
- `declaration` – refers to `Declaration` node if any
|
||||
- `function` – refers to closest `Function`, `PseudoClassSelector` or `PseudoElementSelector` node if current node inside one of them
|
||||
|
||||
```js
|
||||
const csstree = require('css-tree');
|
||||
const ast = csstree.parse(`
|
||||
@import url(import.css);
|
||||
.foo { background: url('foo.jpg'); }
|
||||
.bar { background-image: url(bar.png); }
|
||||
`);
|
||||
|
||||
// collect all urls in declarations
|
||||
const urls = [];
|
||||
csstree.walk(ast, function(node) {
|
||||
if (this.declaration !== null && node.type === 'Url') {
|
||||
const value = node.value;
|
||||
|
||||
if (value.type === 'Raw') {
|
||||
urls.push(value.value);
|
||||
} else {
|
||||
urls.push(value.value.substr(1, value.value.length - 2));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(urls);
|
||||
// [ 'foo.jpg', 'bar.png' ]
|
||||
```
|
||||
|
||||
### leave
|
||||
|
||||
Type: `function` or `undefined`
|
||||
Default: `undefined`
|
||||
|
||||
The same as `enter` handler but invokes on node exit, i.e. after all nested nodes are processed.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = csstree.parse('.a { color: red; }');
|
||||
|
||||
csstree.walk(ast, {
|
||||
leave: function(node) {
|
||||
console.log(node.type);
|
||||
}
|
||||
});
|
||||
// ClassSelector
|
||||
// Selector
|
||||
// SelectorList
|
||||
// Identifier
|
||||
// Value
|
||||
// Declaration
|
||||
// Block
|
||||
// Rule
|
||||
// StyleSheet
|
||||
```
|
||||
|
||||
### visit
|
||||
|
||||
Type: `string` or `null`
|
||||
Default: `null`
|
||||
|
||||
Invokes a handler for a specified node type only.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = csstree.parse('.a { color: red; } .b { color: green; }');
|
||||
|
||||
csstree.walk(ast, {
|
||||
visit: 'ClassSelector',
|
||||
enter: function(node) {
|
||||
console.log(node.name);
|
||||
}
|
||||
});
|
||||
|
||||
// example above is equal to
|
||||
csstree.walk(ast, {
|
||||
enter: function(node) {
|
||||
if (node.type === 'ClassSelector') {
|
||||
console.log(node.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The traveral for some node types can performs faster (10-15 times depending on the CSS structure), because some subtrees may to be skipped since they can't contain a node of specified type (e.g. `Rule` can't be used inside of `Declaration`, so declaration's subtree can be exclude from traversal path). Fast traversal is supported for node types:
|
||||
|
||||
- `Atrule`
|
||||
- `Rule`
|
||||
- `Declaration`
|
||||
|
||||
> NOTE: When fast traversal is applied, some nodes may not be reached in case of an incorrect location in the tree. That's may happen if AST was built outside the CSSTree parser or transformed in a wrong way. If you need to be 100% sure that every node of type will be visited (even in wrong position), don't use `visit` option and test node type by your own.
|
||||
|
||||
### reverse
|
||||
|
||||
Type: `boolean`
|
||||
Default: `false`
|
||||
|
||||
Inverts a natural order of traversal of nodes. To achieve this, the following actions are performed:
|
||||
- children nodes are iterated in reverse order (from last to first)
|
||||
- properties are iterated in reverse order (according to `structure` definition of node)
|
||||
- `enter` and `leave` handlers are swapped
|
||||
|
||||
```js
|
||||
var assert = require('assert');
|
||||
var csstree = require('css-tree');
|
||||
var ast = csstree.parse('.a { color: red; }');
|
||||
|
||||
var natural = [];
|
||||
csstree.walk(ast, {
|
||||
enter: function(node) {
|
||||
natural.push('enter ' + node.type);
|
||||
},
|
||||
leave: function(node) {
|
||||
natural.push('leave ' + node.type);
|
||||
}
|
||||
});
|
||||
|
||||
var reverse = [];
|
||||
csstree.walk(ast, {
|
||||
reverse: true,
|
||||
enter: function(node) {
|
||||
reverse.push('enter ' + node.type);
|
||||
},
|
||||
leave: function(node) {
|
||||
reverse.push('leave ' + node.type);
|
||||
}
|
||||
});
|
||||
|
||||
// will be truthy
|
||||
assert.deepEqual(
|
||||
reverse,
|
||||
natural.reverse()
|
||||
);
|
||||
```
|
||||
151
node_modules/csso/node_modules/css-tree/docs/utils.md
generated
vendored
Normal file
151
node_modules/csso/node_modules/css-tree/docs/utils.md
generated
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
# Utils to work with AST
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [property\(name\)](#propertyname)
|
||||
- [keyword\(name\)](#keywordname)
|
||||
- [clone\(ast\)](#cloneast)
|
||||
- [fromPlainObject\(object\)](#fromplainobjectobject)
|
||||
- [toPlainObject\(ast\)](#toplainobjectast)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## property(name)
|
||||
|
||||
Returns details for a property name, such as vendor prefix, used hack etc. Using for safe test of declaration property names, i.e. `Declaration.property`.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
|
||||
csstree.property('*-vendor-property');
|
||||
// {
|
||||
// basename: 'property',
|
||||
// name: '-vendor-property',
|
||||
// hack: '*',
|
||||
// vendor: '-vendor-',
|
||||
// prefix: '*-vendor-',
|
||||
// custom: false
|
||||
// }
|
||||
|
||||
csstree.property('--test-var');
|
||||
// {
|
||||
// basename: '--test-var',
|
||||
// name: '--test-var',
|
||||
// hack: '',
|
||||
// vendor: '',
|
||||
// prefix: '',
|
||||
// custom: true
|
||||
// };
|
||||
```
|
||||
|
||||
`property()` function normalizes a name to lower case, except custom property names since they are case sensitive. It returns the same immutable (freezed) object for the same input (input after normalization).
|
||||
|
||||
```js
|
||||
csstree.property('name') === csstree.property('NAME') // true
|
||||
csstree.property('NAME').name === 'name' // true
|
||||
csstree.property('--custom') === csstree.property('--Custom') // false
|
||||
|
||||
var info = csstree.property('NAME');
|
||||
info.name === 'name'; //
|
||||
info.name = 'foo'; // have no effect
|
||||
info.name === 'name'; // true
|
||||
```
|
||||
|
||||
Supported hacks:
|
||||
|
||||
- `_` in the beginning
|
||||
- `+` in the beginning
|
||||
- `#` in the beginning
|
||||
- `*` in the beginning
|
||||
- `$` in the beginning
|
||||
- `/` in the beginning
|
||||
- `//` in the beginning
|
||||
|
||||
## keyword(name)
|
||||
|
||||
Mostly the same as `property()` function, but without hack detection. Using for any identifier except declaration property name.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
|
||||
csstree.keyword('-vendor-keyword');
|
||||
// {
|
||||
// basename: 'keyword',
|
||||
// name: '-vendor-keyword',
|
||||
// vendor: '-vendor-',
|
||||
// prefix: '-vendor-',
|
||||
// custom: false
|
||||
// };
|
||||
```
|
||||
|
||||
## clone(ast)
|
||||
|
||||
Make AST deep copy.
|
||||
|
||||
```js
|
||||
var orig = csstree.parse('.test { color: red }');
|
||||
var copy = csstree.clone(orig);
|
||||
|
||||
csstree.walk(copy, function(node) {
|
||||
if (node.type === 'Class') {
|
||||
node.name = 'replaced';
|
||||
}
|
||||
});
|
||||
|
||||
console.log(csstree.generate(orig));
|
||||
// .test{color:red}
|
||||
console.log(csstree.generate(copy));
|
||||
// .replaced{color:red}
|
||||
```
|
||||
|
||||
## fromPlainObject(object)
|
||||
|
||||
`fromPlainObject()` walks through AST and coverts each `children` value into a `List` instance when value is an array.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = {
|
||||
type: 'SelectorList',
|
||||
children: []
|
||||
};
|
||||
|
||||
console.log(Array.isArray(ast.children)); // true
|
||||
console.log(ast.children instanceof csstree.List); // false
|
||||
|
||||
ast = csstree.fromPlainObject(ast);
|
||||
|
||||
console.log(Array.isArray(ast.children)); // false
|
||||
console.log(ast.children instanceof csstree.List); // true
|
||||
```
|
||||
|
||||
Function mutates the passed AST. Use `clone()` function before passing AST to `fromPlainObject()` in case you want to avoid original tree mutation.
|
||||
|
||||
```js
|
||||
astClone = csstree.fromPlainObject(csstree.clone(ast));
|
||||
```
|
||||
|
||||
## toPlainObject(ast)
|
||||
|
||||
`fromPlainObject()` walks through AST and coverts each `children` value to regular array when value is a `List` instance.
|
||||
|
||||
```js
|
||||
var csstree = require('css-tree');
|
||||
var ast = {
|
||||
type: 'SelectorList',
|
||||
children: new List()
|
||||
};
|
||||
|
||||
console.log(Array.isArray(ast.children)); // false
|
||||
console.log(ast.children instanceof csstree.List); // true
|
||||
|
||||
ast = csstree.toPlainObject(ast);
|
||||
|
||||
console.log(Array.isArray(ast.children)); // true
|
||||
console.log(ast.children instanceof csstree.List); // false
|
||||
```
|
||||
|
||||
Function mutates the passed AST. Use `clone()` function before passing AST to `toPlainObject()` in case you want to avoid original tree mutation.
|
||||
|
||||
```js
|
||||
ast = csstree.toPlainObject(csstree.clone(ast));
|
||||
```
|
||||
28
node_modules/csso/node_modules/css-tree/lib/convertor/create.js
generated
vendored
Normal file
28
node_modules/csso/node_modules/css-tree/lib/convertor/create.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
var List = require('../utils/list');
|
||||
|
||||
module.exports = function createConvertors(walk) {
|
||||
return {
|
||||
fromPlainObject: function(ast) {
|
||||
walk(ast, {
|
||||
enter: function(node) {
|
||||
if (node.children && node.children instanceof List === false) {
|
||||
node.children = new List().fromArray(node.children);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ast;
|
||||
},
|
||||
toPlainObject: function(ast) {
|
||||
walk(ast, {
|
||||
leave: function(node) {
|
||||
if (node.children && node.children instanceof List) {
|
||||
node.children = node.children.toArray();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ast;
|
||||
}
|
||||
};
|
||||
};
|
||||
3
node_modules/csso/node_modules/css-tree/lib/convertor/index.js
generated
vendored
Normal file
3
node_modules/csso/node_modules/css-tree/lib/convertor/index.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
var createConvertor = require('./create');
|
||||
|
||||
module.exports = createConvertor(require('../walker'));
|
||||
68
node_modules/csso/node_modules/css-tree/lib/generator/create.js
generated
vendored
Normal file
68
node_modules/csso/node_modules/css-tree/lib/generator/create.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
|
||||
var sourceMap = require('./sourceMap');
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
function processChildren(node, delimeter) {
|
||||
var list = node.children;
|
||||
var prev = null;
|
||||
|
||||
if (typeof delimeter !== 'function') {
|
||||
list.forEach(this.node, this);
|
||||
} else {
|
||||
list.forEach(function(node) {
|
||||
if (prev !== null) {
|
||||
delimeter.call(this, prev);
|
||||
}
|
||||
|
||||
this.node(node);
|
||||
prev = node;
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function createGenerator(config) {
|
||||
function processNode(node) {
|
||||
if (hasOwnProperty.call(types, node.type)) {
|
||||
types[node.type].call(this, node);
|
||||
} else {
|
||||
throw new Error('Unknown node type: ' + node.type);
|
||||
}
|
||||
}
|
||||
|
||||
var types = {};
|
||||
|
||||
if (config.node) {
|
||||
for (var name in config.node) {
|
||||
types[name] = config.node[name].generate;
|
||||
}
|
||||
}
|
||||
|
||||
return function(node, options) {
|
||||
var buffer = '';
|
||||
var handlers = {
|
||||
children: processChildren,
|
||||
node: processNode,
|
||||
chunk: function(chunk) {
|
||||
buffer += chunk;
|
||||
},
|
||||
result: function() {
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
if (options) {
|
||||
if (typeof options.decorator === 'function') {
|
||||
handlers = options.decorator(handlers);
|
||||
}
|
||||
|
||||
if (options.sourceMap) {
|
||||
handlers = sourceMap(handlers);
|
||||
}
|
||||
}
|
||||
|
||||
handlers.node(node);
|
||||
|
||||
return handlers.result();
|
||||
};
|
||||
};
|
||||
4
node_modules/csso/node_modules/css-tree/lib/generator/index.js
generated
vendored
Normal file
4
node_modules/csso/node_modules/css-tree/lib/generator/index.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
var createGenerator = require('./create');
|
||||
var config = require('../syntax/config/parser');
|
||||
|
||||
module.exports = createGenerator(config);
|
||||
97
node_modules/csso/node_modules/css-tree/lib/generator/sourceMap.js
generated
vendored
Normal file
97
node_modules/csso/node_modules/css-tree/lib/generator/sourceMap.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
|
||||
var SourceMapGenerator = require('source-map').SourceMapGenerator;
|
||||
var trackNodes = {
|
||||
Atrule: true,
|
||||
Selector: true,
|
||||
Declaration: true
|
||||
};
|
||||
|
||||
module.exports = function generateSourceMap(handlers) {
|
||||
var map = new SourceMapGenerator();
|
||||
var line = 1;
|
||||
var column = 0;
|
||||
var generated = {
|
||||
line: 1,
|
||||
column: 0
|
||||
};
|
||||
var original = {
|
||||
line: 0, // should be zero to add first mapping
|
||||
column: 0
|
||||
};
|
||||
var sourceMappingActive = false;
|
||||
var activatedGenerated = {
|
||||
line: 1,
|
||||
column: 0
|
||||
};
|
||||
var activatedMapping = {
|
||||
generated: activatedGenerated
|
||||
};
|
||||
|
||||
var handlersNode = handlers.node;
|
||||
handlers.node = function(node) {
|
||||
if (node.loc && node.loc.start && trackNodes.hasOwnProperty(node.type)) {
|
||||
var nodeLine = node.loc.start.line;
|
||||
var nodeColumn = node.loc.start.column - 1;
|
||||
|
||||
if (original.line !== nodeLine ||
|
||||
original.column !== nodeColumn) {
|
||||
original.line = nodeLine;
|
||||
original.column = nodeColumn;
|
||||
|
||||
generated.line = line;
|
||||
generated.column = column;
|
||||
|
||||
if (sourceMappingActive) {
|
||||
sourceMappingActive = false;
|
||||
if (generated.line !== activatedGenerated.line ||
|
||||
generated.column !== activatedGenerated.column) {
|
||||
map.addMapping(activatedMapping);
|
||||
}
|
||||
}
|
||||
|
||||
sourceMappingActive = true;
|
||||
map.addMapping({
|
||||
source: node.loc.source,
|
||||
original: original,
|
||||
generated: generated
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handlersNode.call(this, node);
|
||||
|
||||
if (sourceMappingActive && trackNodes.hasOwnProperty(node.type)) {
|
||||
activatedGenerated.line = line;
|
||||
activatedGenerated.column = column;
|
||||
}
|
||||
};
|
||||
|
||||
var handlersChunk = handlers.chunk;
|
||||
handlers.chunk = function(chunk) {
|
||||
for (var i = 0; i < chunk.length; i++) {
|
||||
if (chunk.charCodeAt(i) === 10) { // \n
|
||||
line++;
|
||||
column = 0;
|
||||
} else {
|
||||
column++;
|
||||
}
|
||||
}
|
||||
|
||||
handlersChunk(chunk);
|
||||
};
|
||||
|
||||
var handlersResult = handlers.result;
|
||||
handlers.result = function() {
|
||||
if (sourceMappingActive) {
|
||||
map.addMapping(activatedMapping);
|
||||
}
|
||||
|
||||
return {
|
||||
css: handlersResult(),
|
||||
map: map
|
||||
};
|
||||
};
|
||||
|
||||
return handlers;
|
||||
};
|
||||
3
node_modules/csso/node_modules/css-tree/lib/index.js
generated
vendored
Normal file
3
node_modules/csso/node_modules/css-tree/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('./syntax');
|
||||
327
node_modules/csso/node_modules/css-tree/lib/lexer/Lexer.js
generated
vendored
Normal file
327
node_modules/csso/node_modules/css-tree/lib/lexer/Lexer.js
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
'use strict';
|
||||
|
||||
var SyntaxReferenceError = require('./error').SyntaxReferenceError;
|
||||
var MatchError = require('./error').MatchError;
|
||||
var names = require('../utils/names');
|
||||
var generic = require('./generic');
|
||||
var parse = require('./grammar/parse');
|
||||
var generate = require('./grammar/generate');
|
||||
var walk = require('./grammar/walk');
|
||||
var astToTokens = require('./ast-to-tokens');
|
||||
var buildMatchGraph = require('./match-graph').buildMatchGraph;
|
||||
var matchAsTree = require('./match').matchAsTree;
|
||||
var trace = require('./trace');
|
||||
var search = require('./search');
|
||||
var getStructureFromConfig = require('./structure').getStructureFromConfig;
|
||||
var cssWideKeywords = buildMatchGraph(parse('inherit | initial | unset'));
|
||||
var cssWideKeywordsWithExpression = buildMatchGraph(parse('inherit | initial | unset | <expression>'));
|
||||
|
||||
function dumpMapSyntax(map, syntaxAsAst) {
|
||||
var result = {};
|
||||
|
||||
for (var name in map) {
|
||||
if (map[name].syntax) {
|
||||
result[name] = syntaxAsAst ? map[name].syntax : generate(map[name].syntax);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function valueHasVar(value) {
|
||||
var hasVar = false;
|
||||
|
||||
this.syntax.walk(value, function(node) {
|
||||
if (node.type === 'Function' && node.name.toLowerCase() === 'var') {
|
||||
hasVar = true;
|
||||
}
|
||||
});
|
||||
|
||||
return hasVar;
|
||||
}
|
||||
|
||||
function buildMatchResult(match, error, iterations) {
|
||||
return {
|
||||
matched: match,
|
||||
iterations: iterations,
|
||||
error: error,
|
||||
getTrace: trace.getTrace,
|
||||
isType: trace.isType,
|
||||
isProperty: trace.isProperty,
|
||||
isKeyword: trace.isKeyword
|
||||
};
|
||||
}
|
||||
|
||||
function matchSyntax(lexer, syntax, node, useCommon) {
|
||||
if (!node) {
|
||||
return buildMatchResult(null, new Error('Node is undefined'));
|
||||
}
|
||||
|
||||
if (valueHasVar.call(lexer, node)) {
|
||||
return buildMatchResult(null, new Error('Matching for a tree with var() is not supported'));
|
||||
}
|
||||
|
||||
var tokens = lexer.syntax.generate(node, astToTokens);
|
||||
var result;
|
||||
|
||||
if (useCommon) {
|
||||
result = matchAsTree(tokens, lexer.valueCommonSyntax, lexer);
|
||||
}
|
||||
|
||||
if (!useCommon || !result.match) {
|
||||
result = matchAsTree(tokens, syntax.match, lexer);
|
||||
if (!result.match) {
|
||||
return buildMatchResult(
|
||||
null,
|
||||
new MatchError(result.reason, lexer, syntax.syntax, node, result),
|
||||
result.iterations
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return buildMatchResult(result.match, null, result.iterations);
|
||||
}
|
||||
|
||||
var Lexer = function(config, syntax, structure) {
|
||||
this.valueCommonSyntax = cssWideKeywords;
|
||||
this.syntax = syntax;
|
||||
this.generic = false;
|
||||
this.properties = {};
|
||||
this.types = {};
|
||||
this.structure = structure || getStructureFromConfig(config);
|
||||
|
||||
if (config) {
|
||||
if (config.generic) {
|
||||
this.generic = true;
|
||||
for (var name in generic) {
|
||||
this.addType_(name, generic[name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.types) {
|
||||
for (var name in config.types) {
|
||||
this.addType_(name, config.types[name]);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.properties) {
|
||||
for (var name in config.properties) {
|
||||
this.addProperty_(name, config.properties[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Lexer.prototype = {
|
||||
structure: {},
|
||||
checkStructure: function(ast) {
|
||||
function collectWarning(node, message) {
|
||||
warns.push({
|
||||
node: node,
|
||||
message: message
|
||||
});
|
||||
}
|
||||
|
||||
var structure = this.structure;
|
||||
var warns = [];
|
||||
|
||||
this.syntax.walk(ast, function(node) {
|
||||
if (structure.hasOwnProperty(node.type)) {
|
||||
structure[node.type].check(node, collectWarning);
|
||||
} else {
|
||||
collectWarning(node, 'Unknown node type `' + node.type + '`');
|
||||
}
|
||||
});
|
||||
|
||||
return warns.length ? warns : false;
|
||||
},
|
||||
|
||||
createDescriptor: function(syntax, type, name) {
|
||||
var ref = {
|
||||
type: type,
|
||||
name: name
|
||||
};
|
||||
var descriptor = {
|
||||
type: type,
|
||||
name: name,
|
||||
syntax: null,
|
||||
match: null
|
||||
};
|
||||
|
||||
if (typeof syntax === 'function') {
|
||||
descriptor.match = buildMatchGraph(syntax, ref);
|
||||
} else {
|
||||
if (typeof syntax === 'string') {
|
||||
// lazy parsing on first access
|
||||
Object.defineProperty(descriptor, 'syntax', {
|
||||
get: function() {
|
||||
Object.defineProperty(descriptor, 'syntax', {
|
||||
value: parse(syntax)
|
||||
});
|
||||
|
||||
return descriptor.syntax;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
descriptor.syntax = syntax;
|
||||
}
|
||||
|
||||
Object.defineProperty(descriptor, 'match', {
|
||||
get: function() {
|
||||
Object.defineProperty(descriptor, 'match', {
|
||||
value: buildMatchGraph(descriptor.syntax, ref)
|
||||
});
|
||||
|
||||
return descriptor.match;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
},
|
||||
addProperty_: function(name, syntax) {
|
||||
this.properties[name] = this.createDescriptor(syntax, 'Property', name);
|
||||
},
|
||||
addType_: function(name, syntax) {
|
||||
this.types[name] = this.createDescriptor(syntax, 'Type', name);
|
||||
|
||||
if (syntax === generic.expression) {
|
||||
this.valueCommonSyntax = cssWideKeywordsWithExpression;
|
||||
}
|
||||
},
|
||||
|
||||
matchDeclaration: function(node) {
|
||||
if (node.type !== 'Declaration') {
|
||||
return buildMatchResult(null, new Error('Not a Declaration node'));
|
||||
}
|
||||
|
||||
return this.matchProperty(node.property, node.value);
|
||||
},
|
||||
matchProperty: function(propertyName, value) {
|
||||
var property = names.property(propertyName);
|
||||
|
||||
// don't match syntax for a custom property
|
||||
if (property.custom) {
|
||||
return buildMatchResult(null, new Error('Lexer matching doesn\'t applicable for custom properties'));
|
||||
}
|
||||
|
||||
var propertySyntax = property.vendor
|
||||
? this.getProperty(property.name) || this.getProperty(property.basename)
|
||||
: this.getProperty(property.name);
|
||||
|
||||
if (!propertySyntax) {
|
||||
return buildMatchResult(null, new SyntaxReferenceError('Unknown property', propertyName));
|
||||
}
|
||||
|
||||
return matchSyntax(this, propertySyntax, value, true);
|
||||
},
|
||||
matchType: function(typeName, value) {
|
||||
var typeSyntax = this.getType(typeName);
|
||||
|
||||
if (!typeSyntax) {
|
||||
return buildMatchResult(null, new SyntaxReferenceError('Unknown type', typeName));
|
||||
}
|
||||
|
||||
return matchSyntax(this, typeSyntax, value, false);
|
||||
},
|
||||
match: function(syntax, value) {
|
||||
if (!syntax || !syntax.type) {
|
||||
return buildMatchResult(null, new SyntaxReferenceError('Bad syntax'));
|
||||
}
|
||||
|
||||
if (!syntax.match) {
|
||||
syntax = this.createDescriptor(syntax);
|
||||
}
|
||||
|
||||
return matchSyntax(this, syntax, value, false);
|
||||
},
|
||||
|
||||
findValueFragments: function(propertyName, value, type, name) {
|
||||
return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
|
||||
},
|
||||
findDeclarationValueFragments: function(declaration, type, name) {
|
||||
return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
|
||||
},
|
||||
findAllFragments: function(ast, type, name) {
|
||||
var result = [];
|
||||
|
||||
this.syntax.walk(ast, {
|
||||
visit: 'Declaration',
|
||||
enter: function(declaration) {
|
||||
result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
getProperty: function(name) {
|
||||
return this.properties.hasOwnProperty(name) ? this.properties[name] : null;
|
||||
},
|
||||
getType: function(name) {
|
||||
return this.types.hasOwnProperty(name) ? this.types[name] : null;
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
function validate(syntax, name, broken, descriptor) {
|
||||
if (broken.hasOwnProperty(name)) {
|
||||
return broken[name];
|
||||
}
|
||||
|
||||
broken[name] = false;
|
||||
if (descriptor.syntax !== null) {
|
||||
walk(descriptor.syntax, function(node) {
|
||||
if (node.type !== 'Type' && node.type !== 'Property') {
|
||||
return;
|
||||
}
|
||||
|
||||
var map = node.type === 'Type' ? syntax.types : syntax.properties;
|
||||
var brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
|
||||
|
||||
if (!map.hasOwnProperty(node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
|
||||
broken[name] = true;
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
var brokenTypes = {};
|
||||
var brokenProperties = {};
|
||||
|
||||
for (var key in this.types) {
|
||||
validate(this, key, brokenTypes, this.types[key]);
|
||||
}
|
||||
|
||||
for (var key in this.properties) {
|
||||
validate(this, key, brokenProperties, this.properties[key]);
|
||||
}
|
||||
|
||||
brokenTypes = Object.keys(brokenTypes).filter(function(name) {
|
||||
return brokenTypes[name];
|
||||
});
|
||||
brokenProperties = Object.keys(brokenProperties).filter(function(name) {
|
||||
return brokenProperties[name];
|
||||
});
|
||||
|
||||
if (brokenTypes.length || brokenProperties.length) {
|
||||
return {
|
||||
types: brokenTypes,
|
||||
properties: brokenProperties
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
dump: function(syntaxAsAst) {
|
||||
return {
|
||||
generic: this.generic,
|
||||
types: dumpMapSyntax(this.types, syntaxAsAst),
|
||||
properties: dumpMapSyntax(this.properties, syntaxAsAst)
|
||||
};
|
||||
},
|
||||
toString: function() {
|
||||
return JSON.stringify(this.dump());
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Lexer;
|
||||
57
node_modules/csso/node_modules/css-tree/lib/lexer/ast-to-tokens.js
generated
vendored
Normal file
57
node_modules/csso/node_modules/css-tree/lib/lexer/ast-to-tokens.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
module.exports = {
|
||||
decorator: function(handlers) {
|
||||
var curNode = null;
|
||||
var prev = null;
|
||||
var tokens = [];
|
||||
|
||||
return {
|
||||
children: handlers.children,
|
||||
node: function(node) {
|
||||
var tmp = curNode;
|
||||
curNode = node;
|
||||
handlers.node.call(this, node);
|
||||
curNode = tmp;
|
||||
},
|
||||
chunk: function(chunk) {
|
||||
if (tokens.length > 0) {
|
||||
switch (curNode.type) {
|
||||
case 'Dimension':
|
||||
case 'HexColor':
|
||||
case 'IdSelector':
|
||||
case 'Percentage':
|
||||
if (prev.node === curNode) {
|
||||
prev.value += chunk;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Function':
|
||||
case 'PseudoClassSelector':
|
||||
case 'PseudoElementSelector':
|
||||
case 'Url':
|
||||
if (chunk === '(') {
|
||||
prev.value += chunk;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Atrule':
|
||||
if (prev.node === curNode && prev.value === '@') {
|
||||
prev.value += chunk;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tokens.push(prev = {
|
||||
value: chunk,
|
||||
node: curNode
|
||||
});
|
||||
},
|
||||
result: function() {
|
||||
return tokens;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
99
node_modules/csso/node_modules/css-tree/lib/lexer/error.js
generated
vendored
Normal file
99
node_modules/csso/node_modules/css-tree/lib/lexer/error.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
'use strict';
|
||||
|
||||
var createCustomError = require('../utils/createCustomError');
|
||||
var generateGrammar = require('./grammar/generate');
|
||||
|
||||
function fromMatchResult(matchResult) {
|
||||
var tokens = matchResult.tokens;
|
||||
var longestMatch = matchResult.longestMatch;
|
||||
var node = longestMatch < tokens.length ? tokens[longestMatch].node : null;
|
||||
var mismatchOffset = 0;
|
||||
var entries = 0;
|
||||
var css = '';
|
||||
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
if (i === longestMatch) {
|
||||
mismatchOffset = css.length;
|
||||
}
|
||||
|
||||
if (node !== null && tokens[i].node === node) {
|
||||
if (i <= longestMatch) {
|
||||
entries++;
|
||||
} else {
|
||||
entries = 0;
|
||||
}
|
||||
}
|
||||
|
||||
css += tokens[i].value;
|
||||
}
|
||||
|
||||
if (node === null) {
|
||||
mismatchOffset = css.length;
|
||||
}
|
||||
|
||||
return {
|
||||
node: node,
|
||||
css: css,
|
||||
mismatchOffset: mismatchOffset,
|
||||
last: node === null || entries > 1
|
||||
};
|
||||
}
|
||||
|
||||
function getLocation(node, point) {
|
||||
var loc = node && node.loc && node.loc[point];
|
||||
|
||||
if (loc) {
|
||||
return {
|
||||
offset: loc.offset,
|
||||
line: loc.line,
|
||||
column: loc.column
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var SyntaxReferenceError = function(type, referenceName) {
|
||||
var error = createCustomError(
|
||||
'SyntaxReferenceError',
|
||||
type + (referenceName ? ' `' + referenceName + '`' : '')
|
||||
);
|
||||
|
||||
error.reference = referenceName;
|
||||
|
||||
return error;
|
||||
};
|
||||
|
||||
var MatchError = function(message, lexer, syntax, node, matchResult) {
|
||||
var error = createCustomError('SyntaxMatchError', message);
|
||||
var details = fromMatchResult(matchResult);
|
||||
var mismatchOffset = details.mismatchOffset || 0;
|
||||
var badNode = details.node || node;
|
||||
var end = getLocation(badNode, 'end');
|
||||
var start = details.last ? end : getLocation(badNode, 'start');
|
||||
var css = details.css;
|
||||
|
||||
error.rawMessage = message;
|
||||
error.syntax = syntax ? generateGrammar(syntax) : '<generic>';
|
||||
error.css = css;
|
||||
error.mismatchOffset = mismatchOffset;
|
||||
error.loc = {
|
||||
source: (badNode && badNode.loc && badNode.loc.source) || '<unknown>',
|
||||
start: start,
|
||||
end: end
|
||||
};
|
||||
error.line = start ? start.line : undefined;
|
||||
error.column = start ? start.column : undefined;
|
||||
error.offset = start ? start.offset : undefined;
|
||||
error.message = message + '\n' +
|
||||
' syntax: ' + error.syntax + '\n' +
|
||||
' value: ' + (error.css || '<empty string>') + '\n' +
|
||||
' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
|
||||
|
||||
return error;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
SyntaxReferenceError: SyntaxReferenceError,
|
||||
MatchError: MatchError
|
||||
};
|
||||
415
node_modules/csso/node_modules/css-tree/lib/lexer/generic.js
generated
vendored
Normal file
415
node_modules/csso/node_modules/css-tree/lib/lexer/generic.js
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
var tokenizerUtils = require('../tokenizer/utils');
|
||||
var findIdentifierEnd = tokenizerUtils.findIdentifierEnd;
|
||||
var findNumberEnd = tokenizerUtils.findNumberEnd;
|
||||
var findDecimalNumberEnd = tokenizerUtils.findDecimalNumberEnd;
|
||||
var isHex = tokenizerUtils.isHex;
|
||||
var tokenizerConst = require('../tokenizer/const');
|
||||
var SYMBOL_TYPE = tokenizerConst.SYMBOL_TYPE;
|
||||
var IDENTIFIER = tokenizerConst.TYPE.Identifier;
|
||||
var PLUSSIGN = tokenizerConst.TYPE.PlusSign;
|
||||
var HYPHENMINUS = tokenizerConst.TYPE.HyphenMinus;
|
||||
var NUMBERSIGN = tokenizerConst.TYPE.NumberSign;
|
||||
|
||||
var PERCENTAGE = {
|
||||
'%': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css-values-3/#lengths
|
||||
var LENGTH = {
|
||||
// absolute length units
|
||||
'px': true,
|
||||
'mm': true,
|
||||
'cm': true,
|
||||
'in': true,
|
||||
'pt': true,
|
||||
'pc': true,
|
||||
'q': true,
|
||||
|
||||
// relative length units
|
||||
'em': true,
|
||||
'ex': true,
|
||||
'ch': true,
|
||||
'rem': true,
|
||||
|
||||
// viewport-percentage lengths
|
||||
'vh': true,
|
||||
'vw': true,
|
||||
'vmin': true,
|
||||
'vmax': true,
|
||||
'vm': true
|
||||
};
|
||||
|
||||
var ANGLE = {
|
||||
'deg': true,
|
||||
'grad': true,
|
||||
'rad': true,
|
||||
'turn': true
|
||||
};
|
||||
|
||||
var TIME = {
|
||||
's': true,
|
||||
'ms': true
|
||||
};
|
||||
|
||||
var FREQUENCY = {
|
||||
'hz': true,
|
||||
'khz': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css-values-3/#resolution (https://drafts.csswg.org/css-values/#resolution)
|
||||
var RESOLUTION = {
|
||||
'dpi': true,
|
||||
'dpcm': true,
|
||||
'dppx': true,
|
||||
'x': true // https://github.com/w3c/csswg-drafts/issues/461
|
||||
};
|
||||
|
||||
// https://drafts.csswg.org/css-grid/#fr-unit
|
||||
var FLEX = {
|
||||
'fr': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
|
||||
var DECIBEL = {
|
||||
'db': true
|
||||
};
|
||||
|
||||
// https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
|
||||
var SEMITONES = {
|
||||
'st': true
|
||||
};
|
||||
|
||||
function consumeFunction(token, addTokenToMatch, getNextToken) {
|
||||
var length = 1;
|
||||
var cursor;
|
||||
|
||||
do {
|
||||
cursor = getNextToken(length++);
|
||||
} while (cursor !== null && cursor.node !== token.node);
|
||||
|
||||
if (cursor === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
// consume tokens until cursor
|
||||
if (addTokenToMatch() === cursor) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
|
||||
// https://drafts.csswg.org/css-values/#calc-notation
|
||||
function calc(token, addTokenToMatch, getNextToken) {
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var name = token.value.toLowerCase();
|
||||
if (name !== 'calc(' &&
|
||||
name !== '-moz-calc(' &&
|
||||
name !== '-webkit-calc(') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return consumeFunction(token, addTokenToMatch, getNextToken);
|
||||
}
|
||||
|
||||
function attr(token, addTokenToMatch, getNextToken) {
|
||||
if (token === null || token.value.toLowerCase() !== 'attr(') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return consumeFunction(token, addTokenToMatch, getNextToken);
|
||||
}
|
||||
|
||||
function expression(token, addTokenToMatch, getNextToken) {
|
||||
if (token === null || token.value.toLowerCase() !== 'expression(') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return consumeFunction(token, addTokenToMatch, getNextToken);
|
||||
}
|
||||
|
||||
function url(token, addTokenToMatch, getNextToken) {
|
||||
if (token === null || token.value.toLowerCase() !== 'url(') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return consumeFunction(token, addTokenToMatch, getNextToken);
|
||||
}
|
||||
|
||||
function idSelector(token, addTokenToMatch) {
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token.value.charCodeAt(0) !== NUMBERSIGN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (consumeIdentifier(token.value, 1) !== token.value.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
function isNumber(str) {
|
||||
return /^[-+]?(\d+|\d*\.\d+)([eE][-+]?\d+)?$/.test(str);
|
||||
}
|
||||
|
||||
function consumeNumber(str, allowFraction) {
|
||||
var code = str.charCodeAt(0);
|
||||
|
||||
return findNumberEnd(str, code === PLUSSIGN || code === HYPHENMINUS ? 1 : 0, allowFraction);
|
||||
}
|
||||
|
||||
function consumeIdentifier(str, offset) {
|
||||
var code = str.charCodeAt(offset);
|
||||
|
||||
if (code < 0x80 && SYMBOL_TYPE[code] !== IDENTIFIER && code !== HYPHENMINUS) {
|
||||
return offset;
|
||||
}
|
||||
|
||||
return findIdentifierEnd(str, offset + 1);
|
||||
}
|
||||
|
||||
function astNode(type) {
|
||||
return function(token, addTokenToMatch) {
|
||||
if (token === null || token.node.type !== type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function dimension(type) {
|
||||
return function(token, addTokenToMatch, getNextToken) {
|
||||
if (calc(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var numberEnd = consumeNumber(token.value, true);
|
||||
if (numberEnd === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type) {
|
||||
if (!type.hasOwnProperty(token.value.substr(numberEnd).toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
var unitEnd = consumeIdentifier(token.value, numberEnd);
|
||||
if (unitEnd === numberEnd || unitEnd !== token.value.length) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function zeroUnitlessDimension(type) {
|
||||
var isDimension = dimension(type);
|
||||
|
||||
return function(token, addTokenToMatch, getNextToken) {
|
||||
if (isDimension(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null || Number(token.value) !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
function number(token, addTokenToMatch, getNextToken) {
|
||||
if (calc(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var numberEnd = consumeNumber(token.value, true);
|
||||
if (numberEnd !== token.value.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
function numberZeroOne(token, addTokenToMatch, getNextToken) {
|
||||
if (calc(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null || !isNumber(token.value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var value = Number(token.value);
|
||||
if (value < 0 || value > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
function numberOneOrGreater(token, addTokenToMatch, getNextToken) {
|
||||
if (calc(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null || !isNumber(token.value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var value = Number(token.value);
|
||||
if (value < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: fail on 10e-2
|
||||
function integer(token, addTokenToMatch, getNextToken) {
|
||||
if (calc(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var numberEnd = consumeNumber(token.value, false);
|
||||
if (numberEnd !== token.value.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: fail on 10e-2
|
||||
function positiveInteger(token, addTokenToMatch, getNextToken) {
|
||||
if (calc(token, addTokenToMatch, getNextToken)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var numberEnd = findDecimalNumberEnd(token.value, 0);
|
||||
if (numberEnd !== token.value.length || token.value.charCodeAt(0) === HYPHENMINUS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
function hexColor(token, addTokenToMatch) {
|
||||
if (token === null || token.value.charCodeAt(0) !== NUMBERSIGN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var length = token.value.length - 1;
|
||||
|
||||
// valid length is 3, 4, 6 and 8 (+1 for #)
|
||||
if (length !== 3 && length !== 4 && length !== 6 && length !== 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 1; i < length; i++) {
|
||||
if (!isHex(token.value.charCodeAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
|
||||
// https://drafts.csswg.org/css-values-4/#identifier-value
|
||||
function customIdent(token, addTokenToMatch) {
|
||||
if (token === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var identEnd = consumeIdentifier(token.value, 0);
|
||||
if (identEnd !== token.value.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var name = token.value.toLowerCase();
|
||||
|
||||
// § 3.2. Author-defined Identifiers: the <custom-ident> type
|
||||
// The CSS-wide keywords are not valid <custom-ident>s
|
||||
if (name === 'unset' || name === 'initial' || name === 'inherit') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The default keyword is reserved and is also not a valid <custom-ident>
|
||||
if (name === 'default') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)
|
||||
|
||||
addTokenToMatch();
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
'angle': zeroUnitlessDimension(ANGLE),
|
||||
'attr()': attr,
|
||||
'custom-ident': customIdent,
|
||||
'decibel': dimension(DECIBEL),
|
||||
'dimension': dimension(),
|
||||
'frequency': dimension(FREQUENCY),
|
||||
'flex': dimension(FLEX),
|
||||
'hex-color': hexColor,
|
||||
'id-selector': idSelector, // element( <id-selector> )
|
||||
'ident': astNode('Identifier'),
|
||||
'integer': integer,
|
||||
'length': zeroUnitlessDimension(LENGTH),
|
||||
'number': number,
|
||||
'number-zero-one': numberZeroOne,
|
||||
'number-one-or-greater': numberOneOrGreater,
|
||||
'percentage': dimension(PERCENTAGE),
|
||||
'positive-integer': positiveInteger,
|
||||
'resolution': dimension(RESOLUTION),
|
||||
'semitones': dimension(SEMITONES),
|
||||
'string': astNode('String'),
|
||||
'time': dimension(TIME),
|
||||
'unicode-range': astNode('UnicodeRange'),
|
||||
'url': url,
|
||||
|
||||
// old IE stuff
|
||||
'progid': astNode('Raw'),
|
||||
'expression': expression
|
||||
};
|
||||
18
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/error.js
generated
vendored
Normal file
18
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/error.js
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
var createCustomError = require('../../utils/createCustomError');
|
||||
|
||||
var SyntaxParseError = function(message, input, offset) {
|
||||
var error = createCustomError('SyntaxParseError', message);
|
||||
|
||||
error.input = input;
|
||||
error.offset = offset;
|
||||
error.rawMessage = message;
|
||||
error.message = error.rawMessage + '\n' +
|
||||
' ' + error.input + '\n' +
|
||||
'--' + new Array((error.offset || error.input.length) + 1).join('-') + '^';
|
||||
|
||||
return error;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
SyntaxParseError: SyntaxParseError
|
||||
};
|
||||
110
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/generate.js
generated
vendored
Normal file
110
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/generate.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
function noop(value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function generateMultiplier(multiplier) {
|
||||
if (multiplier.min === 0 && multiplier.max === 0) {
|
||||
return '*';
|
||||
}
|
||||
|
||||
if (multiplier.min === 0 && multiplier.max === 1) {
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (multiplier.min === 1 && multiplier.max === 0) {
|
||||
return multiplier.comma ? '#' : '+';
|
||||
}
|
||||
|
||||
if (multiplier.min === 1 && multiplier.max === 1) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (
|
||||
(multiplier.comma ? '#' : '') +
|
||||
(multiplier.min === multiplier.max
|
||||
? '{' + multiplier.min + '}'
|
||||
: '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function generateSequence(node, forceBraces, decorate) {
|
||||
var result = node.terms.map(function(term) {
|
||||
return generate(term, forceBraces, decorate);
|
||||
}).join(node.combinator === ' ' ? ' ' : ' ' + node.combinator + ' ');
|
||||
|
||||
if (node.explicit || forceBraces) {
|
||||
result = (result[0] !== ',' ? '[ ' : '[') + result + ' ]';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function generate(node, forceBraces, decorate) {
|
||||
var result;
|
||||
|
||||
switch (node.type) {
|
||||
case 'Group':
|
||||
result =
|
||||
generateSequence(node, forceBraces, decorate) +
|
||||
(node.disallowEmpty ? '!' : '');
|
||||
break;
|
||||
|
||||
case 'Multiplier':
|
||||
// return since node is a composition
|
||||
return (
|
||||
generate(node.term, forceBraces, decorate) +
|
||||
decorate(generateMultiplier(node), node)
|
||||
);
|
||||
|
||||
case 'Type':
|
||||
result = '<' + node.name + '>';
|
||||
break;
|
||||
|
||||
case 'Property':
|
||||
result = '<\'' + node.name + '\'>';
|
||||
break;
|
||||
|
||||
case 'Keyword':
|
||||
result = node.name;
|
||||
break;
|
||||
|
||||
case 'AtKeyword':
|
||||
result = '@' + node.name;
|
||||
break;
|
||||
|
||||
case 'Function':
|
||||
result = node.name + '(';
|
||||
break;
|
||||
|
||||
case 'String':
|
||||
case 'Token':
|
||||
result = node.value;
|
||||
break;
|
||||
|
||||
case 'Comma':
|
||||
result = ',';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Unknown node type `' + node.type + '`');
|
||||
}
|
||||
|
||||
return decorate(result, node);
|
||||
}
|
||||
|
||||
module.exports = function(node, options) {
|
||||
var decorate = noop;
|
||||
var forceBraces = false;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
decorate = options;
|
||||
} else if (options) {
|
||||
forceBraces = Boolean(options.forceBraces);
|
||||
if (typeof options.decorate === 'function') {
|
||||
decorate = options.decorate;
|
||||
}
|
||||
}
|
||||
|
||||
return generate(node, forceBraces, decorate);
|
||||
};
|
||||
6
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/index.js
generated
vendored
Normal file
6
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/index.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
SyntaxParseError: require('./error').SyntaxParseError,
|
||||
parse: require('./parse'),
|
||||
generate: require('./generate'),
|
||||
walk: require('./walk')
|
||||
};
|
||||
501
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/parse.js
generated
vendored
Normal file
501
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/parse.js
generated
vendored
Normal file
@@ -0,0 +1,501 @@
|
||||
var Tokenizer = require('./tokenizer');
|
||||
var TAB = 9;
|
||||
var N = 10;
|
||||
var F = 12;
|
||||
var R = 13;
|
||||
var SPACE = 32;
|
||||
var EXCLAMATIONMARK = 33; // !
|
||||
var NUMBERSIGN = 35; // #
|
||||
var AMPERSAND = 38; // &
|
||||
var APOSTROPHE = 39; // '
|
||||
var LEFTPARENTHESIS = 40; // (
|
||||
var RIGHTPARENTHESIS = 41; // )
|
||||
var ASTERISK = 42; // *
|
||||
var PLUSSIGN = 43; // +
|
||||
var COMMA = 44; // ,
|
||||
var LESSTHANSIGN = 60; // <
|
||||
var GREATERTHANSIGN = 62; // >
|
||||
var QUESTIONMARK = 63; // ?
|
||||
var COMMERCIALAT = 64; // @
|
||||
var LEFTSQUAREBRACKET = 91; // [
|
||||
var RIGHTSQUAREBRACKET = 93; // ]
|
||||
var LEFTCURLYBRACKET = 123; // {
|
||||
var VERTICALLINE = 124; // |
|
||||
var RIGHTCURLYBRACKET = 125; // }
|
||||
var NAME_CHAR = createCharMap(function(ch) {
|
||||
return /[a-zA-Z0-9\-]/.test(ch);
|
||||
});
|
||||
var COMBINATOR_PRECEDENCE = {
|
||||
' ': 1,
|
||||
'&&': 2,
|
||||
'||': 3,
|
||||
'|': 4
|
||||
};
|
||||
|
||||
function createCharMap(fn) {
|
||||
var array = typeof Uint32Array === 'function' ? new Uint32Array(128) : new Array(128);
|
||||
for (var i = 0; i < 128; i++) {
|
||||
array[i] = fn(String.fromCharCode(i)) ? 1 : 0;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function scanSpaces(tokenizer) {
|
||||
return tokenizer.substringToPos(
|
||||
tokenizer.findWsEnd(tokenizer.pos + 1)
|
||||
);
|
||||
}
|
||||
|
||||
function scanWord(tokenizer) {
|
||||
var end = tokenizer.pos;
|
||||
|
||||
for (; end < tokenizer.str.length; end++) {
|
||||
var code = tokenizer.str.charCodeAt(end);
|
||||
if (code >= 128 || NAME_CHAR[code] === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokenizer.pos === end) {
|
||||
tokenizer.error('Expect a keyword');
|
||||
}
|
||||
|
||||
return tokenizer.substringToPos(end);
|
||||
}
|
||||
|
||||
function scanNumber(tokenizer) {
|
||||
var end = tokenizer.pos;
|
||||
|
||||
for (; end < tokenizer.str.length; end++) {
|
||||
var code = tokenizer.str.charCodeAt(end);
|
||||
if (code < 48 || code > 57) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokenizer.pos === end) {
|
||||
tokenizer.error('Expect a number');
|
||||
}
|
||||
|
||||
return tokenizer.substringToPos(end);
|
||||
}
|
||||
|
||||
function scanString(tokenizer) {
|
||||
var end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
|
||||
|
||||
if (end === -1) {
|
||||
tokenizer.pos = tokenizer.str.length;
|
||||
tokenizer.error('Expect an apostrophe');
|
||||
}
|
||||
|
||||
return tokenizer.substringToPos(end + 1);
|
||||
}
|
||||
|
||||
function readMultiplierRange(tokenizer) {
|
||||
var min = null;
|
||||
var max = null;
|
||||
|
||||
tokenizer.eat(LEFTCURLYBRACKET);
|
||||
|
||||
min = scanNumber(tokenizer);
|
||||
|
||||
if (tokenizer.charCode() === COMMA) {
|
||||
tokenizer.pos++;
|
||||
if (tokenizer.charCode() !== RIGHTCURLYBRACKET) {
|
||||
max = scanNumber(tokenizer);
|
||||
}
|
||||
} else {
|
||||
max = min;
|
||||
}
|
||||
|
||||
tokenizer.eat(RIGHTCURLYBRACKET);
|
||||
|
||||
return {
|
||||
min: Number(min),
|
||||
max: max ? Number(max) : 0
|
||||
};
|
||||
}
|
||||
|
||||
function readMultiplier(tokenizer) {
|
||||
var range = null;
|
||||
var comma = false;
|
||||
|
||||
switch (tokenizer.charCode()) {
|
||||
case ASTERISK:
|
||||
tokenizer.pos++;
|
||||
|
||||
range = {
|
||||
min: 0,
|
||||
max: 0
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case PLUSSIGN:
|
||||
tokenizer.pos++;
|
||||
|
||||
range = {
|
||||
min: 1,
|
||||
max: 0
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case QUESTIONMARK:
|
||||
tokenizer.pos++;
|
||||
|
||||
range = {
|
||||
min: 0,
|
||||
max: 1
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case NUMBERSIGN:
|
||||
tokenizer.pos++;
|
||||
|
||||
comma = true;
|
||||
|
||||
if (tokenizer.charCode() === LEFTCURLYBRACKET) {
|
||||
range = readMultiplierRange(tokenizer);
|
||||
} else {
|
||||
range = {
|
||||
min: 1,
|
||||
max: 0
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LEFTCURLYBRACKET:
|
||||
range = readMultiplierRange(tokenizer);
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Multiplier',
|
||||
comma: comma,
|
||||
min: range.min,
|
||||
max: range.max,
|
||||
term: null
|
||||
};
|
||||
}
|
||||
|
||||
function maybeMultiplied(tokenizer, node) {
|
||||
var multiplier = readMultiplier(tokenizer);
|
||||
|
||||
if (multiplier !== null) {
|
||||
multiplier.term = node;
|
||||
return multiplier;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function maybeToken(tokenizer) {
|
||||
var ch = tokenizer.peek();
|
||||
|
||||
if (ch === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Token',
|
||||
value: ch
|
||||
};
|
||||
}
|
||||
|
||||
function readProperty(tokenizer) {
|
||||
var name;
|
||||
|
||||
tokenizer.eat(LESSTHANSIGN);
|
||||
tokenizer.eat(APOSTROPHE);
|
||||
|
||||
name = scanWord(tokenizer);
|
||||
|
||||
tokenizer.eat(APOSTROPHE);
|
||||
tokenizer.eat(GREATERTHANSIGN);
|
||||
|
||||
return maybeMultiplied(tokenizer, {
|
||||
type: 'Property',
|
||||
name: name
|
||||
});
|
||||
}
|
||||
|
||||
function readType(tokenizer) {
|
||||
var name;
|
||||
|
||||
tokenizer.eat(LESSTHANSIGN);
|
||||
name = scanWord(tokenizer);
|
||||
|
||||
if (tokenizer.charCode() === LEFTPARENTHESIS &&
|
||||
tokenizer.nextCharCode() === RIGHTPARENTHESIS) {
|
||||
tokenizer.pos += 2;
|
||||
name += '()';
|
||||
}
|
||||
|
||||
tokenizer.eat(GREATERTHANSIGN);
|
||||
|
||||
return maybeMultiplied(tokenizer, {
|
||||
type: 'Type',
|
||||
name: name
|
||||
});
|
||||
}
|
||||
|
||||
function readKeywordOrFunction(tokenizer) {
|
||||
var name;
|
||||
|
||||
name = scanWord(tokenizer);
|
||||
|
||||
if (tokenizer.charCode() === LEFTPARENTHESIS) {
|
||||
tokenizer.pos++;
|
||||
|
||||
return {
|
||||
type: 'Function',
|
||||
name: name
|
||||
};
|
||||
}
|
||||
|
||||
return maybeMultiplied(tokenizer, {
|
||||
type: 'Keyword',
|
||||
name: name
|
||||
});
|
||||
}
|
||||
|
||||
function regroupTerms(terms, combinators) {
|
||||
function createGroup(terms, combinator) {
|
||||
return {
|
||||
type: 'Group',
|
||||
terms: terms,
|
||||
combinator: combinator,
|
||||
disallowEmpty: false,
|
||||
explicit: false
|
||||
};
|
||||
}
|
||||
|
||||
combinators = Object.keys(combinators).sort(function(a, b) {
|
||||
return COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b];
|
||||
});
|
||||
|
||||
while (combinators.length > 0) {
|
||||
var combinator = combinators.shift();
|
||||
for (var i = 0, subgroupStart = 0; i < terms.length; i++) {
|
||||
var term = terms[i];
|
||||
if (term.type === 'Combinator') {
|
||||
if (term.value === combinator) {
|
||||
if (subgroupStart === -1) {
|
||||
subgroupStart = i - 1;
|
||||
}
|
||||
terms.splice(i, 1);
|
||||
i--;
|
||||
} else {
|
||||
if (subgroupStart !== -1 && i - subgroupStart > 1) {
|
||||
terms.splice(
|
||||
subgroupStart,
|
||||
i - subgroupStart,
|
||||
createGroup(terms.slice(subgroupStart, i), combinator)
|
||||
);
|
||||
i = subgroupStart + 1;
|
||||
}
|
||||
subgroupStart = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (subgroupStart !== -1 && combinators.length) {
|
||||
terms.splice(
|
||||
subgroupStart,
|
||||
i - subgroupStart,
|
||||
createGroup(terms.slice(subgroupStart, i), combinator)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return combinator;
|
||||
}
|
||||
|
||||
function readImplicitGroup(tokenizer) {
|
||||
var terms = [];
|
||||
var combinators = {};
|
||||
var token;
|
||||
var prevToken = null;
|
||||
var prevTokenPos = tokenizer.pos;
|
||||
|
||||
while (token = peek(tokenizer)) {
|
||||
if (token.type !== 'Spaces') {
|
||||
if (token.type === 'Combinator') {
|
||||
// check for combinator in group beginning and double combinator sequence
|
||||
if (prevToken === null || prevToken.type === 'Combinator') {
|
||||
tokenizer.pos = prevTokenPos;
|
||||
tokenizer.error('Unexpected combinator');
|
||||
}
|
||||
|
||||
combinators[token.value] = true;
|
||||
} else if (prevToken !== null && prevToken.type !== 'Combinator') {
|
||||
combinators[' '] = true; // a b
|
||||
terms.push({
|
||||
type: 'Combinator',
|
||||
value: ' '
|
||||
});
|
||||
}
|
||||
|
||||
terms.push(token);
|
||||
prevToken = token;
|
||||
prevTokenPos = tokenizer.pos;
|
||||
}
|
||||
}
|
||||
|
||||
// check for combinator in group ending
|
||||
if (prevToken !== null && prevToken.type === 'Combinator') {
|
||||
tokenizer.pos -= prevTokenPos;
|
||||
tokenizer.error('Unexpected combinator');
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'Group',
|
||||
terms: terms,
|
||||
combinator: regroupTerms(terms, combinators) || ' ',
|
||||
disallowEmpty: false,
|
||||
explicit: false
|
||||
};
|
||||
}
|
||||
|
||||
function readGroup(tokenizer) {
|
||||
var result;
|
||||
|
||||
tokenizer.eat(LEFTSQUAREBRACKET);
|
||||
result = readImplicitGroup(tokenizer);
|
||||
tokenizer.eat(RIGHTSQUAREBRACKET);
|
||||
|
||||
result.explicit = true;
|
||||
|
||||
if (tokenizer.charCode() === EXCLAMATIONMARK) {
|
||||
tokenizer.pos++;
|
||||
result.disallowEmpty = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function peek(tokenizer) {
|
||||
var code = tokenizer.charCode();
|
||||
|
||||
if (code < 128 && NAME_CHAR[code] === 1) {
|
||||
return readKeywordOrFunction(tokenizer);
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case RIGHTSQUAREBRACKET:
|
||||
// don't eat, stop scan a group
|
||||
break;
|
||||
|
||||
case LEFTSQUAREBRACKET:
|
||||
return maybeMultiplied(tokenizer, readGroup(tokenizer));
|
||||
|
||||
case LESSTHANSIGN:
|
||||
return tokenizer.nextCharCode() === APOSTROPHE
|
||||
? readProperty(tokenizer)
|
||||
: readType(tokenizer);
|
||||
|
||||
case VERTICALLINE:
|
||||
return {
|
||||
type: 'Combinator',
|
||||
value: tokenizer.substringToPos(
|
||||
tokenizer.nextCharCode() === VERTICALLINE
|
||||
? tokenizer.pos + 2
|
||||
: tokenizer.pos + 1
|
||||
)
|
||||
};
|
||||
|
||||
case AMPERSAND:
|
||||
tokenizer.pos++;
|
||||
tokenizer.eat(AMPERSAND);
|
||||
|
||||
return {
|
||||
type: 'Combinator',
|
||||
value: '&&'
|
||||
};
|
||||
|
||||
case COMMA:
|
||||
tokenizer.pos++;
|
||||
return {
|
||||
type: 'Comma'
|
||||
};
|
||||
|
||||
case APOSTROPHE:
|
||||
return maybeMultiplied(tokenizer, {
|
||||
type: 'String',
|
||||
value: scanString(tokenizer)
|
||||
});
|
||||
|
||||
case SPACE:
|
||||
case TAB:
|
||||
case N:
|
||||
case R:
|
||||
case F:
|
||||
return {
|
||||
type: 'Spaces',
|
||||
value: scanSpaces(tokenizer)
|
||||
};
|
||||
|
||||
case COMMERCIALAT:
|
||||
code = tokenizer.nextCharCode();
|
||||
|
||||
if (code < 128 && NAME_CHAR[code] === 1) {
|
||||
tokenizer.pos++;
|
||||
return {
|
||||
type: 'AtKeyword',
|
||||
name: scanWord(tokenizer)
|
||||
};
|
||||
}
|
||||
|
||||
return maybeToken(tokenizer);
|
||||
|
||||
case ASTERISK:
|
||||
case PLUSSIGN:
|
||||
case QUESTIONMARK:
|
||||
case NUMBERSIGN:
|
||||
case EXCLAMATIONMARK:
|
||||
// prohibited tokens (used as a multiplier start)
|
||||
break;
|
||||
|
||||
case LEFTCURLYBRACKET:
|
||||
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
|
||||
// check next char isn't a number, because it's likely a disjoined multiplier
|
||||
code = tokenizer.nextCharCode();
|
||||
|
||||
if (code < 48 || code > 57) {
|
||||
return maybeToken(tokenizer);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return maybeToken(tokenizer);
|
||||
}
|
||||
}
|
||||
|
||||
function parse(str) {
|
||||
var tokenizer = new Tokenizer(str);
|
||||
var result = readImplicitGroup(tokenizer);
|
||||
|
||||
if (tokenizer.pos !== str.length) {
|
||||
tokenizer.error('Unexpected input');
|
||||
}
|
||||
|
||||
// reduce redundant groups with single group term
|
||||
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
|
||||
result = result.terms[0];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// warm up parse to elimitate code branches that never execute
|
||||
// fix soft deoptimizations (insufficient type feedback)
|
||||
parse('[a&&<b>#|<\'c\'>*||e() f{2} /,(% g#{1,2} h{2,})]!');
|
||||
|
||||
module.exports = parse;
|
||||
55
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/tokenizer.js
generated
vendored
Normal file
55
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/tokenizer.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
var SyntaxParseError = require('./error').SyntaxParseError;
|
||||
|
||||
var TAB = 9;
|
||||
var N = 10;
|
||||
var F = 12;
|
||||
var R = 13;
|
||||
var SPACE = 32;
|
||||
|
||||
var Tokenizer = function(str) {
|
||||
this.str = str;
|
||||
this.pos = 0;
|
||||
};
|
||||
|
||||
Tokenizer.prototype = {
|
||||
charCodeAt: function(pos) {
|
||||
return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
|
||||
},
|
||||
charCode: function() {
|
||||
return this.charCodeAt(this.pos);
|
||||
},
|
||||
nextCharCode: function() {
|
||||
return this.charCodeAt(this.pos + 1);
|
||||
},
|
||||
nextNonWsCode: function(pos) {
|
||||
return this.charCodeAt(this.findWsEnd(pos));
|
||||
},
|
||||
findWsEnd: function(pos) {
|
||||
for (; pos < this.str.length; pos++) {
|
||||
var code = this.str.charCodeAt(pos);
|
||||
if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
},
|
||||
substringToPos: function(end) {
|
||||
return this.str.substring(this.pos, this.pos = end);
|
||||
},
|
||||
eat: function(code) {
|
||||
if (this.charCode() !== code) {
|
||||
this.error('Expect `' + String.fromCharCode(code) + '`');
|
||||
}
|
||||
|
||||
this.pos++;
|
||||
},
|
||||
peek: function() {
|
||||
return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
|
||||
},
|
||||
error: function(message) {
|
||||
throw new SyntaxParseError(message, this.str, this.pos);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Tokenizer;
|
||||
54
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/walk.js
generated
vendored
Normal file
54
node_modules/csso/node_modules/css-tree/lib/lexer/grammar/walk.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
var noop = function() {};
|
||||
|
||||
function ensureFunction(value) {
|
||||
return typeof value === 'function' ? value : noop;
|
||||
}
|
||||
|
||||
module.exports = function(node, options, context) {
|
||||
function walk(node) {
|
||||
enter.call(context, node);
|
||||
|
||||
switch (node.type) {
|
||||
case 'Group':
|
||||
node.terms.forEach(walk);
|
||||
break;
|
||||
|
||||
case 'Multiplier':
|
||||
walk(node.term);
|
||||
break;
|
||||
|
||||
case 'Type':
|
||||
case 'Property':
|
||||
case 'Keyword':
|
||||
case 'AtKeyword':
|
||||
case 'Function':
|
||||
case 'String':
|
||||
case 'Token':
|
||||
case 'Comma':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Unknown type: ' + node.type);
|
||||
}
|
||||
|
||||
leave.call(context, node);
|
||||
}
|
||||
|
||||
var enter = noop;
|
||||
var leave = noop;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
enter = options;
|
||||
} else if (options) {
|
||||
enter = ensureFunction(options.enter);
|
||||
leave = ensureFunction(options.leave);
|
||||
}
|
||||
|
||||
if (enter === noop && leave === noop) {
|
||||
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
|
||||
}
|
||||
|
||||
walk(node, context);
|
||||
};
|
||||
6
node_modules/csso/node_modules/css-tree/lib/lexer/index.js
generated
vendored
Normal file
6
node_modules/csso/node_modules/css-tree/lib/lexer/index.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
Lexer: require('./Lexer'),
|
||||
grammar: require('./grammar')
|
||||
};
|
||||
455
node_modules/csso/node_modules/css-tree/lib/lexer/match-graph.js
generated
vendored
Normal file
455
node_modules/csso/node_modules/css-tree/lib/lexer/match-graph.js
generated
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
var parse = require('./grammar/parse');
|
||||
|
||||
var MATCH = { type: 'Match' };
|
||||
var MISMATCH = { type: 'Mismatch' };
|
||||
var DISALLOW_EMPTY = { type: 'DisallowEmpty' };
|
||||
var LEFTPARENTHESIS = 40; // (
|
||||
var RIGHTPARENTHESIS = 41; // )
|
||||
|
||||
function createCondition(match, thenBranch, elseBranch) {
|
||||
// reduce node count
|
||||
if (thenBranch === MATCH && elseBranch === MISMATCH) {
|
||||
return match;
|
||||
}
|
||||
|
||||
if (match === MATCH && thenBranch === MATCH && elseBranch === MATCH) {
|
||||
return match;
|
||||
}
|
||||
|
||||
if (match.type === 'If' && match.else === MISMATCH && thenBranch === MATCH) {
|
||||
thenBranch = match.then;
|
||||
match = match.match;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'If',
|
||||
match: match,
|
||||
then: thenBranch,
|
||||
else: elseBranch
|
||||
};
|
||||
}
|
||||
|
||||
function isFunctionType(name) {
|
||||
return (
|
||||
name.length > 2 &&
|
||||
name.charCodeAt(name.length - 2) === LEFTPARENTHESIS &&
|
||||
name.charCodeAt(name.length - 1) === RIGHTPARENTHESIS
|
||||
);
|
||||
}
|
||||
|
||||
function isEnumCapatible(term) {
|
||||
return (
|
||||
term.type === 'Keyword' ||
|
||||
term.type === 'AtKeyword' ||
|
||||
term.type === 'Function' ||
|
||||
term.type === 'Type' && isFunctionType(term.name)
|
||||
);
|
||||
}
|
||||
|
||||
function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
|
||||
switch (combinator) {
|
||||
case ' ':
|
||||
// Juxtaposing components means that all of them must occur, in the given order.
|
||||
//
|
||||
// a b c
|
||||
// =
|
||||
// match a
|
||||
// then match b
|
||||
// then match c
|
||||
// then MATCH
|
||||
// else MISMATCH
|
||||
// else MISMATCH
|
||||
// else MISMATCH
|
||||
var result = MATCH;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
|
||||
result = createCondition(
|
||||
term,
|
||||
result,
|
||||
MISMATCH
|
||||
);
|
||||
};
|
||||
|
||||
return result;
|
||||
|
||||
case '|':
|
||||
// A bar (|) separates two or more alternatives: exactly one of them must occur.
|
||||
//
|
||||
// a | b | c
|
||||
// =
|
||||
// match a
|
||||
// then MATCH
|
||||
// else match b
|
||||
// then MATCH
|
||||
// else match c
|
||||
// then MATCH
|
||||
// else MISMATCH
|
||||
|
||||
var result = MISMATCH;
|
||||
var map = null;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
|
||||
// reduce sequence of keywords into a Enum
|
||||
if (isEnumCapatible(term)) {
|
||||
if (map === null && i > 0 && isEnumCapatible(terms[i - 1])) {
|
||||
map = Object.create(null);
|
||||
result = createCondition(
|
||||
{
|
||||
type: 'Enum',
|
||||
map: map
|
||||
},
|
||||
MATCH,
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
if (map !== null) {
|
||||
var key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
|
||||
if (key in map === false) {
|
||||
map[key] = term;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map = null;
|
||||
|
||||
// create a new conditonal node
|
||||
result = createCondition(
|
||||
term,
|
||||
MATCH,
|
||||
result
|
||||
);
|
||||
};
|
||||
|
||||
return result;
|
||||
|
||||
case '&&':
|
||||
// A double ampersand (&&) separates two or more components,
|
||||
// all of which must occur, in any order.
|
||||
|
||||
// Use MatchOnce for groups with a large number of terms,
|
||||
// since &&-groups produces at least N!-node trees
|
||||
if (terms.length > 5) {
|
||||
return {
|
||||
type: 'MatchOnce',
|
||||
terms: terms,
|
||||
all: true
|
||||
};
|
||||
}
|
||||
|
||||
// Use a combination tree for groups with small number of terms
|
||||
//
|
||||
// a && b && c
|
||||
// =
|
||||
// match a
|
||||
// then [b && c]
|
||||
// else match b
|
||||
// then [a && c]
|
||||
// else match c
|
||||
// then [a && b]
|
||||
// else MISMATCH
|
||||
//
|
||||
// a && b
|
||||
// =
|
||||
// match a
|
||||
// then match b
|
||||
// then MATCH
|
||||
// else MISMATCH
|
||||
// else match b
|
||||
// then match a
|
||||
// then MATCH
|
||||
// else MISMATCH
|
||||
// else MISMATCH
|
||||
var result = MISMATCH;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
var thenClause;
|
||||
|
||||
if (terms.length > 1) {
|
||||
thenClause = buildGroupMatchGraph(
|
||||
combinator,
|
||||
terms.filter(function(newGroupTerm) {
|
||||
return newGroupTerm !== term;
|
||||
}),
|
||||
false
|
||||
);
|
||||
} else {
|
||||
thenClause = MATCH;
|
||||
}
|
||||
|
||||
result = createCondition(
|
||||
term,
|
||||
thenClause,
|
||||
result
|
||||
);
|
||||
};
|
||||
|
||||
return result;
|
||||
|
||||
case '||':
|
||||
// A double bar (||) separates two or more options:
|
||||
// one or more of them must occur, in any order.
|
||||
|
||||
// Use MatchOnce for groups with a large number of terms,
|
||||
// since ||-groups produces at least N!-node trees
|
||||
if (terms.length > 5) {
|
||||
return {
|
||||
type: 'MatchOnce',
|
||||
terms: terms,
|
||||
all: false
|
||||
};;
|
||||
}
|
||||
|
||||
// Use a combination tree for groups with small number of terms
|
||||
//
|
||||
// a || b || c
|
||||
// =
|
||||
// match a
|
||||
// then [b || c]
|
||||
// else match b
|
||||
// then [a || c]
|
||||
// else match c
|
||||
// then [a || b]
|
||||
// else MISMATCH
|
||||
//
|
||||
// a || b
|
||||
// =
|
||||
// match a
|
||||
// then match b
|
||||
// then MATCH
|
||||
// else MATCH
|
||||
// else match b
|
||||
// then match a
|
||||
// then MATCH
|
||||
// else MATCH
|
||||
// else MISMATCH
|
||||
var result = atLeastOneTermMatched ? MATCH : MISMATCH;
|
||||
|
||||
for (var i = terms.length - 1; i >= 0; i--) {
|
||||
var term = terms[i];
|
||||
var thenClause;
|
||||
|
||||
if (terms.length > 1) {
|
||||
thenClause = buildGroupMatchGraph(
|
||||
combinator,
|
||||
terms.filter(function(newGroupTerm) {
|
||||
return newGroupTerm !== term;
|
||||
}),
|
||||
true
|
||||
);
|
||||
} else {
|
||||
thenClause = MATCH;
|
||||
}
|
||||
|
||||
result = createCondition(
|
||||
term,
|
||||
thenClause,
|
||||
result
|
||||
);
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function buildMultiplierMatchGraph(node) {
|
||||
var result = MATCH;
|
||||
var matchTerm = buildMatchGraph(node.term);
|
||||
|
||||
if (node.max === 0) {
|
||||
// disable repeating of empty match to prevent infinite loop
|
||||
matchTerm = createCondition(
|
||||
matchTerm,
|
||||
DISALLOW_EMPTY,
|
||||
MISMATCH
|
||||
);
|
||||
|
||||
// an occurrence count is not limited, make a cycle;
|
||||
// to collect more terms on each following matching mismatch
|
||||
result = createCondition(
|
||||
matchTerm,
|
||||
null, // will be a loop
|
||||
MISMATCH
|
||||
);
|
||||
|
||||
result.then = createCondition(
|
||||
MATCH,
|
||||
MATCH,
|
||||
result // make a loop
|
||||
);
|
||||
|
||||
if (node.comma) {
|
||||
result.then.else = createCondition(
|
||||
{ type: 'Comma', syntax: node },
|
||||
result,
|
||||
MISMATCH
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// create a match node chain for [min .. max] interval with optional matches
|
||||
for (var i = node.min || 1; i <= node.max; i++) {
|
||||
if (node.comma && result !== MATCH) {
|
||||
result = createCondition(
|
||||
{ type: 'Comma', syntax: node },
|
||||
result,
|
||||
MISMATCH
|
||||
);
|
||||
}
|
||||
|
||||
result = createCondition(
|
||||
matchTerm,
|
||||
createCondition(
|
||||
MATCH,
|
||||
MATCH,
|
||||
result
|
||||
),
|
||||
MISMATCH
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.min === 0) {
|
||||
// allow zero match
|
||||
result = createCondition(
|
||||
MATCH,
|
||||
MATCH,
|
||||
result
|
||||
);
|
||||
} else {
|
||||
// create a match node chain to collect [0 ... min - 1] required matches
|
||||
for (var i = 0; i < node.min - 1; i++) {
|
||||
if (node.comma && result !== MATCH) {
|
||||
result = createCondition(
|
||||
{ type: 'Comma', syntax: node },
|
||||
result,
|
||||
MISMATCH
|
||||
);
|
||||
}
|
||||
|
||||
result = createCondition(
|
||||
matchTerm,
|
||||
result,
|
||||
MISMATCH
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function buildMatchGraph(node) {
|
||||
if (typeof node === 'function') {
|
||||
return {
|
||||
type: 'Generic',
|
||||
fn: node
|
||||
};
|
||||
}
|
||||
|
||||
switch (node.type) {
|
||||
case 'Group':
|
||||
var result = buildGroupMatchGraph(
|
||||
node.combinator,
|
||||
node.terms.map(buildMatchGraph),
|
||||
false
|
||||
);
|
||||
|
||||
if (node.disallowEmpty) {
|
||||
result = createCondition(
|
||||
result,
|
||||
DISALLOW_EMPTY,
|
||||
MISMATCH
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
case 'Multiplier':
|
||||
return buildMultiplierMatchGraph(node);
|
||||
|
||||
case 'Type':
|
||||
case 'Property':
|
||||
return {
|
||||
type: node.type,
|
||||
name: node.name,
|
||||
syntax: node
|
||||
};
|
||||
|
||||
case 'Keyword':
|
||||
return {
|
||||
type: node.type,
|
||||
name: node.name.toLowerCase(),
|
||||
syntax: node
|
||||
};
|
||||
|
||||
case 'AtKeyword':
|
||||
return {
|
||||
type: node.type,
|
||||
name: '@' + node.name.toLowerCase(),
|
||||
syntax: node
|
||||
};
|
||||
|
||||
case 'Function':
|
||||
return {
|
||||
type: node.type,
|
||||
name: node.name.toLowerCase() + '(',
|
||||
syntax: node
|
||||
};
|
||||
|
||||
case 'String':
|
||||
// convert a one char length String to a Token
|
||||
if (node.value.length === 3) {
|
||||
return {
|
||||
type: 'Token',
|
||||
value: node.value.charAt(1),
|
||||
syntax: node
|
||||
};
|
||||
}
|
||||
|
||||
// otherwise use it as is
|
||||
return {
|
||||
type: node.type,
|
||||
value: node.value,
|
||||
syntax: node
|
||||
};
|
||||
|
||||
case 'Token':
|
||||
return {
|
||||
type: node.type,
|
||||
value: node.value,
|
||||
syntax: node
|
||||
};
|
||||
|
||||
case 'Comma':
|
||||
return {
|
||||
type: node.type,
|
||||
syntax: node
|
||||
};
|
||||
|
||||
default:
|
||||
throw new Error('Unknown node type:', node.type);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MATCH: MATCH,
|
||||
MISMATCH: MISMATCH,
|
||||
DISALLOW_EMPTY: DISALLOW_EMPTY,
|
||||
buildMatchGraph: function(syntaxTree, ref) {
|
||||
if (typeof syntaxTree === 'string') {
|
||||
syntaxTree = parse(syntaxTree);
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'MatchGraph',
|
||||
match: buildMatchGraph(syntaxTree),
|
||||
syntax: ref || null,
|
||||
source: syntaxTree
|
||||
};
|
||||
}
|
||||
};
|
||||
539
node_modules/csso/node_modules/css-tree/lib/lexer/match.js
generated
vendored
Normal file
539
node_modules/csso/node_modules/css-tree/lib/lexer/match.js
generated
vendored
Normal file
@@ -0,0 +1,539 @@
|
||||
'use strict';
|
||||
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var matchGraph = require('./match-graph');
|
||||
var MATCH = matchGraph.MATCH;
|
||||
var MISMATCH = matchGraph.MISMATCH;
|
||||
var DISALLOW_EMPTY = matchGraph.DISALLOW_EMPTY;
|
||||
|
||||
var TOKEN = 1;
|
||||
var OPEN_SYNTAX = 2;
|
||||
var CLOSE_SYNTAX = 3;
|
||||
|
||||
var EXIT_REASON_MATCH = 'Match';
|
||||
var EXIT_REASON_MISMATCH = 'Mismatch';
|
||||
var EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
|
||||
|
||||
var ITERATION_LIMIT = 10000;
|
||||
var totalIterationCount = 0;
|
||||
|
||||
function mapList(list, fn) {
|
||||
var result = [];
|
||||
|
||||
while (list) {
|
||||
result.unshift(fn(list));
|
||||
list = list.prev;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isCommaContextStart(token) {
|
||||
if (token === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
token = token.value.charAt(token.value.length - 1);
|
||||
|
||||
return (
|
||||
token === ',' ||
|
||||
token === '(' ||
|
||||
token === '[' ||
|
||||
token === '/'
|
||||
);
|
||||
}
|
||||
|
||||
function isCommaContextEnd(token) {
|
||||
if (token === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
token = token.value.charAt(0);
|
||||
|
||||
return (
|
||||
token === ')' ||
|
||||
token === ']' ||
|
||||
token === '/'
|
||||
);
|
||||
}
|
||||
|
||||
function internalMatch(tokens, syntax, syntaxes) {
|
||||
function moveToNextToken() {
|
||||
do {
|
||||
tokenCursor++;
|
||||
token = tokenCursor < tokens.length ? tokens[tokenCursor] : null;
|
||||
} while (token !== null && !/\S/.test(token.value));
|
||||
}
|
||||
|
||||
function getNextToken(offset) {
|
||||
var nextIndex = tokenCursor + offset;
|
||||
|
||||
return nextIndex < tokens.length ? tokens[nextIndex] : null;
|
||||
}
|
||||
|
||||
function pushThenStack(nextSyntax) {
|
||||
thenStack = {
|
||||
nextSyntax: nextSyntax,
|
||||
matchStack: matchStack,
|
||||
syntaxStack: syntaxStack,
|
||||
prev: thenStack
|
||||
};
|
||||
}
|
||||
|
||||
function pushElseStack(nextSyntax) {
|
||||
elseStack = {
|
||||
nextSyntax: nextSyntax,
|
||||
matchStack: matchStack,
|
||||
syntaxStack: syntaxStack,
|
||||
thenStack: thenStack,
|
||||
tokenCursor: tokenCursor,
|
||||
token: token,
|
||||
prev: elseStack
|
||||
};
|
||||
}
|
||||
|
||||
function addTokenToMatch() {
|
||||
matchStack = {
|
||||
type: TOKEN,
|
||||
syntax: syntax.syntax,
|
||||
token: token,
|
||||
prev: matchStack
|
||||
};
|
||||
|
||||
moveToNextToken();
|
||||
|
||||
if (tokenCursor > longestMatch) {
|
||||
longestMatch = tokenCursor;
|
||||
}
|
||||
|
||||
return matchStack.token;
|
||||
}
|
||||
|
||||
function openSyntax() {
|
||||
syntaxStack = {
|
||||
syntax: syntax,
|
||||
prev: syntaxStack
|
||||
};
|
||||
|
||||
matchStack = {
|
||||
type: OPEN_SYNTAX,
|
||||
syntax: syntax.syntax,
|
||||
token: matchStack.token,
|
||||
prev: matchStack
|
||||
};
|
||||
}
|
||||
|
||||
function closeSyntax() {
|
||||
if (matchStack.type === OPEN_SYNTAX) {
|
||||
matchStack = matchStack.prev;
|
||||
} else {
|
||||
matchStack = {
|
||||
type: CLOSE_SYNTAX,
|
||||
syntax: syntaxStack.syntax,
|
||||
token: matchStack.token,
|
||||
prev: matchStack
|
||||
};
|
||||
}
|
||||
|
||||
syntaxStack = syntaxStack.prev;
|
||||
}
|
||||
|
||||
var syntaxStack = null;
|
||||
var thenStack = null;
|
||||
var elseStack = null;
|
||||
|
||||
var iterationCount = 0;
|
||||
var exitReason = EXIT_REASON_MATCH;
|
||||
|
||||
var matchStack = { type: 'Stub', syntax: null, token: null, tokenCursor: -1, prev: null };
|
||||
var longestMatch = 0;
|
||||
var tokenCursor = -1;
|
||||
var token = null;
|
||||
|
||||
moveToNextToken();
|
||||
|
||||
while (true) {
|
||||
// console.log('--\n',
|
||||
// '#' + iterationCount,
|
||||
// require('util').inspect({
|
||||
// match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? x.type + '!' + x.syntax.name : null),
|
||||
// elseStack: mapList(elseStack, x => x.id),
|
||||
// thenStack: mapList(thenStack, x => x.id),
|
||||
// token: token && token.value,
|
||||
// tokenCursor,
|
||||
// syntax
|
||||
// }, { depth: null })
|
||||
// );
|
||||
|
||||
// prevent infinite loop
|
||||
if (++iterationCount === ITERATION_LIMIT) {
|
||||
console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT + ' iterations');
|
||||
exitReason = EXIT_REASON_ITERATION_LIMIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (syntax === MATCH) {
|
||||
if (thenStack === null) {
|
||||
// turn to MISMATCH when some tokens left unmatched
|
||||
if (token !== null) {
|
||||
// doesn't mismatch if just one token left and it's an IE hack
|
||||
if (tokenCursor !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) {
|
||||
syntax = MISMATCH;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// break the main loop, return a result - MATCH
|
||||
exitReason = EXIT_REASON_MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
// go to next syntax (`then` branch)
|
||||
syntax = thenStack.nextSyntax;
|
||||
|
||||
// check match is not empty
|
||||
if (syntax === DISALLOW_EMPTY) {
|
||||
if (thenStack.matchStack.token === matchStack.token) {
|
||||
syntax = MISMATCH;
|
||||
continue;
|
||||
} else {
|
||||
syntax = MATCH;
|
||||
}
|
||||
}
|
||||
|
||||
// close syntax if needed
|
||||
while (syntaxStack !== null && thenStack.syntaxStack !== syntaxStack) {
|
||||
closeSyntax();
|
||||
}
|
||||
|
||||
// pop stack
|
||||
thenStack = thenStack.prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (syntax === MISMATCH) {
|
||||
if (elseStack === null) {
|
||||
// break the main loop, return a result - MISMATCH
|
||||
exitReason = EXIT_REASON_MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
// go to next syntax (`else` branch)
|
||||
syntax = elseStack.nextSyntax;
|
||||
|
||||
// restore all the rest stack states
|
||||
thenStack = elseStack.thenStack;
|
||||
syntaxStack = elseStack.syntaxStack;
|
||||
matchStack = elseStack.matchStack;
|
||||
tokenCursor = elseStack.tokenCursor;
|
||||
token = elseStack.token;
|
||||
|
||||
// pop stack
|
||||
elseStack = elseStack.prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (syntax.type) {
|
||||
case 'MatchGraph':
|
||||
syntax = syntax.match;
|
||||
break;
|
||||
|
||||
case 'If':
|
||||
// IMPORTANT: else stack push must go first,
|
||||
// since it stores the state of thenStack before changes
|
||||
if (syntax.else !== MISMATCH) {
|
||||
pushElseStack(syntax.else);
|
||||
}
|
||||
|
||||
if (syntax.then !== MATCH) {
|
||||
pushThenStack(syntax.then);
|
||||
}
|
||||
|
||||
syntax = syntax.match;
|
||||
break;
|
||||
|
||||
case 'MatchOnce':
|
||||
syntax = {
|
||||
type: 'MatchOnceBuffer',
|
||||
terms: syntax.terms,
|
||||
all: syntax.all,
|
||||
matchStack: matchStack,
|
||||
index: 0,
|
||||
mask: 0
|
||||
};
|
||||
break;
|
||||
|
||||
case 'MatchOnceBuffer':
|
||||
if (syntax.index === syntax.terms.length) {
|
||||
// if no matches during a cycle
|
||||
if (syntax.matchStack === matchStack) {
|
||||
// no matches at all or it's required all terms to be matched
|
||||
if (syntax.mask === 0 || syntax.all) {
|
||||
syntax = MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
// a partial match is ok
|
||||
syntax = MATCH;
|
||||
break;
|
||||
} else {
|
||||
// start trying to match from the start
|
||||
syntax.index = 0;
|
||||
syntax.matchStack = matchStack;
|
||||
}
|
||||
}
|
||||
|
||||
for (; syntax.index < syntax.terms.length; syntax.index++) {
|
||||
if ((syntax.mask & (1 << syntax.index)) === 0) {
|
||||
// IMPORTANT: else stack push must go first,
|
||||
// since it stores the state of thenStack before changes
|
||||
pushElseStack(syntax);
|
||||
pushThenStack({
|
||||
type: 'AddMatchOnce',
|
||||
buffer: syntax
|
||||
});
|
||||
|
||||
// match
|
||||
syntax = syntax.terms[syntax.index++];
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'AddMatchOnce':
|
||||
syntax = syntax.buffer;
|
||||
|
||||
var newMask = syntax.mask | (1 << (syntax.index - 1));
|
||||
|
||||
// all terms are matched
|
||||
if (newMask === (1 << syntax.terms.length) - 1) {
|
||||
syntax = MATCH;
|
||||
continue;
|
||||
}
|
||||
|
||||
syntax = {
|
||||
type: 'MatchOnceBuffer',
|
||||
terms: syntax.terms,
|
||||
all: syntax.all,
|
||||
matchStack: syntax.matchStack,
|
||||
index: syntax.index,
|
||||
mask: newMask
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
case 'Enum':
|
||||
var name = token !== null ? token.value.toLowerCase() : '';
|
||||
|
||||
// drop \0 and \9 hack from keyword name
|
||||
if (name.indexOf('\\') !== -1) {
|
||||
name = name.replace(/\\[09].*$/, '');
|
||||
}
|
||||
|
||||
if (hasOwnProperty.call(syntax.map, name)) {
|
||||
syntax = syntax.map[name];
|
||||
} else {
|
||||
syntax = MISMATCH;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'Generic':
|
||||
syntax = syntax.fn(token, addTokenToMatch, getNextToken) ? MATCH : MISMATCH;
|
||||
break;
|
||||
|
||||
case 'Type':
|
||||
case 'Property':
|
||||
openSyntax();
|
||||
|
||||
var syntaxDict = syntax.type === 'Type' ? 'types' : 'properties';
|
||||
|
||||
if (hasOwnProperty.call(syntaxes, syntaxDict) && syntaxes[syntaxDict][syntax.name]) {
|
||||
syntax = syntaxes[syntaxDict][syntax.name].match;
|
||||
} else {
|
||||
syntax = undefined;
|
||||
}
|
||||
|
||||
if (!syntax) {
|
||||
throw new Error(
|
||||
'Bad syntax reference: ' +
|
||||
(syntaxStack.syntax.type === 'Type'
|
||||
? '<' + syntaxStack.syntax.name + '>'
|
||||
: '<\'' + syntaxStack.syntax.name + '\'>')
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'Keyword':
|
||||
var name = syntax.name;
|
||||
|
||||
if (token !== null) {
|
||||
var keywordName = token.value;
|
||||
|
||||
// drop \0 and \9 hack from keyword name
|
||||
if (keywordName.indexOf('\\') !== -1) {
|
||||
keywordName = keywordName.replace(/\\[09].*$/, '');
|
||||
}
|
||||
|
||||
if (keywordName.toLowerCase() === name) {
|
||||
addTokenToMatch();
|
||||
|
||||
syntax = MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
syntax = MISMATCH;
|
||||
break;
|
||||
|
||||
case 'AtKeyword':
|
||||
case 'Function':
|
||||
if (token !== null && token.value.toLowerCase() === syntax.name) {
|
||||
addTokenToMatch();
|
||||
|
||||
syntax = MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
syntax = MISMATCH;
|
||||
break;
|
||||
|
||||
case 'Token':
|
||||
if (token !== null && token.value === syntax.value) {
|
||||
addTokenToMatch();
|
||||
|
||||
syntax = MATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
syntax = MISMATCH;
|
||||
break;
|
||||
|
||||
case 'Comma':
|
||||
if (token !== null && token.value === ',') {
|
||||
if (isCommaContextStart(matchStack.token)) {
|
||||
syntax = MISMATCH;
|
||||
} else {
|
||||
addTokenToMatch();
|
||||
syntax = isCommaContextEnd(token) ? MISMATCH : MATCH;
|
||||
}
|
||||
} else {
|
||||
syntax = isCommaContextStart(matchStack.token) || isCommaContextEnd(token) ? MATCH : MISMATCH;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// case 'String':
|
||||
// TODO: strings with length other than 1 char
|
||||
|
||||
default:
|
||||
throw new Error('Unknown node type: ' + syntax.type);
|
||||
}
|
||||
}
|
||||
|
||||
totalIterationCount += iterationCount;
|
||||
|
||||
if (exitReason === EXIT_REASON_MATCH) {
|
||||
while (syntaxStack !== null) {
|
||||
closeSyntax();
|
||||
}
|
||||
} else {
|
||||
matchStack = null;
|
||||
}
|
||||
|
||||
return {
|
||||
tokens: tokens,
|
||||
reason: exitReason,
|
||||
iterations: iterationCount,
|
||||
match: matchStack,
|
||||
longestMatch: longestMatch
|
||||
};
|
||||
}
|
||||
|
||||
function matchAsList(tokens, matchGraph, syntaxes) {
|
||||
var matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
|
||||
|
||||
if (matchResult.match !== null) {
|
||||
matchResult.match = mapList(matchResult.match, function(item) {
|
||||
if (item.type === OPEN_SYNTAX || item.type === CLOSE_SYNTAX) {
|
||||
return { type: item.type, syntax: item.syntax };
|
||||
}
|
||||
|
||||
return {
|
||||
syntax: item.syntax,
|
||||
token: item.token && item.token.value,
|
||||
node: item.token && item.token.node
|
||||
};
|
||||
}).slice(1);
|
||||
}
|
||||
|
||||
return matchResult;
|
||||
}
|
||||
|
||||
function matchAsTree(tokens, matchGraph, syntaxes) {
|
||||
var matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
|
||||
|
||||
if (matchResult.match === null) {
|
||||
return matchResult;
|
||||
}
|
||||
|
||||
var cursor = matchResult.match;
|
||||
var host = matchResult.match = {
|
||||
syntax: matchGraph.syntax || null,
|
||||
match: []
|
||||
};
|
||||
var stack = [host];
|
||||
|
||||
// revert a list
|
||||
var prev = null;
|
||||
var next = null;
|
||||
while (cursor !== null) {
|
||||
next = cursor.prev;
|
||||
cursor.prev = prev;
|
||||
prev = cursor;
|
||||
cursor = next;
|
||||
}
|
||||
|
||||
// init the cursor to start with 2nd item since 1st is a stub item
|
||||
cursor = prev.prev;
|
||||
|
||||
// build a tree
|
||||
while (cursor !== null && cursor.syntax !== null) {
|
||||
var entry = cursor;
|
||||
|
||||
switch (entry.type) {
|
||||
case OPEN_SYNTAX:
|
||||
host.match.push(host = {
|
||||
syntax: entry.syntax,
|
||||
match: []
|
||||
});
|
||||
stack.push(host);
|
||||
break;
|
||||
|
||||
case CLOSE_SYNTAX:
|
||||
stack.pop();
|
||||
host = stack[stack.length - 1];
|
||||
break;
|
||||
|
||||
default:
|
||||
host.match.push({
|
||||
syntax: entry.syntax || null,
|
||||
token: entry.token.value,
|
||||
node: entry.token.node
|
||||
});
|
||||
}
|
||||
|
||||
cursor = cursor.prev;
|
||||
}
|
||||
|
||||
return matchResult;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
matchAsList: matchAsList,
|
||||
matchAsTree: matchAsTree,
|
||||
getTotalIterationCount: function() {
|
||||
return totalIterationCount;
|
||||
}
|
||||
};
|
||||
65
node_modules/csso/node_modules/css-tree/lib/lexer/search.js
generated
vendored
Normal file
65
node_modules/csso/node_modules/css-tree/lib/lexer/search.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
var List = require('../utils/list');
|
||||
|
||||
function getFirstMatchNode(matchNode) {
|
||||
if ('node' in matchNode) {
|
||||
return matchNode.node;
|
||||
}
|
||||
|
||||
return getFirstMatchNode(matchNode.match[0]);
|
||||
}
|
||||
|
||||
function getLastMatchNode(matchNode) {
|
||||
if ('node' in matchNode) {
|
||||
return matchNode.node;
|
||||
}
|
||||
|
||||
return getLastMatchNode(matchNode.match[matchNode.match.length - 1]);
|
||||
}
|
||||
|
||||
function matchFragments(lexer, ast, match, type, name) {
|
||||
function findFragments(matchNode) {
|
||||
if (matchNode.syntax !== null &&
|
||||
matchNode.syntax.type === type &&
|
||||
matchNode.syntax.name === name) {
|
||||
var start = getFirstMatchNode(matchNode);
|
||||
var end = getLastMatchNode(matchNode);
|
||||
|
||||
lexer.syntax.walk(ast, function(node, item, list) {
|
||||
if (node === start) {
|
||||
var nodes = new List();
|
||||
|
||||
do {
|
||||
nodes.appendData(item.data);
|
||||
|
||||
if (item.data === end) {
|
||||
break;
|
||||
}
|
||||
|
||||
item = item.next;
|
||||
} while (item !== null);
|
||||
|
||||
fragments.push({
|
||||
parent: list,
|
||||
nodes: nodes
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Array.isArray(matchNode.match)) {
|
||||
matchNode.match.forEach(findFragments);
|
||||
}
|
||||
}
|
||||
|
||||
var fragments = [];
|
||||
|
||||
if (match.matched !== null) {
|
||||
findFragments(match.matched);
|
||||
}
|
||||
|
||||
return fragments;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
matchFragments: matchFragments
|
||||
};
|
||||
163
node_modules/csso/node_modules/css-tree/lib/lexer/structure.js
generated
vendored
Normal file
163
node_modules/csso/node_modules/css-tree/lib/lexer/structure.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
var List = require('../utils/list');
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
function isValidNumber(value) {
|
||||
// Number.isInteger(value) && value >= 0
|
||||
return (
|
||||
typeof value === 'number' &&
|
||||
isFinite(value) &&
|
||||
Math.floor(value) === value &&
|
||||
value >= 0
|
||||
);
|
||||
}
|
||||
|
||||
function isValidLocation(loc) {
|
||||
return (
|
||||
Boolean(loc) &&
|
||||
isValidNumber(loc.offset) &&
|
||||
isValidNumber(loc.line) &&
|
||||
isValidNumber(loc.column)
|
||||
);
|
||||
}
|
||||
|
||||
function createNodeStructureChecker(type, fields) {
|
||||
return function checkNode(node, warn) {
|
||||
if (!node || node.constructor !== Object) {
|
||||
return warn(node, 'Type of node should be an Object');
|
||||
}
|
||||
|
||||
for (var key in node) {
|
||||
var valid = true;
|
||||
|
||||
if (hasOwnProperty.call(node, key) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === 'type') {
|
||||
if (node.type !== type) {
|
||||
warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
|
||||
}
|
||||
} else if (key === 'loc') {
|
||||
if (node.loc === null) {
|
||||
continue;
|
||||
} else if (node.loc && node.loc.constructor === Object) {
|
||||
if (typeof node.loc.source !== 'string') {
|
||||
key += '.source';
|
||||
} else if (!isValidLocation(node.loc.start)) {
|
||||
key += '.start';
|
||||
} else if (!isValidLocation(node.loc.end)) {
|
||||
key += '.end';
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
valid = false;
|
||||
} else if (fields.hasOwnProperty(key)) {
|
||||
for (var i = 0, valid = false; !valid && i < fields[key].length; i++) {
|
||||
var fieldType = fields[key][i];
|
||||
|
||||
switch (fieldType) {
|
||||
case String:
|
||||
valid = typeof node[key] === 'string';
|
||||
break;
|
||||
|
||||
case Boolean:
|
||||
valid = typeof node[key] === 'boolean';
|
||||
break;
|
||||
|
||||
case null:
|
||||
valid = node[key] === null;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (typeof fieldType === 'string') {
|
||||
valid = node[key] && node[key].type === fieldType;
|
||||
} else if (Array.isArray(fieldType)) {
|
||||
valid = node[key] instanceof List;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
warn(node, 'Bad value for `' + type + '.' + key + '`');
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in fields) {
|
||||
if (hasOwnProperty.call(fields, key) &&
|
||||
hasOwnProperty.call(node, key) === false) {
|
||||
warn(node, 'Field `' + type + '.' + key + '` is missed');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function processStructure(name, nodeType) {
|
||||
var structure = nodeType.structure;
|
||||
var fields = {
|
||||
type: String,
|
||||
loc: true
|
||||
};
|
||||
var docs = {
|
||||
type: '"' + name + '"'
|
||||
};
|
||||
|
||||
for (var key in structure) {
|
||||
if (hasOwnProperty.call(structure, key) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var docsTypes = [];
|
||||
var fieldTypes = fields[key] = Array.isArray(structure[key])
|
||||
? structure[key].slice()
|
||||
: [structure[key]];
|
||||
|
||||
for (var i = 0; i < fieldTypes.length; i++) {
|
||||
var fieldType = fieldTypes[i];
|
||||
if (fieldType === String || fieldType === Boolean) {
|
||||
docsTypes.push(fieldType.name);
|
||||
} else if (fieldType === null) {
|
||||
docsTypes.push('null');
|
||||
} else if (typeof fieldType === 'string') {
|
||||
docsTypes.push('<' + fieldType + '>');
|
||||
} else if (Array.isArray(fieldType)) {
|
||||
docsTypes.push('List'); // TODO: use type enum
|
||||
} else {
|
||||
throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
|
||||
}
|
||||
}
|
||||
|
||||
docs[key] = docsTypes.join(' | ');
|
||||
}
|
||||
|
||||
return {
|
||||
docs: docs,
|
||||
check: createNodeStructureChecker(name, fields)
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getStructureFromConfig: function(config) {
|
||||
var structure = {};
|
||||
|
||||
if (config.node) {
|
||||
for (var name in config.node) {
|
||||
if (hasOwnProperty.call(config.node, name)) {
|
||||
var nodeType = config.node[name];
|
||||
|
||||
if (nodeType.structure) {
|
||||
structure[name] = processStructure(name, nodeType);
|
||||
} else {
|
||||
throw new Error('Missed `structure` field in `' + name + '` node type definition');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return structure;
|
||||
}
|
||||
};
|
||||
79
node_modules/csso/node_modules/css-tree/lib/lexer/trace.js
generated
vendored
Normal file
79
node_modules/csso/node_modules/css-tree/lib/lexer/trace.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
function getTrace(node) {
|
||||
function shouldPutToTrace(syntax) {
|
||||
if (syntax === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
syntax.type === 'Type' ||
|
||||
syntax.type === 'Property' ||
|
||||
syntax.type === 'Keyword'
|
||||
);
|
||||
}
|
||||
|
||||
function hasMatch(matchNode) {
|
||||
if (Array.isArray(matchNode.match)) {
|
||||
// use for-loop for better perfomance
|
||||
for (var i = 0; i < matchNode.match.length; i++) {
|
||||
if (hasMatch(matchNode.match[i])) {
|
||||
if (shouldPutToTrace(matchNode.syntax)) {
|
||||
result.unshift(matchNode.syntax);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (matchNode.node === node) {
|
||||
result = shouldPutToTrace(matchNode.syntax)
|
||||
? [matchNode.syntax]
|
||||
: [];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = null;
|
||||
|
||||
if (this.matched !== null) {
|
||||
hasMatch(this.matched);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function testNode(match, node, fn) {
|
||||
var trace = getTrace.call(match, node);
|
||||
|
||||
if (trace === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return trace.some(fn);
|
||||
}
|
||||
|
||||
function isType(node, type) {
|
||||
return testNode(this, node, function(matchNode) {
|
||||
return matchNode.type === 'Type' && matchNode.name === type;
|
||||
});
|
||||
}
|
||||
|
||||
function isProperty(node, property) {
|
||||
return testNode(this, node, function(matchNode) {
|
||||
return matchNode.type === 'Property' && matchNode.name === property;
|
||||
});
|
||||
}
|
||||
|
||||
function isKeyword(node) {
|
||||
return testNode(this, node, function(matchNode) {
|
||||
return matchNode.type === 'Keyword';
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getTrace: getTrace,
|
||||
isType: isType,
|
||||
isProperty: isProperty,
|
||||
isKeyword: isKeyword
|
||||
};
|
||||
177
node_modules/csso/node_modules/css-tree/lib/parser/create.js
generated
vendored
Normal file
177
node_modules/csso/node_modules/css-tree/lib/parser/create.js
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
'use strict';
|
||||
|
||||
var Tokenizer = require('../tokenizer');
|
||||
var List = require('../utils/list');
|
||||
var sequence = require('./sequence');
|
||||
var noop = function() {};
|
||||
|
||||
function createParseContext(name) {
|
||||
return function() {
|
||||
return this[name]();
|
||||
};
|
||||
}
|
||||
|
||||
function processConfig(config) {
|
||||
var parserConfig = {
|
||||
context: {},
|
||||
scope: {},
|
||||
atrule: {},
|
||||
pseudo: {}
|
||||
};
|
||||
|
||||
if (config.parseContext) {
|
||||
for (var name in config.parseContext) {
|
||||
switch (typeof config.parseContext[name]) {
|
||||
case 'function':
|
||||
parserConfig.context[name] = config.parseContext[name];
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
parserConfig.context[name] = createParseContext(config.parseContext[name]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.scope) {
|
||||
for (var name in config.scope) {
|
||||
parserConfig.scope[name] = config.scope[name];
|
||||
}
|
||||
}
|
||||
|
||||
if (config.atrule) {
|
||||
for (var name in config.atrule) {
|
||||
var atrule = config.atrule[name];
|
||||
|
||||
if (atrule.parse) {
|
||||
parserConfig.atrule[name] = atrule.parse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.pseudo) {
|
||||
for (var name in config.pseudo) {
|
||||
var pseudo = config.pseudo[name];
|
||||
|
||||
if (pseudo.parse) {
|
||||
parserConfig.pseudo[name] = pseudo.parse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (config.node) {
|
||||
for (var name in config.node) {
|
||||
parserConfig[name] = config.node[name].parse;
|
||||
}
|
||||
}
|
||||
|
||||
return parserConfig;
|
||||
}
|
||||
|
||||
module.exports = function createParser(config) {
|
||||
var parser = {
|
||||
scanner: new Tokenizer(),
|
||||
filename: '<unknown>',
|
||||
needPositions: false,
|
||||
onParseError: noop,
|
||||
onParseErrorThrow: false,
|
||||
parseAtrulePrelude: true,
|
||||
parseRulePrelude: true,
|
||||
parseValue: true,
|
||||
parseCustomProperty: false,
|
||||
|
||||
readSequence: sequence,
|
||||
|
||||
createList: function() {
|
||||
return new List();
|
||||
},
|
||||
createSingleNodeList: function(node) {
|
||||
return new List().appendData(node);
|
||||
},
|
||||
getFirstListNode: function(list) {
|
||||
return list && list.first();
|
||||
},
|
||||
getLastListNode: function(list) {
|
||||
return list.last();
|
||||
},
|
||||
|
||||
parseWithFallback: function(consumer, fallback) {
|
||||
var startToken = this.scanner.currentToken;
|
||||
|
||||
try {
|
||||
return consumer.call(this);
|
||||
} catch (e) {
|
||||
if (this.onParseErrorThrow) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
var fallbackNode = fallback.call(this, startToken);
|
||||
|
||||
this.onParseErrorThrow = true;
|
||||
this.onParseError(e, fallbackNode);
|
||||
this.onParseErrorThrow = false;
|
||||
|
||||
return fallbackNode;
|
||||
}
|
||||
},
|
||||
|
||||
getLocation: function(start, end) {
|
||||
if (this.needPositions) {
|
||||
return this.scanner.getLocationRange(
|
||||
start,
|
||||
end,
|
||||
this.filename
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
getLocationFromList: function(list) {
|
||||
if (this.needPositions) {
|
||||
var head = this.getFirstListNode(list);
|
||||
var tail = this.getLastListNode(list);
|
||||
return this.scanner.getLocationRange(
|
||||
head !== null ? head.loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
|
||||
tail !== null ? tail.loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
|
||||
this.filename
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
config = processConfig(config || {});
|
||||
for (var key in config) {
|
||||
parser[key] = config[key];
|
||||
}
|
||||
|
||||
return function(source, options) {
|
||||
options = options || {};
|
||||
|
||||
var context = options.context || 'default';
|
||||
var ast;
|
||||
|
||||
parser.scanner.setSource(source, options.offset, options.line, options.column);
|
||||
parser.filename = options.filename || '<unknown>';
|
||||
parser.needPositions = Boolean(options.positions);
|
||||
parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop;
|
||||
parser.onParseErrorThrow = false;
|
||||
parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true;
|
||||
parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true;
|
||||
parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
|
||||
parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
|
||||
|
||||
if (!parser.context.hasOwnProperty(context)) {
|
||||
throw new Error('Unknown context `' + context + '`');
|
||||
}
|
||||
|
||||
ast = parser.context[context].call(parser, options);
|
||||
|
||||
if (!parser.scanner.eof) {
|
||||
parser.scanner.error();
|
||||
}
|
||||
|
||||
return ast;
|
||||
};
|
||||
};
|
||||
4
node_modules/csso/node_modules/css-tree/lib/parser/index.js
generated
vendored
Normal file
4
node_modules/csso/node_modules/css-tree/lib/parser/index.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
var createParser = require('./create');
|
||||
var config = require('../syntax/config/parser');
|
||||
|
||||
module.exports = createParser(config);
|
||||
54
node_modules/csso/node_modules/css-tree/lib/parser/sequence.js
generated
vendored
Normal file
54
node_modules/csso/node_modules/css-tree/lib/parser/sequence.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
var TYPE = require('../tokenizer').TYPE;
|
||||
var WHITESPACE = TYPE.WhiteSpace;
|
||||
var COMMENT = TYPE.Comment;
|
||||
|
||||
module.exports = function readSequence(recognizer) {
|
||||
var children = this.createList();
|
||||
var child = null;
|
||||
var context = {
|
||||
recognizer: recognizer,
|
||||
space: null,
|
||||
ignoreWS: false,
|
||||
ignoreWSAfter: false
|
||||
};
|
||||
|
||||
this.scanner.skipSC();
|
||||
|
||||
while (!this.scanner.eof) {
|
||||
switch (this.scanner.tokenType) {
|
||||
case COMMENT:
|
||||
this.scanner.next();
|
||||
continue;
|
||||
|
||||
case WHITESPACE:
|
||||
if (context.ignoreWS) {
|
||||
this.scanner.next();
|
||||
} else {
|
||||
context.space = this.WhiteSpace();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
child = recognizer.getNode.call(this, context);
|
||||
|
||||
if (child === undefined) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (context.space !== null) {
|
||||
children.push(context.space);
|
||||
context.space = null;
|
||||
}
|
||||
|
||||
children.push(child);
|
||||
|
||||
if (context.ignoreWSAfter) {
|
||||
context.ignoreWSAfter = false;
|
||||
context.ignoreWS = true;
|
||||
} else {
|
||||
context.ignoreWS = false;
|
||||
}
|
||||
}
|
||||
|
||||
return children;
|
||||
};
|
||||
8
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/font-face.js
generated
vendored
Normal file
8
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/font-face.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
parse: {
|
||||
prelude: null,
|
||||
block: function() {
|
||||
return this.Block(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
38
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/import.js
generated
vendored
Normal file
38
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/import.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
var TYPE = require('../../tokenizer').TYPE;
|
||||
|
||||
var STRING = TYPE.String;
|
||||
var IDENTIFIER = TYPE.Identifier;
|
||||
var URL = TYPE.Url;
|
||||
var LEFTPARENTHESIS = TYPE.LeftParenthesis;
|
||||
|
||||
module.exports = {
|
||||
parse: {
|
||||
prelude: function() {
|
||||
var children = this.createList();
|
||||
|
||||
this.scanner.skipSC();
|
||||
|
||||
switch (this.scanner.tokenType) {
|
||||
case STRING:
|
||||
children.push(this.String());
|
||||
break;
|
||||
|
||||
case URL:
|
||||
children.push(this.Url());
|
||||
break;
|
||||
|
||||
default:
|
||||
this.scanner.error('String or url() is expected');
|
||||
}
|
||||
|
||||
if (this.scanner.lookupNonWSType(0) === IDENTIFIER ||
|
||||
this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS) {
|
||||
children.push(this.WhiteSpace());
|
||||
children.push(this.MediaQueryList());
|
||||
}
|
||||
|
||||
return children;
|
||||
},
|
||||
block: null
|
||||
}
|
||||
};
|
||||
7
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/index.js
generated
vendored
Normal file
7
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/index.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
'font-face': require('./font-face'),
|
||||
'import': require('./import'),
|
||||
'media': require('./media'),
|
||||
'page': require('./page'),
|
||||
'supports': require('./supports')
|
||||
};
|
||||
12
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/media.js
generated
vendored
Normal file
12
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/media.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
parse: {
|
||||
prelude: function() {
|
||||
return this.createSingleNodeList(
|
||||
this.MediaQueryList()
|
||||
);
|
||||
},
|
||||
block: function() {
|
||||
return this.Block(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
12
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/page.js
generated
vendored
Normal file
12
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/page.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
parse: {
|
||||
prelude: function() {
|
||||
return this.createSingleNodeList(
|
||||
this.SelectorList()
|
||||
);
|
||||
},
|
||||
block: function() {
|
||||
return this.Block(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
99
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/supports.js
generated
vendored
Normal file
99
node_modules/csso/node_modules/css-tree/lib/syntax/atrule/supports.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
var TYPE = require('../../tokenizer').TYPE;
|
||||
|
||||
var WHITESPACE = TYPE.WhiteSpace;
|
||||
var COMMENT = TYPE.Comment;
|
||||
var IDENTIFIER = TYPE.Identifier;
|
||||
var FUNCTION = TYPE.Function;
|
||||
var LEFTPARENTHESIS = TYPE.LeftParenthesis;
|
||||
var HYPHENMINUS = TYPE.HyphenMinus;
|
||||
var COLON = TYPE.Colon;
|
||||
|
||||
function consumeRaw() {
|
||||
return this.createSingleNodeList(
|
||||
this.Raw(this.scanner.currentToken, 0, 0, false, false)
|
||||
);
|
||||
}
|
||||
|
||||
function parentheses() {
|
||||
var index = 0;
|
||||
|
||||
this.scanner.skipSC();
|
||||
|
||||
// TODO: make it simplier
|
||||
if (this.scanner.tokenType === IDENTIFIER) {
|
||||
index = 1;
|
||||
} else if (this.scanner.tokenType === HYPHENMINUS &&
|
||||
this.scanner.lookupType(1) === IDENTIFIER) {
|
||||
index = 2;
|
||||
}
|
||||
|
||||
if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON) {
|
||||
return this.createSingleNodeList(
|
||||
this.Declaration()
|
||||
);
|
||||
}
|
||||
|
||||
return readSequence.call(this);
|
||||
}
|
||||
|
||||
function readSequence() {
|
||||
var children = this.createList();
|
||||
var space = null;
|
||||
var child;
|
||||
|
||||
this.scanner.skipSC();
|
||||
|
||||
scan:
|
||||
while (!this.scanner.eof) {
|
||||
switch (this.scanner.tokenType) {
|
||||
case WHITESPACE:
|
||||
space = this.WhiteSpace();
|
||||
continue;
|
||||
|
||||
case COMMENT:
|
||||
this.scanner.next();
|
||||
continue;
|
||||
|
||||
case FUNCTION:
|
||||
child = this.Function(consumeRaw, this.scope.AtrulePrelude);
|
||||
break;
|
||||
|
||||
case IDENTIFIER:
|
||||
child = this.Identifier();
|
||||
break;
|
||||
|
||||
case LEFTPARENTHESIS:
|
||||
child = this.Parentheses(parentheses, this.scope.AtrulePrelude);
|
||||
break;
|
||||
|
||||
default:
|
||||
break scan;
|
||||
}
|
||||
|
||||
if (space !== null) {
|
||||
children.push(space);
|
||||
space = null;
|
||||
}
|
||||
|
||||
children.push(child);
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parse: {
|
||||
prelude: function() {
|
||||
var children = readSequence.call(this);
|
||||
|
||||
if (this.getFirstListNode(children) === null) {
|
||||
this.scanner.error('Condition is expected');
|
||||
}
|
||||
|
||||
return children;
|
||||
},
|
||||
block: function() {
|
||||
return this.Block(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
8
node_modules/csso/node_modules/css-tree/lib/syntax/config/lexer.js
generated
vendored
Normal file
8
node_modules/csso/node_modules/css-tree/lib/syntax/config/lexer.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
var data = require('../../../data');
|
||||
|
||||
module.exports = {
|
||||
generic: true,
|
||||
types: data.types,
|
||||
properties: data.properties,
|
||||
node: require('../node')
|
||||
};
|
||||
94
node_modules/csso/node_modules/css-tree/lib/syntax/config/mix.js
generated
vendored
Normal file
94
node_modules/csso/node_modules/css-tree/lib/syntax/config/mix.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
var shape = {
|
||||
generic: true,
|
||||
types: {},
|
||||
properties: {},
|
||||
parseContext: {},
|
||||
scope: {},
|
||||
atrule: ['parse'],
|
||||
pseudo: ['parse'],
|
||||
node: ['name', 'structure', 'parse', 'generate', 'walkContext']
|
||||
};
|
||||
|
||||
function isObject(value) {
|
||||
return value && value.constructor === Object;
|
||||
}
|
||||
|
||||
function copy(value) {
|
||||
if (isObject(value)) {
|
||||
var res = {};
|
||||
for (var key in value) {
|
||||
if (hasOwnProperty.call(value, key)) {
|
||||
res[key] = value[key];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function extend(dest, src) {
|
||||
for (var key in src) {
|
||||
if (hasOwnProperty.call(src, key)) {
|
||||
if (isObject(dest[key])) {
|
||||
extend(dest[key], copy(src[key]));
|
||||
} else {
|
||||
dest[key] = copy(src[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mix(dest, src, shape) {
|
||||
for (var key in shape) {
|
||||
if (hasOwnProperty.call(shape, key) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shape[key] === true) {
|
||||
if (key in src) {
|
||||
if (hasOwnProperty.call(src, key)) {
|
||||
dest[key] = copy(src[key]);
|
||||
}
|
||||
}
|
||||
} else if (shape[key]) {
|
||||
if (isObject(shape[key])) {
|
||||
var res = {};
|
||||
extend(res, dest[key]);
|
||||
extend(res, src[key]);
|
||||
dest[key] = res;
|
||||
} else if (Array.isArray(shape[key])) {
|
||||
var res = {};
|
||||
var innerShape = shape[key].reduce(function(s, k) {
|
||||
s[k] = true;
|
||||
return s;
|
||||
}, {});
|
||||
for (var name in dest[key]) {
|
||||
if (hasOwnProperty.call(dest[key], name)) {
|
||||
res[name] = {};
|
||||
if (dest[key] && dest[key][name]) {
|
||||
mix(res[name], dest[key][name], innerShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var name in src[key]) {
|
||||
if (hasOwnProperty.call(src[key], name)) {
|
||||
if (!res[name]) {
|
||||
res[name] = {};
|
||||
}
|
||||
if (src[key] && src[key][name]) {
|
||||
mix(res[name], src[key][name], innerShape);
|
||||
}
|
||||
}
|
||||
}
|
||||
dest[key] = res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
module.exports = function(dest, src) {
|
||||
return mix(dest, src, shape);
|
||||
};
|
||||
25
node_modules/csso/node_modules/css-tree/lib/syntax/config/parser.js
generated
vendored
Normal file
25
node_modules/csso/node_modules/css-tree/lib/syntax/config/parser.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
module.exports = {
|
||||
parseContext: {
|
||||
default: 'StyleSheet',
|
||||
stylesheet: 'StyleSheet',
|
||||
atrule: 'Atrule',
|
||||
atrulePrelude: function(options) {
|
||||
return this.AtrulePrelude(options.atrule ? String(options.atrule) : null);
|
||||
},
|
||||
mediaQueryList: 'MediaQueryList',
|
||||
mediaQuery: 'MediaQuery',
|
||||
rule: 'Rule',
|
||||
selectorList: 'SelectorList',
|
||||
selector: 'Selector',
|
||||
block: function() {
|
||||
return this.Block(true);
|
||||
},
|
||||
declarationList: 'DeclarationList',
|
||||
declaration: 'Declaration',
|
||||
value: 'Value'
|
||||
},
|
||||
scope: require('../scope'),
|
||||
atrule: require('../atrule'),
|
||||
pseudo: require('../pseudo'),
|
||||
node: require('../node')
|
||||
};
|
||||
3
node_modules/csso/node_modules/css-tree/lib/syntax/config/walker.js
generated
vendored
Normal file
3
node_modules/csso/node_modules/css-tree/lib/syntax/config/walker.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
node: require('../node')
|
||||
};
|
||||
76
node_modules/csso/node_modules/css-tree/lib/syntax/create.js
generated
vendored
Normal file
76
node_modules/csso/node_modules/css-tree/lib/syntax/create.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
var List = require('../utils/list');
|
||||
var Tokenizer = require('../tokenizer');
|
||||
var Lexer = require('../lexer/Lexer');
|
||||
var grammar = require('../lexer/grammar');
|
||||
var createParser = require('../parser/create');
|
||||
var createGenerator = require('../generator/create');
|
||||
var createConvertor = require('../convertor/create');
|
||||
var createWalker = require('../walker/create');
|
||||
var clone = require('../utils/clone');
|
||||
var names = require('../utils/names');
|
||||
var mix = require('./config/mix');
|
||||
|
||||
function assign(dest, src) {
|
||||
for (var key in src) {
|
||||
dest[key] = src[key];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
function createSyntax(config) {
|
||||
var parse = createParser(config);
|
||||
var walk = createWalker(config);
|
||||
var generate = createGenerator(config);
|
||||
var convert = createConvertor(walk);
|
||||
|
||||
var syntax = {
|
||||
List: List,
|
||||
Tokenizer: Tokenizer,
|
||||
Lexer: Lexer,
|
||||
|
||||
vendorPrefix: names.vendorPrefix,
|
||||
keyword: names.keyword,
|
||||
property: names.property,
|
||||
isCustomProperty: names.isCustomProperty,
|
||||
|
||||
grammar: grammar,
|
||||
lexer: null,
|
||||
createLexer: function(config) {
|
||||
return new Lexer(config, syntax, syntax.lexer.structure);
|
||||
},
|
||||
|
||||
parse: parse,
|
||||
walk: walk,
|
||||
generate: generate,
|
||||
|
||||
clone: clone,
|
||||
fromPlainObject: convert.fromPlainObject,
|
||||
toPlainObject: convert.toPlainObject,
|
||||
|
||||
createSyntax: function(config) {
|
||||
return createSyntax(mix({}, config));
|
||||
},
|
||||
fork: function(extension) {
|
||||
var base = mix({}, config); // copy of config
|
||||
return createSyntax(
|
||||
typeof extension === 'function'
|
||||
? extension(base, assign)
|
||||
: mix(base, extension)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
syntax.lexer = new Lexer({
|
||||
generic: true,
|
||||
types: config.types,
|
||||
properties: config.properties,
|
||||
node: config.node
|
||||
}, syntax);
|
||||
|
||||
return syntax;
|
||||
};
|
||||
|
||||
exports.create = function(config) {
|
||||
return createSyntax(mix({}, config));
|
||||
};
|
||||
13
node_modules/csso/node_modules/css-tree/lib/syntax/function/element.js
generated
vendored
Normal file
13
node_modules/csso/node_modules/css-tree/lib/syntax/function/element.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// https://drafts.csswg.org/css-images-4/#element-notation
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/element
|
||||
module.exports = function() {
|
||||
this.scanner.skipSC();
|
||||
|
||||
var children = this.createSingleNodeList(
|
||||
this.IdSelector()
|
||||
);
|
||||
|
||||
this.scanner.skipSC();
|
||||
|
||||
return children;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user