diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 31dd6aa4..00000000 --- a/.editorconfig +++ /dev/null @@ -1,14 +0,0 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -charset = utf-8 - -[Makefile] -indent_style = tab - -[*.php] -indent_style = space -indent_size = 4 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 73d1a258..00000000 --- a/.gitattributes +++ /dev/null @@ -1,8 +0,0 @@ -Makefile export-ignore -.editorconfig export-ignore -.gitattributes export-ignore -.gitignore export-ignore -.travis.yml export-ignore -box.json.dist export-ignore -phpunit.xml.dist export-ignore -tests/ export-ignore diff --git a/.gitignore b/.gitignore index 999984a4..d199acea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,7 @@ -.idea +_site .sass-cache -scss_cache composer.lock -/*.css -/*.scss -/_site/ -/sass/ -/compass/ -/vendor/ +pscss.phar /frameworks/ +/src/ +/vendor/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ccbbf00b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: php -sudo: false - -php: - - 5.6 - - 7.0 - - 7.1 - - 7.2 - - nightly - -install: composer install - -script: - - vendor/bin/phpunit tests - -branches: - only: - - master - -matrix: - allow_failures: - - php: nightly diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..053c27dc --- /dev/null +++ b/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'github-pages' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..b89b8039 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,131 @@ +GEM + remote: https://rubygems.org/ + specs: + RedCloth (4.2.9) + activesupport (4.2.3) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + blankslate (2.1.2.4) + celluloid (0.16.0) + timers (~> 4.0.0) + classifier-reborn (2.0.3) + fast-stemmer (~> 1.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.9.1.1) + colorator (0.1) + execjs (2.5.2) + fast-stemmer (1.0.2) + ffi (1.9.10) + gemoji (2.1.0) + github-pages (38) + RedCloth (= 4.2.9) + github-pages-health-check (~> 0.2) + jekyll (= 2.4.0) + jekyll-coffeescript (= 1.0.1) + jekyll-feed (= 0.3.0) + jekyll-mentions (= 0.2.1) + jekyll-redirect-from (= 0.8.0) + jekyll-sass-converter (= 1.2.0) + jekyll-sitemap (= 0.8.1) + jemoji (= 0.4.0) + kramdown (= 1.5.0) + liquid (= 2.6.2) + maruku (= 0.7.0) + mercenary (~> 0.3) + pygments.rb (= 0.6.3) + rdiscount (= 2.1.7) + redcarpet (= 3.3.1) + terminal-table (~> 1.4) + github-pages-health-check (0.3.1) + net-dns (~> 0.6) + public_suffix (~> 1.4) + hitimes (1.2.2) + html-pipeline (1.9.0) + activesupport (>= 2) + nokogiri (~> 1.4) + i18n (0.7.0) + jekyll (2.4.0) + classifier-reborn (~> 2.0) + colorator (~> 0.1) + jekyll-coffeescript (~> 1.0) + jekyll-gist (~> 1.0) + jekyll-paginate (~> 1.0) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 1.1) + kramdown (~> 1.3) + liquid (~> 2.6.1) + mercenary (~> 0.3.3) + pygments.rb (~> 0.6.0) + redcarpet (~> 3.1) + safe_yaml (~> 1.0) + toml (~> 0.1.0) + jekyll-coffeescript (1.0.1) + coffee-script (~> 2.2) + jekyll-feed (0.3.0) + jekyll-gist (1.2.1) + jekyll-mentions (0.2.1) + html-pipeline (~> 1.9.0) + jekyll (~> 2.0) + jekyll-paginate (1.1.0) + jekyll-redirect-from (0.8.0) + jekyll (>= 2.0) + jekyll-sass-converter (1.2.0) + sass (~> 3.2) + jekyll-sitemap (0.8.1) + jekyll-watch (1.2.1) + listen (~> 2.7) + jemoji (0.4.0) + gemoji (~> 2.0) + html-pipeline (~> 1.9) + jekyll (~> 2.0) + json (1.8.3) + kramdown (1.5.0) + liquid (2.6.2) + listen (2.10.1) + celluloid (~> 0.16.0) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + maruku (0.7.0) + mercenary (0.3.5) + mini_portile (0.6.2) + minitest (5.7.0) + net-dns (0.8.0) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) + parslet (1.5.0) + blankslate (~> 2.0) + posix-spawn (0.3.11) + public_suffix (1.5.1) + pygments.rb (0.6.3) + posix-spawn (~> 0.3.6) + yajl-ruby (~> 1.2.0) + rb-fsevent (0.9.5) + rb-inotify (0.9.5) + ffi (>= 0.5.0) + rdiscount (2.1.7) + redcarpet (3.3.1) + safe_yaml (1.0.4) + sass (3.4.15) + terminal-table (1.5.2) + thread_safe (0.3.5) + timers (4.0.1) + hitimes + toml (0.1.2) + parslet (~> 1.5.0) + tzinfo (1.2.2) + thread_safe (~> 0.1) + yajl-ruby (1.2.1) + +PLATFORMS + ruby + +DEPENDENCIES + github-pages + +BUNDLED WITH + 1.10.5 diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 2f5412f9..00000000 --- a/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2015 Leaf Corcoran, http://leafo.github.io/scssphp - -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. diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 index fb50ffdb..2634e638 --- a/Makefile +++ b/Makefile @@ -1,8 +1,3 @@ -test: - vendor/bin/phpunit --colors tests - -compat: - TEST_SCSS_COMPAT=1 vendor/bin/phpunit --colors tests | tail -2 - -standard: - vendor/bin/phpcs --standard=PSR2 bin src example tests *.php +serve: + # site should be available at http://localhost:4000/scssphp + bundle exec jekyll serve diff --git a/README.md b/README.md deleted file mode 100644 index d3fbf154..00000000 --- a/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# This repo has been archived - - -#### Please go to https://github.com/scssphp/scssphp - ----- - -## scssphp - -![License](https://poser.pugx.org/leafo/scssphp/license.svg) - -`scssphp` is a compiler for SCSS written in PHP. - -### Running Tests - -`scssphp` uses [PHPUnit](https://github.com/sebastianbergmann/phpunit) for testing. - -Run the following command from the root directory to run every test: - - vendor/bin/phpunit tests - -There are several tests in the `tests/` directory: - -* `ApiTest.php` contains various unit tests that test the PHP interface. -* `ExceptionTest.php` contains unit tests that test for exceptions thrown by the parser and compiler. -* `FailingTest.php` contains tests reported in Github issues that demonstrate compatibility bugs. -* `InputTest.php` compiles every `.scss` file in the `tests/inputs` directory - then compares to the respective `.css` file in the `tests/outputs` directory. -* `ScssTest.php` extracts (ruby) `scss` tests from the `tests/scss_test.rb` file. -* `ServerTest.php` contains functional tests for the `Server` class. - -When changing any of the tests in `tests/inputs`, the tests will most likely -fail because the output has changed. Once you verify that the output is correct -you can run the following command to rebuild all the tests: - - BUILD=1 vendor/bin/phpunit tests - -This will compile all the tests, and save results into `tests/outputs`. - -To enable the `scss` compatibility tests: - - TEST_SCSS_COMPAT=1 vendor/bin/phpunit tests - -### Coding Standard - -`scssphp` source conforms to [PSR2](http://www.php-fig.org/psr/psr-2/). - -Run the following command from the root directory to check the code for "sniffs". - - vendor/bin/phpcs --standard=PSR2 bin src tests diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..ef3ffcda --- /dev/null +++ b/_config.yml @@ -0,0 +1,27 @@ +# Site settings +title: SCSS Compiler in PHP +current_version: 0.8.3 +description: > + SCSS compiler written in PHP +url: http://leafo.github.io +baseurl: /scssphp +repo_url: https://github.com/leafo/scssphp + +# Build settings +markdown: kramdown +exclude: +- Gemfile +- Gemfile.lock +- Makefile +- composer.lock +- frameworks/ +- vendor/ + +# Github Pages +ghlighter: pygments +github: [Repository metadata] +gems: +- jekyll-mentions +- jemoji +- jekyll-redirect-from +- jekyll-sitemap diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 00000000..d219a0af --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,14 @@ + + +{% assign generate_date = 'now' | date: "%a %b %d, %Y %T" %} +{% include head.html %} + + {% include header.html %} +
+
+ {{ content }} +
+
+ {% include footer.html %} + + diff --git a/_sass/_leafo.scss b/_sass/_leafo.scss new file mode 100644 index 00000000..d8ceb1a3 --- /dev/null +++ b/_sass/_leafo.scss @@ -0,0 +1,302 @@ +$site_width: 640px; + +$light_teal: #7FC7AF; +$teal: desaturate(#3FB8AF, 10%); +$brown: #DAD8A7; +$pink: darken(#FF9E9D, 10%); +$btn_color: desaturate(#FF3D7F, 10%); + +::selection { + background: red; + color: white; +} + +@mixin unselectable { + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +@mixin grad($top, $bottom) { + background-color: mix($top, $bottom); + background-image: linear-gradient(bottom, $bottom 0%, $top 100%); + background-image: -webkit-linear-gradient(bottom, $bottom 0%, $top 100%); + background-image: -moz-linear-gradient(bottom, $bottom 0%, $top 100%); + background-image: -o-linear-gradient(bottom, $bottom 0%, $top 100%); + background-image: -ms-linear-gradient(bottom, $bottom 0%, $top 100%); +} + +@mixin autograd($color, $amount: 10%) { + @include grad($color, darken($color, $amount)); +} + +body { + background: $pink; + font-family: Lato, sans-serif; +} + +.header, .footer, .body { + .inner { + width: $site_width; + margin: 0 auto; + } +} + +.header { + text-shadow: 0px -1px 0px darken($teal, 15%); + + .color { + background: $teal url(../img/tile.png); + border-top: 4px solid $light_teal; + box-shadow: inset 0px 1px 0px rgba(255,255,255, 0.5), inset 0px 8px 8px -8px #37505A, inset 0px -1px 0px rgba(255,255,255, 0.3); + } + + h1 { + font-family: 'Quicksand', sans-serif; + font-size: 40px; + line-height: 100px; + font-weight: normal; + margin: 0; + + a { + text-decoration: none; + color: #EDFFF9; + + &:active { + position: relative; + top: 1px; + } + } + } + + .nav { + padding: 8px 0; + font-size: 17px; + text-shadow: none; + background: darken($teal, 30%); + color: $teal; + box-shadow: inset 0px 4px 8px -4px rgba(0,0,0,0.9), inset 0px -1px 0px rgba(255,255,255, 0.8); + + a { + color: lighten($teal, 40%); + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + } + + .download-area { + float: right; + margin-top: 25px; + background: rgba(255,255,255, 0.3); + border-radius: 8px; + padding: 5px; + + a { + text-decoration: none; + } + + .download-button { + $height: 8px; + $depress: 4px; + + @include unselectable; + + color: white; + text-align: center; + + @include autograd($btn_color); + + position: relative; + top: -1 * $height; + + padding: 8px 20px; + border-radius: 8px; + text-shadow: none; + + box-shadow: 0px $height 0px darken($btn_color, 30%), inset 0px -1px 0px rgba(255,255,255, 0.2), inset 0px 1px 0px rgba(0,0,0, 0.2); + text-shadow: 0px 1px 2px darken($btn_color, 40%); + + cursor: pointer; + + -webkit-transition: all 0.05s ease-in-out; + -moz-transition: all 0.05s ease-in-out; + transition: all 0.05s ease-in-out; + + &:hover { + @include autograd(lighten($btn_color, 3%)); + } + + &:active { + box-shadow: 0px $height - $depress 0px darken($btn_color, 30%), inset 0px -1px 0px rgba(255,255,255, 0.2), inset 0px 1px 0px rgba(0,0,0, 0.2); + top: -1 * ($height - $depress); + } + + .top { + font-weight: bold; + font-size: 16px; + } + + .sub { + font-size: 14px; + } + } + } + +} + +.body { + $bg_color: #FEFFED; + $text_color: darken($brown, 60%); + box-shadow: inset 0px 4px 8px -4px rgba(0,0,0,0.7), inset 0px -4px 8px -4px rgba(0,0,0,0.4); + background: $bg_color; + overflow: hidden; + color: $text_color; + font-size: 18px; + padding-bottom: 20px; + + .inner { + background: white; + margin-top: 20px; + padding: 30px 50px; + border: 1px solid lightGrey; + box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.19); + + h1, h2, h3 { + margin: 0 0 20px 0; + } + } + + h1, h2, h3 { + text-shadow: 1px 1px 0px $bg_color, 2px 2px 0px rgba($text_color, 0.3); + letter-spacing: -1px; + } + + h3 { + color: #4D4C3D; + } + + p { + margin: 0 0 15px 0; + } + + a { + color: #DB1C4A; + &:hover { + color: lighten(#DB1C4A, 10%); + } + } + + pre { + margin: 20px 0; + } +} + +.footer { + font-size: 16px; + color: lighten($pink, 20%); + text-shadow: 0px 1px 0px darken($pink, 20%); + + border-top: 1px dashed darken($pink, 50%); + box-shadow: inset 0px 1px 0px rgba(255,255,255, 0.5); + padding: 8px 0 20px 0; + + line-height: 150%; + + a { + color: white; + font-weight: bold; + text-decoration: none; + padding: 0 4px; + border-radius: 4px; + border: 1px solid lighten($pink, 4%); + + &:hover { + background: darken($pink, 3%); + border: 1px solid lighten($pink, 4%); + } + } +} + + +p { + line-height: 150%; + code { + background: rgba(0,0,0, 0.1); + border-radius: 4px; + padding: 1px 4px; + } +} + +.comments { + font-size: 12px; +} + +.index { + line-height: 150%; + margin-bottom: 20px; + + ul { + margin: 0; + } +} + +.highlight { + background: #333; + color: white; + font-size: 14px; + padding: 10px; + margin-bottom: 15px; + box-shadow: 0px 1px 3px rgba(0,0,0, 0.7), inset 0px 0px 0px 1px rgba(255,255,255,0.3); + border-radius: 2px; + border: 1px solid #222; + + pre { + margin-top: 0px; + margin-bottom: 0px; + } + + // builtins + .nb { + color: #FFA67C; + } + + // strings + .s, .s1, .s2, .se, .nt { + color: #ffe898; + } + + // proper names + .nc, .vc, .bp { + color: #98d9ff; + } + + // true, false, nil + .kc { + color: #acfff0; + } + + // function lit, braces, parens + .nf, .kt { + color: #9fff98; + } + + .nv { + color: #ff9898; + } + + // keywords + .k, .kd, .na { + color: #cb98ff; + } + + .c1, .c2 { + color: #929292; + } + + .m, .mi, .mf, .mh, .o { + color: #9495ff; + } +} diff --git a/bin/pscss b/bin/pscss deleted file mode 100755 index ce80e6a9..00000000 --- a/bin/pscss +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env php -parse($data)), true)); - - exit(); -} - -$scss = new Compiler(); - -if ($debugInfo) { - $scss->setLineNumberStyle(Compiler::DEBUG_INFO); -} - -if ($lineNumbers) { - $scss->setLineNumberStyle(Compiler::LINE_COMMENTS); -} - -if ($ignoreErrors) { - $scss->setIgnoreErrors($ignoreErrors); -} - -if ($loadPaths) { - $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths)); -} - -if ($precision) { - $scss->setNumberPrecision($precision); -} - -if ($style) { - $scss->setFormatter('Leafo\\ScssPhp\\Formatter\\' . ucfirst($style)); -} - -if ($sourceMap) { - $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); -} - -if ($encoding) { - $scss->setEncoding($encoding); -} - -echo $scss->compile($data, $inputFile); - -if ($changeDir) { - chdir($oldWorkingDir); -} diff --git a/community/index.md b/community/index.md new file mode 100644 index 00000000..2b6e6332 --- /dev/null +++ b/community/index.md @@ -0,0 +1,5 @@ +--- +layout: default +title: Community Guidelines +redirect_to: https://scssphp.github.io/scssphp/community/ +--- diff --git a/composer.json b/composer.json deleted file mode 100644 index eaa8e87b..00000000 --- a/composer.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "leafo/scssphp", - "type": "library", - "description": "scssphp is a compiler for SCSS written in PHP.", - "keywords": ["css", "stylesheet", "scss", "sass", "less"], - "homepage": "http://leafo.github.io/scssphp/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Leaf Corcoran", - "email": "leafot@gmail.com", - "homepage": "http://leafo.net" - } - ], - "autoload": { - "psr-4": { "Leafo\\ScssPhp\\": "src/" } - }, - "autoload-dev": { - "psr-4": { "Leafo\\ScssPhp\\Test\\": "tests/" } - }, - "require": { - "php": "^5.4.0 || ^7" - }, - "require-dev": { - "squizlabs/php_codesniffer": "~2.5", - "phpunit/phpunit": "~4.6", - "twbs/bootstrap": "~4.3", - "zurb/foundation": "~6.5" - }, - "bin": ["bin/pscss"], - "archive": { - "exclude": [ - "/Makefile", - "/.gitattributes", - "/.gitignore", - "/.travis.yml", - "/phpunit.xml.dist", - "/tests" - ] - }, - "abandoned": "scssphp/scssphp" -} diff --git a/css/main.scss b/css/main.scss new file mode 100755 index 00000000..046ee8c8 --- /dev/null +++ b/css/main.scss @@ -0,0 +1,8 @@ +--- +# Only the main Sass file needs front matter (the dashes are enough) +--- +@charset "utf-8"; + +@import + "leafo" +; diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 00000000..9d156c6d --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,5 @@ +--- +layout: default +title: Changelog +redirect_to: https://scssphp.github.io/scssphp/docs/changelog +--- diff --git a/docs/example.md b/docs/example.md new file mode 100644 index 00000000..1c7eb4cc --- /dev/null +++ b/docs/example.md @@ -0,0 +1,5 @@ +--- +layout: default +title: Example +redirect_to: https://scssphp.github.io/scssphp/docs/example +--- diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..7718e5f1 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,5 @@ +--- +layout: default +title: Documentation +redirect_to: https://scssphp.github.io/scssphp/docs/ +--- diff --git a/example/Server.php b/example/Server.php deleted file mode 100644 index 54060b1a..00000000 --- a/example/Server.php +++ /dev/null @@ -1,515 +0,0 @@ - - */ -class Server -{ - /** - * @var boolean - */ - private $showErrorsAsCSS; - - /** - * @var string - */ - private $dir; - - /** - * @var string - */ - private $cacheDir; - - /** - * @var \Leafo\ScssPhp\Compiler - */ - private $scss; - - /** - * Join path components - * - * @param string $left Path component, left of the directory separator - * @param string $right Path component, right of the directory separator - * - * @return string - */ - protected function join($left, $right) - { - return rtrim($left, '/\\') . DIRECTORY_SEPARATOR . ltrim($right, '/\\'); - } - - /** - * Get name of requested .scss file - * - * @return string|null - */ - protected function inputName() - { - switch (true) { - case isset($_GET['p']): - return $_GET['p']; - case isset($_SERVER['PATH_INFO']): - return $_SERVER['PATH_INFO']; - case isset($_SERVER['DOCUMENT_URI']): - return substr($_SERVER['DOCUMENT_URI'], strlen($_SERVER['SCRIPT_NAME'])); - } - } - - /** - * Get path to requested .scss file - * - * @return string - */ - protected function findInput() - { - if (($input = $this->inputName()) - && strpos($input, '..') === false - && substr($input, -5) === '.scss' - ) { - $name = $this->join($this->dir, $input); - - if (is_file($name) && is_readable($name)) { - return $name; - } - } - - return false; - } - - /** - * Get path to cached .css file - * - * @return string - */ - protected function cacheName($fname) - { - return $this->join($this->cacheDir, md5($fname) . '.css'); - } - - /** - * Get path to meta data - * - * @return string - */ - protected function metadataName($out) - { - return $out . '.meta'; - } - - /** - * Determine whether .scss file needs to be re-compiled. - * - * @param string $out Output path - * @param string $etag ETag - * - * @return boolean True if compile required. - */ - protected function needsCompile($out, &$etag) - { - if (! is_file($out)) { - return true; - } - - $mtime = filemtime($out); - - $metadataName = $this->metadataName($out); - - if (is_readable($metadataName)) { - $metadata = unserialize(file_get_contents($metadataName)); - - foreach ($metadata['imports'] as $import => $originalMtime) { - $currentMtime = filemtime($import); - - if ($currentMtime !== $originalMtime || $currentMtime > $mtime) { - return true; - } - } - - $metaVars = crc32(serialize($this->scss->getVariables())); - - if ($metaVars !== $metadata['vars']) { - return true; - } - - $etag = $metadata['etag']; - - return false; - } - - return true; - } - - /** - * Get If-Modified-Since header from client request - * - * @return string|null - */ - protected function getIfModifiedSinceHeader() - { - $modifiedSince = null; - - if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { - $modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE']; - - if (false !== ($semicolonPos = strpos($modifiedSince, ';'))) { - $modifiedSince = substr($modifiedSince, 0, $semicolonPos); - } - } - - return $modifiedSince; - } - - /** - * Get If-None-Match header from client request - * - * @return string|null - */ - protected function getIfNoneMatchHeader() - { - $noneMatch = null; - - if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) { - $noneMatch = $_SERVER['HTTP_IF_NONE_MATCH']; - } - - return $noneMatch; - } - - /** - * Compile .scss file - * - * @param string $in Input path (.scss) - * @param string $out Output path (.css) - * - * @return array - */ - protected function compile($in, $out) - { - $start = microtime(true); - $css = $this->scss->compile(file_get_contents($in), $in); - $elapsed = round((microtime(true) - $start), 4); - - $v = Version::VERSION; - $t = gmdate('r'); - $css = "/* compiled by scssphp $v on $t (${elapsed}s) */\n\n" . $css; - $etag = md5($css); - - file_put_contents($out, $css); - file_put_contents( - $this->metadataName($out), - serialize([ - 'etag' => $etag, - 'imports' => $this->scss->getParsedFiles(), - 'vars' => crc32(serialize($this->scss->getVariables())), - ]) - ); - - return [$css, $etag]; - } - - /** - * Format error as a pseudo-element in CSS - * - * @param \Exception $error - * - * @return string - */ - protected function createErrorCSS(\Exception $error) - { - $message = str_replace( - ["'", "\n"], - ["\\'", "\\A"], - $error->getfile() . ":\n\n" . $error->getMessage() - ); - - return "body { display: none !important; } - html:after { - background: white; - color: black; - content: '$message'; - display: block !important; - font-family: mono; - padding: 1em; - white-space: pre; - }"; - } - - /** - * Render errors as a pseudo-element within valid CSS, displaying the errors on any - * page that includes this CSS. - * - * @param boolean $show - */ - public function showErrorsAsCSS($show = true) - { - $this->showErrorsAsCSS = $show; - } - - /** - * Compile .scss file - * - * @param string $in Input file (.scss) - * @param string $out Output file (.css) optional - * - * @return string|bool - * - * @throws \Leafo\ScssPhp\Exception\ServerException - */ - public function compileFile($in, $out = null) - { - if (! is_readable($in)) { - throw new ServerException('load error: failed to find ' . $in); - } - - $pi = pathinfo($in); - - $this->scss->addImportPath($pi['dirname'] . '/'); - - $compiled = $this->scss->compile(file_get_contents($in), $in); - - if ($out !== null) { - return file_put_contents($out, $compiled); - } - - return $compiled; - } - - /** - * Check if file need compiling - * - * @param string $in Input file (.scss) - * @param string $out Output file (.css) - * - * @return bool - */ - public function checkedCompile($in, $out) - { - if (! is_file($out) || filemtime($in) > filemtime($out)) { - $this->compileFile($in, $out); - - return true; - } - - return false; - } - - /** - * Compile requested scss and serve css. Outputs HTTP response. - * - * @param string $salt Prefix a string to the filename for creating the cache name hash - */ - public function serve($salt = '') - { - $protocol = isset($_SERVER['SERVER_PROTOCOL']) - ? $_SERVER['SERVER_PROTOCOL'] - : 'HTTP/1.0'; - - if ($input = $this->findInput()) { - $output = $this->cacheName($salt . $input); - $etag = $noneMatch = trim($this->getIfNoneMatchHeader(), '"'); - - if ($this->needsCompile($output, $etag)) { - try { - list($css, $etag) = $this->compile($input, $output); - - $lastModified = gmdate('r', filemtime($output)); - - header('Last-Modified: ' . $lastModified); - header('Content-type: text/css'); - header('ETag: "' . $etag . '"'); - - echo $css; - } catch (\Exception $e) { - if ($this->showErrorsAsCSS) { - header('Content-type: text/css'); - - echo $this->createErrorCSS($e); - } else { - header($protocol . ' 500 Internal Server Error'); - header('Content-type: text/plain'); - - echo 'Parse error: ' . $e->getMessage() . "\n"; - } - } - - return; - } - - header('X-SCSS-Cache: true'); - header('Content-type: text/css'); - header('ETag: "' . $etag . '"'); - - if ($etag === $noneMatch) { - header($protocol . ' 304 Not Modified'); - - return; - } - - $modifiedSince = $this->getIfModifiedSinceHeader(); - $mtime = filemtime($output); - - if (strtotime($modifiedSince) === $mtime) { - header($protocol . ' 304 Not Modified'); - - return; - } - - $lastModified = gmdate('r', $mtime); - header('Last-Modified: ' . $lastModified); - - echo file_get_contents($output); - - return; - } - - header($protocol . ' 404 Not Found'); - header('Content-type: text/plain'); - - $v = Version::VERSION; - echo "/* INPUT NOT FOUND scss $v */\n"; - } - - /** - * Based on explicit input/output files does a full change check on cache before compiling. - * - * @param string $in - * @param string $out - * @param boolean $force - * - * @return string Compiled CSS results - * - * @throws \Leafo\ScssPhp\Exception\ServerException - */ - public function checkedCachedCompile($in, $out, $force = false) - { - if (! is_file($in) || ! is_readable($in)) { - throw new ServerException('Invalid or unreadable input file specified.'); - } - - if (is_dir($out) || ! is_writable(file_exists($out) ? $out : dirname($out))) { - throw new ServerException('Invalid or unwritable output file specified.'); - } - - if ($force || $this->needsCompile($out, $etag)) { - list($css, $etag) = $this->compile($in, $out); - } else { - $css = file_get_contents($out); - } - - return $css; - } - - /** - * Execute scssphp on a .scss file or a scssphp cache structure - * - * The scssphp cache structure contains information about a specific - * scss file having been parsed. It can be used as a hint for future - * calls to determine whether or not a rebuild is required. - * - * The cache structure contains two important keys that may be used - * externally: - * - * compiled: The final compiled CSS - * updated: The time (in seconds) the CSS was last compiled - * - * The cache structure is a plain-ol' PHP associative array and can - * be serialized and unserialized without a hitch. - * - * @param mixed $in Input - * @param boolean $force Force rebuild? - * - * @return array scssphp cache structure - */ - public function cachedCompile($in, $force = false) - { - // assume no root - $root = null; - - if (is_string($in)) { - $root = $in; - } elseif (is_array($in) and isset($in['root'])) { - if ($force or ! isset($in['files'])) { - // If we are forcing a recompile or if for some reason the - // structure does not contain any file information we should - // specify the root to trigger a rebuild. - $root = $in['root']; - } elseif (isset($in['files']) and is_array($in['files'])) { - foreach ($in['files'] as $fname => $ftime) { - if (! file_exists($fname) or filemtime($fname) > $ftime) { - // One of the files we knew about previously has changed - // so we should look at our incoming root again. - $root = $in['root']; - break; - } - } - } - } else { - // TODO: Throw an exception? We got neither a string nor something - // that looks like a compatible lessphp cache structure. - return null; - } - - if ($root !== null) { - // If we have a root value which means we should rebuild. - $out = []; - $out['root'] = $root; - $out['compiled'] = $this->compileFile($root); - $out['files'] = $this->scss->getParsedFiles(); - $out['updated'] = time(); - return $out; - } else { - // No changes, pass back the structure - // we were given initially. - return $in; - } - } - - /** - * Constructor - * - * @param string $dir Root directory to .scss files - * @param string $cacheDir Cache directory - * @param \Leafo\ScssPhp\Compiler|null $scss SCSS compiler instance - */ - public function __construct($dir, $cacheDir = null, $scss = null) - { - $this->dir = $dir; - - if (! isset($cacheDir)) { - $cacheDir = $this->join($dir, 'scss_cache'); - } - - $this->cacheDir = $cacheDir; - - if (! is_dir($this->cacheDir)) { - throw new ServerException('Cache directory doesn\'t exist: ' . $cacheDir); - } - - if (! isset($scss)) { - $scss = new Compiler(); - $scss->setImportPaths($this->dir); - } - - $this->scss = $scss; - $this->showErrorsAsCSS = false; - - date_default_timezone_set('UTC'); - } -} diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..bc72ac63 Binary files /dev/null and b/favicon.ico differ diff --git a/img/tile.png b/img/tile.png new file mode 100644 index 00000000..ecb7149d Binary files /dev/null and b/img/tile.png differ diff --git a/index.md b/index.md new file mode 100644 index 00000000..cb7e50f2 --- /dev/null +++ b/index.md @@ -0,0 +1,4 @@ +--- +layout: default +redirect_to: https://scssphp.github.io/scssphp/ +--- diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index c007930c..00000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - tests - - - - - - src - - - - diff --git a/scss.inc.php b/scss.inc.php deleted file mode 100644 index 2a5f0774..00000000 --- a/scss.inc.php +++ /dev/null @@ -1,34 +0,0 @@ - - */ -class Range -{ - public $first; - public $last; - - /** - * Initialize range - * - * @param integer|float $first - * @param integer|float $last - */ - public function __construct($first, $last) - { - $this->first = $first; - $this->last = $last; - } - - /** - * Test for inclusion in range - * - * @param integer|float $value - * - * @return boolean - */ - public function includes($value) - { - return $value >= $this->first && $value <= $this->last; - } -} diff --git a/src/Block.php b/src/Block.php deleted file mode 100644 index 41abf01a..00000000 --- a/src/Block.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -class Block -{ - /** - * @var string - */ - public $type; - - /** - * @var \Leafo\ScssPhp\Block - */ - public $parent; - - /** - * @var string - */ - public $sourceName; - - /** - * @var integer - */ - public $sourceIndex; - - /** - * @var integer - */ - public $sourceLine; - - /** - * @var integer - */ - public $sourceColumn; - - /** - * @var array - */ - public $selectors; - - /** - * @var array - */ - public $comments; - - /** - * @var array - */ - public $children; - - /** - * @var \Leafo\ScssPhp\Block - */ - public $selfParent; -} diff --git a/src/Cache.php b/src/Cache.php deleted file mode 100644 index 49cf631b..00000000 --- a/src/Cache.php +++ /dev/null @@ -1,239 +0,0 @@ - $lastModified) - && $cacheTime + self::$gcLifetime > time() - ) { - $c = file_get_contents($fileCache); - $c = unserialize($c); - - if (is_array($c) && isset($c['value'])) { - return $c['value']; - } - } - } - - return null; - } - - /** - * Put in cache the result of $operation on $what, - * which is known as dependant from the content of $options - * - * @param string $operation - * @param mixed $what - * @param mixed $value - * @param array $options - */ - public function setCache($operation, $what, $value, $options = []) - { - $fileCache = self::$cacheDir . self::cacheName($operation, $what, $options); - - $c = ['value' => $value]; - $c = serialize($c); - file_put_contents($fileCache, $c); - - if (self::$forceRefresh === 'once') { - self::$refreshed[$fileCache] = true; - } - } - - /** - * Get the cache name for the caching of $operation on $what, - * which is known as dependant from the content of $options - * - * @param string $operation - * @param mixed $what - * @param array $options - * - * @return string - */ - private static function cacheName($operation, $what, $options = []) - { - $t = [ - 'version' => self::CACHE_VERSION, - 'operation' => $operation, - 'what' => $what, - 'options' => $options - ]; - - $t = self::$prefix - . sha1(json_encode($t)) - . ".$operation" - . ".scsscache"; - - return $t; - } - - /** - * Check that the cache dir exists and is writeable - * - * @throws \Exception - */ - public static function checkCacheDir() - { - self::$cacheDir = str_replace('\\', '/', self::$cacheDir); - self::$cacheDir = rtrim(self::$cacheDir, '/') . '/'; - - if (! file_exists(self::$cacheDir)) { - if (! mkdir(self::$cacheDir)) { - throw new Exception('Cache directory couldn\'t be created: ' . self::$cacheDir); - } - } elseif (! is_dir(self::$cacheDir)) { - throw new Exception('Cache directory doesn\'t exist: ' . self::$cacheDir); - } elseif (! is_writable(self::$cacheDir)) { - throw new Exception('Cache directory isn\'t writable: ' . self::$cacheDir); - } - } - - /** - * Delete unused cached files - */ - public static function cleanCache() - { - static $clean = false; - - if ($clean || empty(self::$cacheDir)) { - return; - } - - $clean = true; - - // only remove files with extensions created by SCSSPHP Cache - // css files removed based on the list files - $removeTypes = ['scsscache' => 1]; - - $files = scandir(self::$cacheDir); - - if (! $files) { - return; - } - - $checkTime = time() - self::$gcLifetime; - - foreach ($files as $file) { - // don't delete if the file wasn't created with SCSSPHP Cache - if (strpos($file, self::$prefix) !== 0) { - continue; - } - - $parts = explode('.', $file); - $type = array_pop($parts); - - if (! isset($removeTypes[$type])) { - continue; - } - - $fullPath = self::$cacheDir . $file; - $mtime = filemtime($fullPath); - - // don't delete if it's a relatively new file - if ($mtime > $checkTime) { - continue; - } - - unlink($fullPath); - } - } -} diff --git a/src/Colors.php b/src/Colors.php deleted file mode 100644 index 2314ea58..00000000 --- a/src/Colors.php +++ /dev/null @@ -1,179 +0,0 @@ - - */ -class Colors -{ - /** - * CSS Colors - * - * @see http://www.w3.org/TR/css3-color - * - * @var array - */ - public static $cssColors = [ - 'aliceblue' => '240,248,255', - 'antiquewhite' => '250,235,215', - 'aqua' => '0,255,255', - 'aquamarine' => '127,255,212', - 'azure' => '240,255,255', - 'beige' => '245,245,220', - 'bisque' => '255,228,196', - 'black' => '0,0,0', - 'blanchedalmond' => '255,235,205', - 'blue' => '0,0,255', - 'blueviolet' => '138,43,226', - 'brown' => '165,42,42', - 'burlywood' => '222,184,135', - 'cadetblue' => '95,158,160', - 'chartreuse' => '127,255,0', - 'chocolate' => '210,105,30', - 'coral' => '255,127,80', - 'cornflowerblue' => '100,149,237', - 'cornsilk' => '255,248,220', - 'crimson' => '220,20,60', - 'cyan' => '0,255,255', - 'darkblue' => '0,0,139', - 'darkcyan' => '0,139,139', - 'darkgoldenrod' => '184,134,11', - 'darkgray' => '169,169,169', - 'darkgreen' => '0,100,0', - 'darkgrey' => '169,169,169', - 'darkkhaki' => '189,183,107', - 'darkmagenta' => '139,0,139', - 'darkolivegreen' => '85,107,47', - 'darkorange' => '255,140,0', - 'darkorchid' => '153,50,204', - 'darkred' => '139,0,0', - 'darksalmon' => '233,150,122', - 'darkseagreen' => '143,188,143', - 'darkslateblue' => '72,61,139', - 'darkslategray' => '47,79,79', - 'darkslategrey' => '47,79,79', - 'darkturquoise' => '0,206,209', - 'darkviolet' => '148,0,211', - 'deeppink' => '255,20,147', - 'deepskyblue' => '0,191,255', - 'dimgray' => '105,105,105', - 'dimgrey' => '105,105,105', - 'dodgerblue' => '30,144,255', - 'firebrick' => '178,34,34', - 'floralwhite' => '255,250,240', - 'forestgreen' => '34,139,34', - 'fuchsia' => '255,0,255', - 'gainsboro' => '220,220,220', - 'ghostwhite' => '248,248,255', - 'gold' => '255,215,0', - 'goldenrod' => '218,165,32', - 'gray' => '128,128,128', - 'green' => '0,128,0', - 'greenyellow' => '173,255,47', - 'grey' => '128,128,128', - 'honeydew' => '240,255,240', - 'hotpink' => '255,105,180', - 'indianred' => '205,92,92', - 'indigo' => '75,0,130', - 'ivory' => '255,255,240', - 'khaki' => '240,230,140', - 'lavender' => '230,230,250', - 'lavenderblush' => '255,240,245', - 'lawngreen' => '124,252,0', - 'lemonchiffon' => '255,250,205', - 'lightblue' => '173,216,230', - 'lightcoral' => '240,128,128', - 'lightcyan' => '224,255,255', - 'lightgoldenrodyellow' => '250,250,210', - 'lightgray' => '211,211,211', - 'lightgreen' => '144,238,144', - 'lightgrey' => '211,211,211', - 'lightpink' => '255,182,193', - 'lightsalmon' => '255,160,122', - 'lightseagreen' => '32,178,170', - 'lightskyblue' => '135,206,250', - 'lightslategray' => '119,136,153', - 'lightslategrey' => '119,136,153', - 'lightsteelblue' => '176,196,222', - 'lightyellow' => '255,255,224', - 'lime' => '0,255,0', - 'limegreen' => '50,205,50', - 'linen' => '250,240,230', - 'magenta' => '255,0,255', - 'maroon' => '128,0,0', - 'mediumaquamarine' => '102,205,170', - 'mediumblue' => '0,0,205', - 'mediumorchid' => '186,85,211', - 'mediumpurple' => '147,112,219', - 'mediumseagreen' => '60,179,113', - 'mediumslateblue' => '123,104,238', - 'mediumspringgreen' => '0,250,154', - 'mediumturquoise' => '72,209,204', - 'mediumvioletred' => '199,21,133', - 'midnightblue' => '25,25,112', - 'mintcream' => '245,255,250', - 'mistyrose' => '255,228,225', - 'moccasin' => '255,228,181', - 'navajowhite' => '255,222,173', - 'navy' => '0,0,128', - 'oldlace' => '253,245,230', - 'olive' => '128,128,0', - 'olivedrab' => '107,142,35', - 'orange' => '255,165,0', - 'orangered' => '255,69,0', - 'orchid' => '218,112,214', - 'palegoldenrod' => '238,232,170', - 'palegreen' => '152,251,152', - 'paleturquoise' => '175,238,238', - 'palevioletred' => '219,112,147', - 'papayawhip' => '255,239,213', - 'peachpuff' => '255,218,185', - 'peru' => '205,133,63', - 'pink' => '255,192,203', - 'plum' => '221,160,221', - 'powderblue' => '176,224,230', - 'purple' => '128,0,128', - 'rebeccapurple' => '102,51,153', - 'red' => '255,0,0', - 'rosybrown' => '188,143,143', - 'royalblue' => '65,105,225', - 'saddlebrown' => '139,69,19', - 'salmon' => '250,128,114', - 'sandybrown' => '244,164,96', - 'seagreen' => '46,139,87', - 'seashell' => '255,245,238', - 'sienna' => '160,82,45', - 'silver' => '192,192,192', - 'skyblue' => '135,206,235', - 'slateblue' => '106,90,205', - 'slategray' => '112,128,144', - 'slategrey' => '112,128,144', - 'snow' => '255,250,250', - 'springgreen' => '0,255,127', - 'steelblue' => '70,130,180', - 'tan' => '210,180,140', - 'teal' => '0,128,128', - 'thistle' => '216,191,216', - 'tomato' => '255,99,71', - 'transparent' => '0,0,0,0', - 'turquoise' => '64,224,208', - 'violet' => '238,130,238', - 'wheat' => '245,222,179', - 'white' => '255,255,255', - 'whitesmoke' => '245,245,245', - 'yellow' => '255,255,0', - 'yellowgreen' => '154,205,50', - ]; -} diff --git a/src/Compiler.php b/src/Compiler.php deleted file mode 100644 index d22d0a35..00000000 --- a/src/Compiler.php +++ /dev/null @@ -1,6659 +0,0 @@ - - */ -class Compiler -{ - const LINE_COMMENTS = 1; - const DEBUG_INFO = 2; - - const WITH_RULE = 1; - const WITH_MEDIA = 2; - const WITH_SUPPORTS = 4; - const WITH_ALL = 7; - - const SOURCE_MAP_NONE = 0; - const SOURCE_MAP_INLINE = 1; - const SOURCE_MAP_FILE = 2; - - /** - * @var array - */ - static protected $operatorNames = [ - '+' => 'add', - '-' => 'sub', - '*' => 'mul', - '/' => 'div', - '%' => 'mod', - - '==' => 'eq', - '!=' => 'neq', - '<' => 'lt', - '>' => 'gt', - - '<=' => 'lte', - '>=' => 'gte', - '<=>' => 'cmp', - ]; - - /** - * @var array - */ - static protected $namespaces = [ - 'special' => '%', - 'mixin' => '@', - 'function' => '^', - ]; - - static public $true = [Type::T_KEYWORD, 'true']; - static public $false = [Type::T_KEYWORD, 'false']; - static public $null = [Type::T_NULL]; - static public $nullString = [Type::T_STRING, '', []]; - static public $defaultValue = [Type::T_KEYWORD, '']; - static public $selfSelector = [Type::T_SELF]; - static public $emptyList = [Type::T_LIST, '', []]; - static public $emptyMap = [Type::T_MAP, [], []]; - static public $emptyString = [Type::T_STRING, '"', []]; - static public $with = [Type::T_KEYWORD, 'with']; - static public $without = [Type::T_KEYWORD, 'without']; - - protected $importPaths = ['']; - protected $importCache = []; - protected $importedFiles = []; - protected $userFunctions = []; - protected $registeredVars = []; - protected $registeredFeatures = [ - 'extend-selector-pseudoclass' => false, - 'at-error' => true, - 'units-level-3' => false, - 'global-variable-shadowing' => false, - ]; - - protected $encoding = null; - protected $lineNumberStyle = null; - - protected $sourceMap = self::SOURCE_MAP_NONE; - protected $sourceMapOptions = []; - - /** - * @var string|\Leafo\ScssPhp\Formatter - */ - protected $formatter = 'Leafo\ScssPhp\Formatter\Nested'; - - protected $rootEnv; - protected $rootBlock; - - /** - * @var \Leafo\ScssPhp\Compiler\Environment - */ - protected $env; - protected $scope; - protected $storeEnv; - protected $charsetSeen; - protected $sourceNames; - - protected $cache; - - protected $indentLevel; - protected $extends; - protected $extendsMap; - protected $parsedFiles; - protected $parser; - protected $sourceIndex; - protected $sourceLine; - protected $sourceColumn; - protected $stderr; - protected $shouldEvaluate; - protected $ignoreErrors; - - protected $callStack = []; - - /** - * Constructor - */ - public function __construct($cacheOptions = null) - { - $this->parsedFiles = []; - $this->sourceNames = []; - - if ($cacheOptions) { - $this->cache = new Cache($cacheOptions); - } - } - - public function getCompileOptions() - { - $options = [ - 'importPaths' => $this->importPaths, - 'registeredVars' => $this->registeredVars, - 'registeredFeatures' => $this->registeredFeatures, - 'encoding' => $this->encoding, - 'sourceMap' => serialize($this->sourceMap), - 'sourceMapOptions' => $this->sourceMapOptions, - 'formatter' => $this->formatter, - ]; - - return $options; - } - - /** - * Compile scss - * - * @api - * - * @param string $code - * @param string $path - * - * @return string - */ - public function compile($code, $path = null) - { - if ($this->cache) { - $cacheKey = ($path ? $path : "(stdin)") . ":" . md5($code); - $compileOptions = $this->getCompileOptions(); - $cache = $this->cache->getCache("compile", $cacheKey, $compileOptions); - - if (is_array($cache) - && isset($cache['dependencies']) - && isset($cache['out']) - ) { - // check if any dependency file changed before accepting the cache - foreach ($cache['dependencies'] as $file => $mtime) { - if (! file_exists($file) - || filemtime($file) !== $mtime - ) { - unset($cache); - break; - } - } - - if (isset($cache)) { - return $cache['out']; - } - } - } - - - $this->indentLevel = -1; - $this->extends = []; - $this->extendsMap = []; - $this->sourceIndex = null; - $this->sourceLine = null; - $this->sourceColumn = null; - $this->env = null; - $this->scope = null; - $this->storeEnv = null; - $this->charsetSeen = null; - $this->shouldEvaluate = null; - $this->stderr = fopen('php://stderr', 'w'); - - $this->parser = $this->parserFactory($path); - $tree = $this->parser->parse($code); - $this->parser = null; - - $this->formatter = new $this->formatter(); - $this->rootBlock = null; - $this->rootEnv = $this->pushEnv($tree); - - $this->injectVariables($this->registeredVars); - $this->compileRoot($tree); - $this->popEnv(); - - $sourceMapGenerator = null; - - if ($this->sourceMap) { - if (is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) { - $sourceMapGenerator = $this->sourceMap; - $this->sourceMap = self::SOURCE_MAP_FILE; - } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions); - } - } - - $out = $this->formatter->format($this->scope, $sourceMapGenerator); - - if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) { - $sourceMap = $sourceMapGenerator->generateJson(); - $sourceMapUrl = null; - - switch ($this->sourceMap) { - case self::SOURCE_MAP_INLINE: - $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap)); - break; - - case self::SOURCE_MAP_FILE: - $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap); - break; - } - - $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl); - } - - if ($this->cache && isset($cacheKey) && isset($compileOptions)) { - $v = [ - 'dependencies' => $this->getParsedFiles(), - 'out' => &$out, - ]; - - $this->cache->setCache("compile", $cacheKey, $v, $compileOptions); - } - - return $out; - } - - /** - * Instantiate parser - * - * @param string $path - * - * @return \Leafo\ScssPhp\Parser - */ - protected function parserFactory($path) - { - $parser = new Parser($path, count($this->sourceNames), $this->encoding, $this->cache); - - $this->sourceNames[] = $path; - $this->addParsedFile($path); - - return $parser; - } - - /** - * Is self extend? - * - * @param array $target - * @param array $origin - * - * @return boolean - */ - protected function isSelfExtend($target, $origin) - { - foreach ($origin as $sel) { - if (in_array($target, $sel)) { - return true; - } - } - - return false; - } - - /** - * Push extends - * - * @param array $target - * @param array $origin - * @param \stdClass $block - */ - protected function pushExtends($target, $origin, $block) - { - if ($this->isSelfExtend($target, $origin)) { - return; - } - - $i = count($this->extends); - $this->extends[] = [$target, $origin, $block]; - - foreach ($target as $part) { - if (isset($this->extendsMap[$part])) { - $this->extendsMap[$part][] = $i; - } else { - $this->extendsMap[$part] = [$i]; - } - } - } - - /** - * Make output block - * - * @param string $type - * @param array $selectors - * - * @return \Leafo\ScssPhp\Formatter\OutputBlock - */ - protected function makeOutputBlock($type, $selectors = null) - { - $out = new OutputBlock; - $out->type = $type; - $out->lines = []; - $out->children = []; - $out->parent = $this->scope; - $out->selectors = $selectors; - $out->depth = $this->env->depth; - - if ($this->env->block instanceof Block) { - $out->sourceName = $this->env->block->sourceName; - $out->sourceLine = $this->env->block->sourceLine; - $out->sourceColumn = $this->env->block->sourceColumn; - } else { - $out->sourceName = null; - $out->sourceLine = null; - $out->sourceColumn = null; - } - - return $out; - } - - /** - * Compile root - * - * @param \Leafo\ScssPhp\Block $rootBlock - */ - protected function compileRoot(Block $rootBlock) - { - $this->rootBlock = $this->scope = $this->makeOutputBlock(Type::T_ROOT); - - $this->compileChildrenNoReturn($rootBlock->children, $this->scope); - $this->flattenSelectors($this->scope); - $this->missingSelectors(); - } - - /** - * Report missing selectors - */ - protected function missingSelectors() - { - foreach ($this->extends as $extend) { - if (isset($extend[3])) { - continue; - } - - list($target, $origin, $block) = $extend; - - // ignore if !optional - if ($block[2]) { - continue; - } - - $target = implode(' ', $target); - $origin = $this->collapseSelectors($origin); - - $this->sourceLine = $block[Parser::SOURCE_LINE]; - $this->throwError("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found."); - } - } - - /** - * Flatten selectors - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - * @param string $parentKey - */ - protected function flattenSelectors(OutputBlock $block, $parentKey = null) - { - if ($block->selectors) { - $selectors = []; - - foreach ($block->selectors as $s) { - $selectors[] = $s; - - if (! is_array($s)) { - continue; - } - - // check extends - if (! empty($this->extendsMap)) { - $this->matchExtends($s, $selectors); - - // remove duplicates - array_walk($selectors, function (&$value) { - $value = serialize($value); - }); - - $selectors = array_unique($selectors); - - array_walk($selectors, function (&$value) { - $value = unserialize($value); - }); - } - } - - $block->selectors = []; - $placeholderSelector = false; - - foreach ($selectors as $selector) { - if ($this->hasSelectorPlaceholder($selector)) { - $placeholderSelector = true; - continue; - } - - $block->selectors[] = $this->compileSelector($selector); - } - - if ($placeholderSelector && 0 === count($block->selectors) && null !== $parentKey) { - unset($block->parent->children[$parentKey]); - - return; - } - } - - foreach ($block->children as $key => $child) { - $this->flattenSelectors($child, $key); - } - } - - /** - * Glue parts of :not( or :nth-child( ... that are in general splitted in selectors parts - * - * @param array $parts - * - * @return array - */ - protected function glueFunctionSelectors($parts) - { - $new = []; - - foreach ($parts as $part) { - if (is_array($part)) { - $part = $this->glueFunctionSelectors($part); - $new[] = $part; - } else { - // a selector part finishing with a ) is the last part of a :not( or :nth-child( - // and need to be joined to this - if (count($new) && is_string($new[count($new) - 1]) - && strlen($part) && substr($part, -1) === ')' && strpos($part, '(') === false - ) { - $new[count($new) - 1] .= $part; - } else { - $new[] = $part; - } - } - } - - return $new; - } - - /** - * Match extends - * - * @param array $selector - * @param array $out - * @param integer $from - * @param boolean $initial - */ - protected function matchExtends($selector, &$out, $from = 0, $initial = true) - { - static $partsPile = []; - - $selector = $this->glueFunctionSelectors($selector); - - foreach ($selector as $i => $part) { - if ($i < $from) { - continue; - } - - // check that we are not building an infinite loop of extensions - // if the new part is just including a previous part don't try to extend anymore - if (count($part) > 1) { - foreach ($partsPile as $previousPart) { - if (! count(array_diff($previousPart, $part))) { - continue 2; - } - } - } - - if ($this->matchExtendsSingle($part, $origin)) { - $partsPile[] = $part; - $after = array_slice($selector, $i + 1); - $before = array_slice($selector, 0, $i); - - list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before); - - foreach ($origin as $new) { - $k = 0; - - // remove shared parts - if (count($new) > 1) { - while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) { - $k++; - } - } - - $replacement = []; - $tempReplacement = $k > 0 ? array_slice($new, $k) : $new; - - for ($l = count($tempReplacement) - 1; $l >= 0; $l--) { - $slice = []; - - foreach ($tempReplacement[$l] as $chunk) { - if (! in_array($chunk, $slice)) { - $slice[] = $chunk; - } - } - - array_unshift($replacement, $slice); - - if (! $this->isImmediateRelationshipCombinator(end($slice))) { - break; - } - } - - $afterBefore = $l != 0 ? array_slice($tempReplacement, 0, $l) : []; - - // Merge shared direct relationships. - $mergedBefore = $this->mergeDirectRelationships($afterBefore, $nonBreakableBefore); - - $result = array_merge( - $before, - $mergedBefore, - $replacement, - $after - ); - - if ($result === $selector) { - continue; - } - - $out[] = $result; - - // recursively check for more matches - $startRecurseFrom = count($before) + min(count($nonBreakableBefore), count($mergedBefore)); - $this->matchExtends($result, $out, $startRecurseFrom, false); - - // selector sequence merging - if (! empty($before) && count($new) > 1) { - $preSharedParts = $k > 0 ? array_slice($before, 0, $k) : []; - $postSharedParts = $k > 0 ? array_slice($before, $k) : $before; - - list($betweenSharedParts, $nonBreakable2) = $this->extractRelationshipFromFragment($afterBefore); - - $result2 = array_merge( - $preSharedParts, - $betweenSharedParts, - $postSharedParts, - $nonBreakable2, - $nonBreakableBefore, - $replacement, - $after - ); - - $out[] = $result2; - } - } - - array_pop($partsPile); - } - } - } - - /** - * Match extends single - * - * @param array $rawSingle - * @param array $outOrigin - * - * @return boolean - */ - protected function matchExtendsSingle($rawSingle, &$outOrigin) - { - $counts = []; - $single = []; - - // simple usual cases, no need to do the whole trick - if (in_array($rawSingle, [['>'],['+'],['~']])) { - return false; - } - - foreach ($rawSingle as $part) { - // matches Number - if (! is_string($part)) { - return false; - } - - if (! preg_match('/^[\[.:#%]/', $part) && count($single)) { - $single[count($single) - 1] .= $part; - } else { - $single[] = $part; - } - } - - $extendingDecoratedTag = false; - - if (count($single) > 1) { - $matches = null; - $extendingDecoratedTag = preg_match('/^[a-z0-9]+$/i', $single[0], $matches) ? $matches[0] : false; - } - - foreach ($single as $part) { - if (isset($this->extendsMap[$part])) { - foreach ($this->extendsMap[$part] as $idx) { - $counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1; - } - } - } - - $outOrigin = []; - $found = false; - - foreach ($counts as $idx => $count) { - list($target, $origin, /* $block */) = $this->extends[$idx]; - - $origin = $this->glueFunctionSelectors($origin); - - // check count - if ($count !== count($target)) { - continue; - } - - $this->extends[$idx][3] = true; - - $rem = array_diff($single, $target); - - foreach ($origin as $j => $new) { - // prevent infinite loop when target extends itself - if ($this->isSelfExtend($single, $origin)) { - return false; - } - - $replacement = end($new); - - // Extending a decorated tag with another tag is not possible. - if ($extendingDecoratedTag && $replacement[0] != $extendingDecoratedTag && - preg_match('/^[a-z0-9]+$/i', $replacement[0]) - ) { - unset($origin[$j]); - continue; - } - - $combined = $this->combineSelectorSingle($replacement, $rem); - - if (count(array_diff($combined, $origin[$j][count($origin[$j]) - 1]))) { - $origin[$j][count($origin[$j]) - 1] = $combined; - } - } - - $outOrigin = array_merge($outOrigin, $origin); - - $found = true; - } - - return $found; - } - - /** - * Extract a relationship from the fragment. - * - * When extracting the last portion of a selector we will be left with a - * fragment which may end with a direction relationship combinator. This - * method will extract the relationship fragment and return it along side - * the rest. - * - * @param array $fragment The selector fragment maybe ending with a direction relationship combinator. - * - * @return array The selector without the relationship fragment if any, the relationship fragment. - */ - protected function extractRelationshipFromFragment(array $fragment) - { - $parents = []; - $children = []; - $j = $i = count($fragment); - - for (;;) { - $children = $j != $i ? array_slice($fragment, $j, $i - $j) : []; - $parents = array_slice($fragment, 0, $j); - $slice = end($parents); - - if (empty($slice) || ! $this->isImmediateRelationshipCombinator($slice[0])) { - break; - } - - $j -= 2; - } - - return [$parents, $children]; - } - - /** - * Combine selector single - * - * @param array $base - * @param array $other - * - * @return array - */ - protected function combineSelectorSingle($base, $other) - { - $tag = []; - $out = []; - $wasTag = true; - - foreach ([$base, $other] as $single) { - foreach ($single as $part) { - if (preg_match('/^[\[.:#]/', $part)) { - $out[] = $part; - $wasTag = false; - } elseif (preg_match('/^[^_-]/', $part)) { - $tag[] = $part; - $wasTag = true; - } elseif ($wasTag) { - $tag[count($tag) - 1] .= $part; - } else { - $out[count($out) - 1] .= $part; - } - } - } - - if (count($tag)) { - array_unshift($out, $tag[0]); - } - - return $out; - } - - /** - * Compile media - * - * @param \Leafo\ScssPhp\Block $media - */ - protected function compileMedia(Block $media) - { - $this->pushEnv($media); - - $mediaQueries = $this->compileMediaQuery($this->multiplyMedia($this->env)); - - if (! empty($mediaQueries) && $mediaQueries) { - $previousScope = $this->scope; - $parentScope = $this->mediaParent($this->scope); - - foreach ($mediaQueries as $mediaQuery) { - $this->scope = $this->makeOutputBlock(Type::T_MEDIA, [$mediaQuery]); - - $parentScope->children[] = $this->scope; - $parentScope = $this->scope; - } - - // top level properties in a media cause it to be wrapped - $needsWrap = false; - - foreach ($media->children as $child) { - $type = $child[0]; - - if ($type !== Type::T_BLOCK && - $type !== Type::T_MEDIA && - $type !== Type::T_DIRECTIVE && - $type !== Type::T_IMPORT - ) { - $needsWrap = true; - break; - } - } - - if ($needsWrap) { - $wrapped = new Block; - $wrapped->sourceName = $media->sourceName; - $wrapped->sourceIndex = $media->sourceIndex; - $wrapped->sourceLine = $media->sourceLine; - $wrapped->sourceColumn = $media->sourceColumn; - $wrapped->selectors = []; - $wrapped->comments = []; - $wrapped->parent = $media; - $wrapped->children = $media->children; - - $media->children = [[Type::T_BLOCK, $wrapped]]; - if (isset($this->lineNumberStyle)) { - $annotation = $this->makeOutputBlock(Type::T_COMMENT); - $annotation->depth = 0; - - $file = $this->sourceNames[$media->sourceIndex]; - $line = $media->sourceLine; - - switch ($this->lineNumberStyle) { - case static::LINE_COMMENTS: - $annotation->lines[] = '/* line ' . $line - . ($file ? ', ' . $file : '') - . ' */'; - break; - - case static::DEBUG_INFO: - $annotation->lines[] = '@media -sass-debug-info{' - . ($file ? 'filename{font-family:"' . $file . '"}' : '') - . 'line{font-family:' . $line . '}}'; - break; - } - - $this->scope->children[] = $annotation; - } - } - - $this->compileChildrenNoReturn($media->children, $this->scope); - - $this->scope = $previousScope; - } - - $this->popEnv(); - } - - /** - * Media parent - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * - * @return \Leafo\ScssPhp\Formatter\OutputBlock - */ - protected function mediaParent(OutputBlock $scope) - { - while (! empty($scope->parent)) { - if (! empty($scope->type) && $scope->type !== Type::T_MEDIA) { - break; - } - - $scope = $scope->parent; - } - - return $scope; - } - - /** - * Compile directive - * - * @param \Leafo\ScssPhp\Block $block - */ - protected function compileDirective(Block $block) - { - $s = '@' . $block->name; - - if (! empty($block->value)) { - $s .= ' ' . $this->compileValue($block->value); - } - - if ($block->name === 'keyframes' || substr($block->name, -10) === '-keyframes') { - $this->compileKeyframeBlock($block, [$s]); - } else { - $this->compileNestedBlock($block, [$s]); - } - } - - /** - * Compile at-root - * - * @param \Leafo\ScssPhp\Block $block - */ - protected function compileAtRoot(Block $block) - { - $env = $this->pushEnv($block); - $envs = $this->compactEnv($env); - $without = isset($block->with) ? $this->compileWith($block->with) : static::WITH_RULE; - - // wrap inline selector - if ($block->selector) { - $wrapped = new Block; - $wrapped->sourceName = $block->sourceName; - $wrapped->sourceIndex = $block->sourceIndex; - $wrapped->sourceLine = $block->sourceLine; - $wrapped->sourceColumn = $block->sourceColumn; - $wrapped->selectors = $block->selector; - $wrapped->comments = []; - $wrapped->parent = $block; - $wrapped->children = $block->children; - $wrapped->selfParent = $block->selfParent; - - $block->children = [[Type::T_BLOCK, $wrapped]]; - $block->selector = null; - } - - $selfParent = $block->selfParent; - - if (! $block->selfParent->selectors && isset($block->parent) && $block->parent && - isset($block->parent->selectors) && $block->parent->selectors - ) { - $selfParent = $block->parent; - } - - $this->env = $this->filterWithout($envs, $without); - - $saveScope = $this->scope; - $this->scope = $this->filterScopeWithout($saveScope, $without); - - // propagate selfParent to the children where they still can be useful - $this->compileChildrenNoReturn($block->children, $this->scope, $selfParent); - - $this->scope = $this->completeScope($this->scope, $saveScope); - $this->scope = $saveScope; - $this->env = $this->extractEnv($envs); - - $this->popEnv(); - } - - /** - * Filter at-root scope depending of with/without option - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * @param mixed $without - * - * @return mixed - */ - protected function filterScopeWithout($scope, $without) - { - $filteredScopes = []; - - if ($scope->type === TYPE::T_ROOT) { - return $scope; - } - - // start from the root - while ($scope->parent && $scope->parent->type !== TYPE::T_ROOT) { - $scope = $scope->parent; - } - - for (;;) { - if (! $scope) { - break; - } - - if (! $this->isWithout($without, $scope)) { - $s = clone $scope; - $s->children = []; - $s->lines = []; - $s->parent = null; - - if ($s->type !== Type::T_MEDIA && $s->type !== Type::T_DIRECTIVE) { - $s->selectors = []; - } - - $filteredScopes[] = $s; - } - - if ($scope->children) { - $scope = end($scope->children); - } else { - $scope = null; - } - } - - if (! count($filteredScopes)) { - return $this->rootBlock; - } - - $newScope = array_shift($filteredScopes); - $newScope->parent = $this->rootBlock; - - $this->rootBlock->children[] = $newScope; - - $p = &$newScope; - - while (count($filteredScopes)) { - $s = array_shift($filteredScopes); - $s->parent = $p; - $p->children[] = &$s; - $p = $s; - } - - return $newScope; - } - - /** - * found missing selector from a at-root compilation in the previous scope - * (if at-root is just enclosing a property, the selector is in the parent tree) - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * @param \Leafo\ScssPhp\Formatter\OutputBlock $previousScope - * - * @return mixed - */ - protected function completeScope($scope, $previousScope) - { - if (! $scope->type && (! $scope->selectors || ! count($scope->selectors)) && count($scope->lines)) { - $scope->selectors = $this->findScopeSelectors($previousScope, $scope->depth); - } - - if ($scope->children) { - foreach ($scope->children as $k => $c) { - $scope->children[$k] = $this->completeScope($c, $previousScope); - } - } - - return $scope; - } - - /** - * Find a selector by the depth node in the scope - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $scope - * @param integer $depth - * - * @return array - */ - protected function findScopeSelectors($scope, $depth) - { - if ($scope->depth === $depth && $scope->selectors) { - return $scope->selectors; - } - - if ($scope->children) { - foreach (array_reverse($scope->children) as $c) { - if ($s = $this->findScopeSelectors($c, $depth)) { - return $s; - } - } - } - - return []; - } - - /** - * Compile @at-root's with: inclusion / without: exclusion into filter flags - * - * @param array $with - * - * @return integer - */ - protected function compileWith($with) - { - static $mapping = [ - 'rule' => self::WITH_RULE, - 'media' => self::WITH_MEDIA, - 'supports' => self::WITH_SUPPORTS, - 'all' => self::WITH_ALL, - ]; - - // exclude selectors by default - $without = static::WITH_RULE; - - if ($this->libMapHasKey([$with, static::$with])) { - $without = static::WITH_ALL; - - $list = $this->coerceList($this->libMapGet([$with, static::$with])); - - foreach ($list[2] as $item) { - $keyword = $this->compileStringContent($this->coerceString($item)); - - if (array_key_exists($keyword, $mapping)) { - $without &= ~($mapping[$keyword]); - } - } - } - - if ($this->libMapHasKey([$with, static::$without])) { - $without = 0; - - $list = $this->coerceList($this->libMapGet([$with, static::$without])); - - foreach ($list[2] as $item) { - $keyword = $this->compileStringContent($this->coerceString($item)); - - if (array_key_exists($keyword, $mapping)) { - $without |= $mapping[$keyword]; - } - } - } - - return $without; - } - - /** - * Filter env stack - * - * @param array $envs - * @param integer $without - * - * @return \Leafo\ScssPhp\Compiler\Environment - */ - protected function filterWithout($envs, $without) - { - $filtered = []; - - foreach ($envs as $e) { - if ($e->block && $this->isWithout($without, $e->block)) { - $ec = clone $e; - $ec->block = null; - $ec->selectors = []; - $filtered[] = $ec; - } else { - $filtered[] = $e; - } - } - - return $this->extractEnv($filtered); - } - - /** - * Filter WITH rules - * - * @param integer $without - * @param \Leafo\ScssPhp\Block|\Leafo\ScssPhp\Formatter\OutputBlock $block - * - * @return boolean - */ - protected function isWithout($without, $block) - { - if (isset($block->type)) { - if ($block->type === Type::T_MEDIA) { - return ($without & static::WITH_MEDIA) ? true : false; - } - - if ($block->type === Type::T_DIRECTIVE) { - if (isset($block->name) && $block->name === 'supports') { - return ($without & static::WITH_SUPPORTS) ? true : false; - } - - if (isset($block->selectors) && strpos(serialize($block->selectors), '@supports') !== false) { - return ($without & static::WITH_SUPPORTS) ? true : false; - } - } - } - - if ((($without & static::WITH_RULE) && isset($block->selectors))) { - return true; - } - - return false; - } - - /** - * Compile keyframe block - * - * @param \Leafo\ScssPhp\Block $block - * @param array $selectors - */ - protected function compileKeyframeBlock(Block $block, $selectors) - { - $env = $this->pushEnv($block); - - $envs = $this->compactEnv($env); - - $this->env = $this->extractEnv(array_filter($envs, function (Environment $e) { - return ! isset($e->block->selectors); - })); - - $this->scope = $this->makeOutputBlock($block->type, $selectors); - $this->scope->depth = 1; - $this->scope->parent->children[] = $this->scope; - - $this->compileChildrenNoReturn($block->children, $this->scope); - - $this->scope = $this->scope->parent; - $this->env = $this->extractEnv($envs); - - $this->popEnv(); - } - - /** - * Compile nested block - * - * @param \Leafo\ScssPhp\Block $block - * @param array $selectors - */ - protected function compileNestedBlock(Block $block, $selectors) - { - $this->pushEnv($block); - - $this->scope = $this->makeOutputBlock($block->type, $selectors); - $this->scope->parent->children[] = $this->scope; - - // wrap assign children in a block - // except for @font-face - if ($block->type !== Type::T_DIRECTIVE || $block->name !== "font-face") { - // need wrapping? - $needWrapping = false; - - foreach ($block->children as $child) { - if ($child[0] === Type::T_ASSIGN) { - $needWrapping = true; - break; - } - } - - if ($needWrapping) { - $wrapped = new Block; - $wrapped->sourceName = $block->sourceName; - $wrapped->sourceIndex = $block->sourceIndex; - $wrapped->sourceLine = $block->sourceLine; - $wrapped->sourceColumn = $block->sourceColumn; - $wrapped->selectors = []; - $wrapped->comments = []; - $wrapped->parent = $block; - $wrapped->children = $block->children; - $wrapped->selfParent = $block->selfParent; - - $block->children = [[Type::T_BLOCK, $wrapped]]; - } - } - - $this->compileChildrenNoReturn($block->children, $this->scope); - - $this->scope = $this->scope->parent; - - $this->popEnv(); - } - - /** - * Recursively compiles a block. - * - * A block is analogous to a CSS block in most cases. A single SCSS document - * is encapsulated in a block when parsed, but it does not have parent tags - * so all of its children appear on the root level when compiled. - * - * Blocks are made up of selectors and children. - * - * The children of a block are just all the blocks that are defined within. - * - * Compiling the block involves pushing a fresh environment on the stack, - * and iterating through the props, compiling each one. - * - * @see Compiler::compileChild() - * - * @param \Leafo\ScssPhp\Block $block - */ - protected function compileBlock(Block $block) - { - $env = $this->pushEnv($block); - $env->selectors = $this->evalSelectors($block->selectors); - - $out = $this->makeOutputBlock(null); - - if (isset($this->lineNumberStyle) && count($env->selectors) && count($block->children)) { - $annotation = $this->makeOutputBlock(Type::T_COMMENT); - $annotation->depth = 0; - - $file = $this->sourceNames[$block->sourceIndex]; - $line = $block->sourceLine; - - switch ($this->lineNumberStyle) { - case static::LINE_COMMENTS: - $annotation->lines[] = '/* line ' . $line - . ($file ? ', ' . $file : '') - . ' */'; - break; - - case static::DEBUG_INFO: - $annotation->lines[] = '@media -sass-debug-info{' - . ($file ? 'filename{font-family:"' . $file . '"}' : '') - . 'line{font-family:' . $line . '}}'; - break; - } - - $this->scope->children[] = $annotation; - } - - $this->scope->children[] = $out; - - if (count($block->children)) { - $out->selectors = $this->multiplySelectors($env, $block->selfParent); - - // propagate selfParent to the children where they still can be useful - $selfParentSelectors = null; - - if (isset($block->selfParent->selectors)) { - $selfParentSelectors = $block->selfParent->selectors; - $block->selfParent->selectors = $out->selectors; - } - - $this->compileChildrenNoReturn($block->children, $out, $block->selfParent); - - // and revert for the following childs of the same block - if ($selfParentSelectors) { - $block->selfParent->selectors = $selfParentSelectors; - } - } - - $this->formatter->stripSemicolon($out->lines); - - $this->popEnv(); - } - - /** - * Compile root level comment - * - * @param array $block - */ - protected function compileComment($block) - { - $out = $this->makeOutputBlock(Type::T_COMMENT); - $out->lines[] = is_string($block[1]) ? $block[1] : $this->compileValue($block[1]); - - $this->scope->children[] = $out; - } - - /** - * Evaluate selectors - * - * @param array $selectors - * - * @return array - */ - protected function evalSelectors($selectors) - { - $this->shouldEvaluate = false; - - $selectors = array_map([$this, 'evalSelector'], $selectors); - - // after evaluating interpolates, we might need a second pass - if ($this->shouldEvaluate) { - $selectors = $this->revertSelfSelector($selectors); - $buffer = $this->collapseSelectors($selectors); - $parser = $this->parserFactory(__METHOD__); - - if ($parser->parseSelector($buffer, $newSelectors)) { - $selectors = array_map([$this, 'evalSelector'], $newSelectors); - } - } - - return $selectors; - } - - /** - * Evaluate selector - * - * @param array $selector - * - * @return array - */ - protected function evalSelector($selector) - { - return array_map([$this, 'evalSelectorPart'], $selector); - } - - /** - * Evaluate selector part; replaces all the interpolates, stripping quotes - * - * @param array $part - * - * @return array - */ - protected function evalSelectorPart($part) - { - foreach ($part as &$p) { - if (is_array($p) && ($p[0] === Type::T_INTERPOLATE || $p[0] === Type::T_STRING)) { - $p = $this->compileValue($p); - - // force re-evaluation - if (strpos($p, '&') !== false || strpos($p, ',') !== false) { - $this->shouldEvaluate = true; - } - } elseif (is_string($p) && strlen($p) >= 2 && - ($first = $p[0]) && ($first === '"' || $first === "'") && - substr($p, -1) === $first - ) { - $p = substr($p, 1, -1); - } - } - - return $this->flattenSelectorSingle($part); - } - - /** - * Collapse selectors - * - * @param array $selectors - * @param boolean $selectorFormat - * if false return a collapsed string - * if true return an array description of a structured selector - * - * @return string - */ - protected function collapseSelectors($selectors, $selectorFormat = false) - { - $parts = []; - - foreach ($selectors as $selector) { - $output = []; - $glueNext = false; - - foreach ($selector as $node) { - $compound = ''; - - array_walk_recursive( - $node, - function ($value, $key) use (&$compound) { - $compound .= $value; - } - ); - - if ($selectorFormat && $this->isImmediateRelationshipCombinator($compound)) { - if (count($output)) { - $output[count($output) - 1] .= ' ' . $compound; - } else { - $output[] = $compound; - } - $glueNext = true; - } elseif ($glueNext) { - $output[count($output) - 1] .= ' ' . $compound; - $glueNext = false; - } else { - $output[] = $compound; - } - } - - if ($selectorFormat) { - foreach ($output as &$o) { - $o = [Type::T_STRING, '', [$o]]; - } - $output = [Type::T_LIST, ' ', $output]; - } else { - $output = implode(' ', $output); - } - - $parts[] = $output; - } - - if ($selectorFormat) { - $parts = [Type::T_LIST, ',', $parts]; - } else { - $parts = implode(', ', $parts); - } - - return $parts; - } - - /** - * Parse down the selector and revert [self] to "&" before a reparsing - * - * @param array $selectors - * - * @return array - */ - protected function revertSelfSelector($selectors) - { - foreach ($selectors as &$part) { - if (is_array($part)) { - if ($part === [Type::T_SELF]) { - $part = '&'; - } else { - $part = $this->revertSelfSelector($part); - } - } - } - - return $selectors; - } - - /** - * Flatten selector single; joins together .classes and #ids - * - * @param array $single - * - * @return array - */ - protected function flattenSelectorSingle($single) - { - $joined = []; - - foreach ($single as $part) { - if (empty($joined) || - ! is_string($part) || - preg_match('/[\[.:#%]/', $part) - ) { - $joined[] = $part; - continue; - } - - if (is_array(end($joined))) { - $joined[] = $part; - } else { - $joined[count($joined) - 1] .= $part; - } - } - - return $joined; - } - - /** - * Compile selector to string; self(&) should have been replaced by now - * - * @param string|array $selector - * - * @return string - */ - protected function compileSelector($selector) - { - if (! is_array($selector)) { - return $selector; // media and the like - } - - return implode( - ' ', - array_map( - [$this, 'compileSelectorPart'], - $selector - ) - ); - } - - /** - * Compile selector part - * - * @param array $piece - * - * @return string - */ - protected function compileSelectorPart($piece) - { - foreach ($piece as &$p) { - if (! is_array($p)) { - continue; - } - - switch ($p[0]) { - case Type::T_SELF: - $p = '&'; - break; - - default: - $p = $this->compileValue($p); - break; - } - } - - return implode($piece); - } - - /** - * Has selector placeholder? - * - * @param array $selector - * - * @return boolean - */ - protected function hasSelectorPlaceholder($selector) - { - if (! is_array($selector)) { - return false; - } - - foreach ($selector as $parts) { - foreach ($parts as $part) { - if (strlen($part) && '%' === $part[0]) { - return true; - } - } - } - - return false; - } - - protected function pushCallStack($name = '') - { - $this->callStack[] = [ - 'n' => $name, - Parser::SOURCE_INDEX => $this->sourceIndex, - Parser::SOURCE_LINE => $this->sourceLine, - Parser::SOURCE_COLUMN => $this->sourceColumn - ]; - - // infinite calling loop - if (count($this->callStack) > 25000) { - // not displayed but you can var_dump it to deep debug - $msg = $this->callStackMessage(true, 100); - $msg = "Infinite calling loop"; - $this->throwError($msg); - } - } - - protected function popCallStack() - { - array_pop($this->callStack); - } - - /** - * Compile children and return result - * - * @param array $stms - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * @param string $traceName - * - * @return array|null - */ - protected function compileChildren($stms, OutputBlock $out, $traceName = '') - { - $this->pushCallStack($traceName); - - foreach ($stms as $stm) { - $ret = $this->compileChild($stm, $out); - - if (isset($ret)) { - return $ret; - } - } - - $this->popCallStack(); - - return null; - } - - /** - * Compile children and throw exception if unexpected @return - * - * @param array $stms - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * @param \Leafo\ScssPhp\Block $selfParent - * @param string $traceName - * - * @throws \Exception - */ - protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent = null, $traceName = '') - { - $this->pushCallStack($traceName); - - foreach ($stms as $stm) { - if ($selfParent && isset($stm[1]) && is_object($stm[1]) && $stm[1] instanceof Block) { - $stm[1]->selfParent = $selfParent; - $ret = $this->compileChild($stm, $out); - $stm[1]->selfParent = null; - } elseif ($selfParent && $stm[0] === TYPE::T_INCLUDE) { - $stm['selfParent'] = $selfParent; - $ret = $this->compileChild($stm, $out); - unset($stm['selfParent']); - } else { - $ret = $this->compileChild($stm, $out); - } - - if (isset($ret)) { - $this->throwError('@return may only be used within a function'); - - return; - } - } - - $this->popCallStack(); - } - - - /** - * evaluate media query : compile internal value keeping the structure inchanged - * - * @param array $queryList - * - * @return array - */ - protected function evaluateMediaQuery($queryList) - { - foreach ($queryList as $kql => $query) { - foreach ($query as $kq => $q) { - for ($i = 1; $i < count($q); $i++) { - $value = $this->compileValue($q[$i]); - - // the parser had no mean to know if media type or expression if it was an interpolation - if ($q[0] == Type::T_MEDIA_TYPE && - (strpos($value, '(') !== false || - strpos($value, ')') !== false || - strpos($value, ':') !== false) - ) { - $queryList[$kql][$kq][0] = Type::T_MEDIA_EXPRESSION; - - if (strpos($value, 'and') !== false) { - $values = explode('and', $value); - $value = trim(array_pop($values)); - - while ($v = trim(array_pop($values))) { - $type = Type::T_MEDIA_EXPRESSION; - - if (strpos($v, '(') === false && - strpos($v, ')') === false && - strpos($v, ':') === false - ) { - $type = Type::T_MEDIA_TYPE; - } - - if (substr($v, 0, 1) === '(' && substr($v, -1) === ')') { - $v = substr($v, 1, -1); - } - - $queryList[$kql][] = [$type,[Type::T_KEYWORD, $v]]; - } - } - - if (substr($value, 0, 1) === '(' && substr($value, -1) === ')') { - $value = substr($value, 1, -1); - } - } - - $queryList[$kql][$kq][$i] = [Type::T_KEYWORD, $value]; - } - } - } - - return $queryList; - } - - /** - * Compile media query - * - * @param array $queryList - * - * @return array - */ - protected function compileMediaQuery($queryList) - { - $start = '@media '; - $default = trim($start); - $out = []; - $current = ""; - - foreach ($queryList as $query) { - $type = null; - $parts = []; - - $mediaTypeOnly = true; - - foreach ($query as $q) { - if ($q[0] !== Type::T_MEDIA_TYPE) { - $mediaTypeOnly = false; - break; - } - } - - foreach ($query as $q) { - switch ($q[0]) { - case Type::T_MEDIA_TYPE: - $newType = array_map([$this, 'compileValue'], array_slice($q, 1)); - // combining not and anything else than media type is too risky and should be avoided - if (! $mediaTypeOnly) { - if (in_array(Type::T_NOT, $newType) || ($type && in_array(Type::T_NOT, $type) )) { - if ($type) { - array_unshift($parts, implode(' ', array_filter($type))); - } - - if (! empty($parts)) { - if (strlen($current)) { - $current .= $this->formatter->tagSeparator; - } - - $current .= implode(' and ', $parts); - } - - if ($current) { - $out[] = $start . $current; - } - - $current = ""; - $type = null; - $parts = []; - } - } - - if ($newType === ['all'] && $default) { - $default = $start . 'all'; - } - - // all can be safely ignored and mixed with whatever else - if ($newType !== ['all']) { - if ($type) { - $type = $this->mergeMediaTypes($type, $newType); - - if (empty($type)) { - // merge failed : ignore this query that is not valid, skip to the next one - $parts = []; - $default = ''; // if everything fail, no @media at all - continue 3; - } - } else { - $type = $newType; - } - } - break; - - case Type::T_MEDIA_EXPRESSION: - if (isset($q[2])) { - $parts[] = '(' - . $this->compileValue($q[1]) - . $this->formatter->assignSeparator - . $this->compileValue($q[2]) - . ')'; - } else { - $parts[] = '(' - . $this->compileValue($q[1]) - . ')'; - } - break; - - case Type::T_MEDIA_VALUE: - $parts[] = $this->compileValue($q[1]); - break; - } - } - - if ($type) { - array_unshift($parts, implode(' ', array_filter($type))); - } - - if (! empty($parts)) { - if (strlen($current)) { - $current .= $this->formatter->tagSeparator; - } - - $current .= implode(' and ', $parts); - } - } - - if ($current) { - $out[] = $start . $current; - } - - // no @media type except all, and no conflict? - if (! $out && $default) { - $out[] = $default; - } - - return $out; - } - - /** - * Merge direct relationships between selectors - * - * @param array $selectors1 - * @param array $selectors2 - * - * @return array - */ - protected function mergeDirectRelationships($selectors1, $selectors2) - { - if (empty($selectors1) || empty($selectors2)) { - return array_merge($selectors1, $selectors2); - } - - $part1 = end($selectors1); - $part2 = end($selectors2); - - if (! $this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) { - return array_merge($selectors1, $selectors2); - } - - $merged = []; - - do { - $part1 = array_pop($selectors1); - $part2 = array_pop($selectors2); - - if (! $this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) { - if ($this->isImmediateRelationshipCombinator(reset($merged)[0])) { - array_unshift($merged, [$part1[0] . $part2[0]]); - $merged = array_merge($selectors1, $selectors2, $merged); - } else { - $merged = array_merge($selectors1, [$part1], $selectors2, [$part2], $merged); - } - - break; - } - - array_unshift($merged, $part1); - } while (! empty($selectors1) && ! empty($selectors2)); - - return $merged; - } - - /** - * Merge media types - * - * @param array $type1 - * @param array $type2 - * - * @return array|null - */ - protected function mergeMediaTypes($type1, $type2) - { - if (empty($type1)) { - return $type2; - } - - if (empty($type2)) { - return $type1; - } - - $m1 = ''; - $t1 = ''; - - if (count($type1) > 1) { - $m1= strtolower($type1[0]); - $t1= strtolower($type1[1]); - } else { - $t1 = strtolower($type1[0]); - } - - $m2 = ''; - $t2 = ''; - - if (count($type2) > 1) { - $m2 = strtolower($type2[0]); - $t2 = strtolower($type2[1]); - } else { - $t2 = strtolower($type2[0]); - } - - if (($m1 === Type::T_NOT) ^ ($m2 === Type::T_NOT)) { - if ($t1 === $t2) { - return null; - } - - return [ - $m1 === Type::T_NOT ? $m2 : $m1, - $m1 === Type::T_NOT ? $t2 : $t1, - ]; - } - - if ($m1 === Type::T_NOT && $m2 === Type::T_NOT) { - // CSS has no way of representing "neither screen nor print" - if ($t1 !== $t2) { - return null; - } - - return [Type::T_NOT, $t1]; - } - - if ($t1 !== $t2) { - return null; - } - - // t1 == t2, neither m1 nor m2 are "not" - return [empty($m1)? $m2 : $m1, $t1]; - } - - /** - * Compile import; returns true if the value was something that could be imported - * - * @param array $rawPath - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * @param boolean $once - * - * @return boolean - */ - protected function compileImport($rawPath, OutputBlock $out, $once = false) - { - if ($rawPath[0] === Type::T_STRING) { - $path = $this->compileStringContent($rawPath); - - if ($path = $this->findImport($path)) { - if (! $once || ! in_array($path, $this->importedFiles)) { - $this->importFile($path, $out); - $this->importedFiles[] = $path; - } - - return true; - } - - return false; - } - - if ($rawPath[0] === Type::T_LIST) { - // handle a list of strings - if (count($rawPath[2]) === 0) { - return false; - } - - foreach ($rawPath[2] as $path) { - if ($path[0] !== Type::T_STRING) { - return false; - } - } - - foreach ($rawPath[2] as $path) { - $this->compileImport($path, $out); - } - - return true; - } - - return false; - } - - /** - * Compile child; returns a value to halt execution - * - * @param array $child - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - * - * @return array - */ - protected function compileChild($child, OutputBlock $out) - { - if (isset($child[Parser::SOURCE_LINE])) { - $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null; - $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1; - $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1; - } elseif (is_array($child) && isset($child[1]->sourceLine)) { - $this->sourceIndex = $child[1]->sourceIndex; - $this->sourceLine = $child[1]->sourceLine; - $this->sourceColumn = $child[1]->sourceColumn; - } elseif (! empty($out->sourceLine) && ! empty($out->sourceName)) { - $this->sourceLine = $out->sourceLine; - $this->sourceIndex = array_search($out->sourceName, $this->sourceNames); - - if ($this->sourceIndex === false) { - $this->sourceIndex = null; - } - } - - switch ($child[0]) { - case Type::T_SCSSPHP_IMPORT_ONCE: - $rawPath = $this->reduce($child[1]); - - if (! $this->compileImport($rawPath, $out, true)) { - $out->lines[] = '@import ' . $this->compileValue($rawPath) . ';'; - } - break; - - case Type::T_IMPORT: - $rawPath = $this->reduce($child[1]); - - if (! $this->compileImport($rawPath, $out)) { - $out->lines[] = '@import ' . $this->compileValue($rawPath) . ';'; - } - break; - - case Type::T_DIRECTIVE: - $this->compileDirective($child[1]); - break; - - case Type::T_AT_ROOT: - $this->compileAtRoot($child[1]); - break; - - case Type::T_MEDIA: - $this->compileMedia($child[1]); - break; - - case Type::T_BLOCK: - $this->compileBlock($child[1]); - break; - - case Type::T_CHARSET: - if (! $this->charsetSeen) { - $this->charsetSeen = true; - - $out->lines[] = '@charset ' . $this->compileValue($child[1]) . ';'; - } - break; - - case Type::T_ASSIGN: - list(, $name, $value) = $child; - - if ($name[0] === Type::T_VARIABLE) { - $flags = isset($child[3]) ? $child[3] : []; - $isDefault = in_array('!default', $flags); - $isGlobal = in_array('!global', $flags); - - if ($isGlobal) { - $this->set($name[1], $this->reduce($value), false, $this->rootEnv, $value); - break; - } - - $shouldSet = $isDefault && - (($result = $this->get($name[1], false)) === null - || $result === static::$null); - - if (! $isDefault || $shouldSet) { - $this->set($name[1], $this->reduce($value), true, null, $value); - } - break; - } - - $compiledName = $this->compileValue($name); - - // handle shorthand syntax: size / line-height - if ($compiledName === 'font' || $compiledName === 'grid-row' || $compiledName === 'grid-column') { - if ($value[0] === Type::T_VARIABLE) { - // if the font value comes from variable, the content is already reduced - // (i.e., formulas were already calculated), so we need the original unreduced value - $value = $this->get($value[1], true, null, true); - } - - $fontValue=&$value; - - if ($value[0] === Type::T_LIST && $value[1]==',') { - // this is the case if more than one font is given: example: "font: 400 1em/1.3 arial,helvetica" - // we need to handle the first list element - $fontValue=&$value[2][0]; - } - - if ($fontValue[0] === Type::T_EXPRESSION && $fontValue[1] === '/') { - $fontValue = $this->expToString($fontValue); - } elseif ($fontValue[0] === Type::T_LIST) { - foreach ($fontValue[2] as &$item) { - if ($item[0] === Type::T_EXPRESSION && $item[1] === '/') { - $item = $this->expToString($item); - } - } - } - } - - // if the value reduces to null from something else then - // the property should be discarded - if ($value[0] !== Type::T_NULL) { - $value = $this->reduce($value); - - if ($value[0] === Type::T_NULL || $value === static::$nullString) { - break; - } - } - - $compiledValue = $this->compileValue($value); - - $out->lines[] = $this->formatter->property( - $compiledName, - $compiledValue - ); - break; - - case Type::T_COMMENT: - if ($out->type === Type::T_ROOT) { - $this->compileComment($child); - break; - } - - $out->lines[] = $child[1]; - break; - - case Type::T_MIXIN: - case Type::T_FUNCTION: - list(, $block) = $child; - - $this->set(static::$namespaces[$block->type] . $block->name, $block); - break; - - case Type::T_EXTEND: - foreach ($child[1] as $sel) { - $results = $this->evalSelectors([$sel]); - - foreach ($results as $result) { - // only use the first one - $result = current($result); - - $this->pushExtends($result, $out->selectors, $child); - } - } - break; - - case Type::T_IF: - list(, $if) = $child; - - if ($this->isTruthy($this->reduce($if->cond, true))) { - return $this->compileChildren($if->children, $out); - } - - foreach ($if->cases as $case) { - if ($case->type === Type::T_ELSE || - $case->type === Type::T_ELSEIF && $this->isTruthy($this->reduce($case->cond)) - ) { - return $this->compileChildren($case->children, $out); - } - } - break; - - case Type::T_EACH: - list(, $each) = $child; - - $list = $this->coerceList($this->reduce($each->list)); - - $this->pushEnv(); - - foreach ($list[2] as $item) { - if (count($each->vars) === 1) { - $this->set($each->vars[0], $item, true); - } else { - list(,, $values) = $this->coerceList($item); - - foreach ($each->vars as $i => $var) { - $this->set($var, isset($values[$i]) ? $values[$i] : static::$null, true); - } - } - - $ret = $this->compileChildren($each->children, $out); - - if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - $this->popEnv(); - - return $ret; - } - - if ($ret[1]) { - break; - } - } - } - - $this->popEnv(); - break; - - case Type::T_WHILE: - list(, $while) = $child; - - while ($this->isTruthy($this->reduce($while->cond, true))) { - $ret = $this->compileChildren($while->children, $out); - - if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - return $ret; - } - - if ($ret[1]) { - break; - } - } - } - break; - - case Type::T_FOR: - list(, $for) = $child; - - $start = $this->reduce($for->start, true); - $end = $this->reduce($for->end, true); - - if (! ($start[2] == $end[2] || $end->unitless())) { - $this->throwError('Incompatible units: "%s" and "%s".', $start->unitStr(), $end->unitStr()); - - break; - } - - $unit = $start[2]; - $start = $start[1]; - $end = $end[1]; - - $d = $start < $end ? 1 : -1; - - for (;;) { - if ((! $for->until && $start - $d == $end) || - ($for->until && $start == $end) - ) { - break; - } - - $this->set($for->var, new Node\Number($start, $unit)); - $start += $d; - - $ret = $this->compileChildren($for->children, $out); - - if ($ret) { - if ($ret[0] !== Type::T_CONTROL) { - return $ret; - } - - if ($ret[1]) { - break; - } - } - } - break; - - case Type::T_BREAK: - return [Type::T_CONTROL, true]; - - case Type::T_CONTINUE: - return [Type::T_CONTROL, false]; - - case Type::T_RETURN: - return $this->reduce($child[1], true); - - case Type::T_NESTED_PROPERTY: - list(, $prop) = $child; - - $prefixed = []; - $prefix = $this->compileValue($prop->prefix) . '-'; - - foreach ($prop->children as $child) { - switch ($child[0]) { - case Type::T_ASSIGN: - array_unshift($child[1][2], $prefix); - break; - - case Type::T_NESTED_PROPERTY: - array_unshift($child[1]->prefix[2], $prefix); - break; - } - - $prefixed[] = $child; - } - - $this->compileChildrenNoReturn($prefixed, $out); - break; - - case Type::T_INCLUDE: - // including a mixin - list(, $name, $argValues, $content) = $child; - - $mixin = $this->get(static::$namespaces['mixin'] . $name, false); - - if (! $mixin) { - $this->throwError("Undefined mixin $name"); - break; - } - - $callingScope = $this->getStoreEnv(); - - // push scope, apply args - $this->pushEnv(); - $this->env->depth--; - - $storeEnv = $this->storeEnv; - $this->storeEnv = $this->env; - - // Find the parent selectors in the env to be able to know what '&' refers to in the mixin - // and assign this fake parent to childs - $selfParent = null; - - if (isset($child['selfParent']) && isset($child['selfParent']->selectors)) { - $selfParent = $child['selfParent']; - } else { - $parentSelectors = $this->multiplySelectors($this->env); - - if ($parentSelectors) { - $parent = new Block(); - $parent->selectors = $parentSelectors; - - foreach ($mixin->children as $k => $child) { - if (isset($child[1]) && is_object($child[1]) && $child[1] instanceof Block) { - $mixin->children[$k][1]->parent = $parent; - } - } - } - } - - // clone the stored content to not have its scope spoiled by a further call to the same mixin - // i.e., recursive @include of the same mixin - if (isset($content)) { - $copyContent = clone $content; - $copyContent->scope = $callingScope; - - $this->setRaw(static::$namespaces['special'] . 'content', $copyContent, $this->env); - } - - if (isset($mixin->args)) { - $this->applyArguments($mixin->args, $argValues); - } - - $this->env->marker = 'mixin'; - - $this->compileChildrenNoReturn($mixin->children, $out, $selfParent, $this->env->marker . " " . $name); - - $this->storeEnv = $storeEnv; - - $this->popEnv(); - break; - - case Type::T_MIXIN_CONTENT: - $env = isset($this->storeEnv) ? $this->storeEnv : $this->env; - $content = $this->get(static::$namespaces['special'] . 'content', false, $env); - - if (! $content) { - $content = new \stdClass(); - $content->scope = new \stdClass(); - $content->children = $this->storeEnv->parent->block->children; - break; - } - - $storeEnv = $this->storeEnv; - $this->storeEnv = $content->scope; - $this->compileChildrenNoReturn($content->children, $out); - - $this->storeEnv = $storeEnv; - break; - - case Type::T_DEBUG: - list(, $value) = $child; - - $fname = $this->sourceNames[$this->sourceIndex]; - $line = $this->sourceLine; - $value = $this->compileValue($this->reduce($value, true)); - fwrite($this->stderr, "File $fname on line $line DEBUG: $value\n"); - break; - - case Type::T_WARN: - list(, $value) = $child; - - $fname = $this->sourceNames[$this->sourceIndex]; - $line = $this->sourceLine; - $value = $this->compileValue($this->reduce($value, true)); - fwrite($this->stderr, "File $fname on line $line WARN: $value\n"); - break; - - case Type::T_ERROR: - list(, $value) = $child; - - $fname = $this->sourceNames[$this->sourceIndex]; - $line = $this->sourceLine; - $value = $this->compileValue($this->reduce($value, true)); - $this->throwError("File $fname on line $line ERROR: $value\n"); - break; - - case Type::T_CONTROL: - $this->throwError('@break/@continue not permitted in this scope'); - break; - - default: - $this->throwError("unknown child type: $child[0]"); - } - } - - /** - * Reduce expression to string - * - * @param array $exp - * - * @return array - */ - protected function expToString($exp) - { - list(, $op, $left, $right, /* $inParens */, $whiteLeft, $whiteRight) = $exp; - - $content = [$this->reduce($left)]; - - if ($whiteLeft) { - $content[] = ' '; - } - - $content[] = $op; - - if ($whiteRight) { - $content[] = ' '; - } - - $content[] = $this->reduce($right); - - return [Type::T_STRING, '', $content]; - } - - /** - * Is truthy? - * - * @param array $value - * - * @return boolean - */ - protected function isTruthy($value) - { - return $value !== static::$false && $value !== static::$null; - } - - /** - * Is the value a direct relationship combinator? - * - * @param string $value - * - * @return boolean - */ - protected function isImmediateRelationshipCombinator($value) - { - return $value === '>' || $value === '+' || $value === '~'; - } - - /** - * Should $value cause its operand to eval - * - * @param array $value - * - * @return boolean - */ - protected function shouldEval($value) - { - switch ($value[0]) { - case Type::T_EXPRESSION: - if ($value[1] === '/') { - return $this->shouldEval($value[2]) || $this->shouldEval($value[3]); - } - - // fall-thru - case Type::T_VARIABLE: - case Type::T_FUNCTION_CALL: - return true; - } - - return false; - } - - /** - * Reduce value - * - * @param array $value - * @param boolean $inExp - * - * @return array|\Leafo\ScssPhp\Node\Number - */ - protected function reduce($value, $inExp = false) - { - - switch ($value[0]) { - case Type::T_EXPRESSION: - list(, $op, $left, $right, $inParens) = $value; - - $opName = isset(static::$operatorNames[$op]) ? static::$operatorNames[$op] : $op; - $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right); - - $left = $this->reduce($left, true); - - if ($op !== 'and' && $op !== 'or') { - $right = $this->reduce($right, true); - } - - // special case: looks like css shorthand - if ($opName == 'div' && ! $inParens && ! $inExp && isset($right[2]) - && (($right[0] !== Type::T_NUMBER && $right[2] != '') - || ($right[0] === Type::T_NUMBER && ! $right->unitless())) - ) { - return $this->expToString($value); - } - - $left = $this->coerceForExpression($left); - $right = $this->coerceForExpression($right); - - $ltype = $left[0]; - $rtype = $right[0]; - - $ucOpName = ucfirst($opName); - $ucLType = ucfirst($ltype); - $ucRType = ucfirst($rtype); - - // this tries: - // 1. op[op name][left type][right type] - // 2. op[left type][right type] (passing the op as first arg - // 3. op[op name] - $fn = "op${ucOpName}${ucLType}${ucRType}"; - - if (is_callable([$this, $fn]) || - (($fn = "op${ucLType}${ucRType}") && - is_callable([$this, $fn]) && - $passOp = true) || - (($fn = "op${ucOpName}") && - is_callable([$this, $fn]) && - $genOp = true) - ) { - $coerceUnit = false; - - if (! isset($genOp) && - $left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER - ) { - $coerceUnit = true; - - switch ($opName) { - case 'mul': - $targetUnit = $left[2]; - - foreach ($right[2] as $unit => $exp) { - $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) + $exp; - } - break; - - case 'div': - $targetUnit = $left[2]; - - foreach ($right[2] as $unit => $exp) { - $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) - $exp; - } - break; - - case 'mod': - $targetUnit = $left[2]; - break; - - default: - $targetUnit = $left->unitless() ? $right[2] : $left[2]; - } - - if (! $left->unitless() && ! $right->unitless()) { - $left = $left->normalize(); - $right = $right->normalize(); - } - } - - $shouldEval = $inParens || $inExp; - - if (isset($passOp)) { - $out = $this->$fn($op, $left, $right, $shouldEval); - } else { - $out = $this->$fn($left, $right, $shouldEval); - } - - if (isset($out)) { - if ($coerceUnit && $out[0] === Type::T_NUMBER) { - $out = $out->coerce($targetUnit); - } - - return $out; - } - } - - return $this->expToString($value); - - case Type::T_UNARY: - list(, $op, $exp, $inParens) = $value; - - $inExp = $inExp || $this->shouldEval($exp); - $exp = $this->reduce($exp); - - if ($exp[0] === Type::T_NUMBER) { - switch ($op) { - case '+': - return new Node\Number($exp[1], $exp[2]); - - case '-': - return new Node\Number(-$exp[1], $exp[2]); - } - } - - if ($op === 'not') { - if ($inExp || $inParens) { - if ($exp === static::$false || $exp === static::$null) { - return static::$true; - } - - return static::$false; - } - - $op = $op . ' '; - } - - return [Type::T_STRING, '', [$op, $exp]]; - - case Type::T_VARIABLE: - return $this->reduce($this->get($value[1])); - - case Type::T_LIST: - foreach ($value[2] as &$item) { - $item = $this->reduce($item); - } - - return $value; - - case Type::T_MAP: - foreach ($value[1] as &$item) { - $item = $this->reduce($item); - } - - foreach ($value[2] as &$item) { - $item = $this->reduce($item); - } - - return $value; - - case Type::T_STRING: - foreach ($value[2] as &$item) { - if (is_array($item) || $item instanceof \ArrayAccess) { - $item = $this->reduce($item); - } - } - - return $value; - - case Type::T_INTERPOLATE: - $value[1] = $this->reduce($value[1]); - if ($inExp) { - return $value[1]; - } - - return $value; - - case Type::T_FUNCTION_CALL: - return $this->fncall($value[1], $value[2]); - - case Type::T_SELF: - $selfSelector = $this->multiplySelectors($this->env); - $selfSelector = $this->collapseSelectors($selfSelector, true); - return $selfSelector; - - default: - return $value; - } - } - - /** - * Function caller - * - * @param string $name - * @param array $argValues - * - * @return array|null - */ - protected function fncall($name, $argValues) - { - // SCSS @function - if ($this->callScssFunction($name, $argValues, $returnValue)) { - return $returnValue; - } - - // native PHP functions - if ($this->callNativeFunction($name, $argValues, $returnValue)) { - return $returnValue; - } - - // for CSS functions, simply flatten the arguments into a list - $listArgs = []; - - foreach ((array) $argValues as $arg) { - if (empty($arg[0])) { - $listArgs[] = $this->reduce($arg[1]); - } - } - - return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', $listArgs]]; - } - - /** - * Normalize name - * - * @param string $name - * - * @return string - */ - protected function normalizeName($name) - { - return str_replace('-', '_', $name); - } - - /** - * Normalize value - * - * @param array $value - * - * @return array - */ - public function normalizeValue($value) - { - $value = $this->coerceForExpression($this->reduce($value)); - - switch ($value[0]) { - case Type::T_LIST: - $value = $this->extractInterpolation($value); - - if ($value[0] !== Type::T_LIST) { - return [Type::T_KEYWORD, $this->compileValue($value)]; - } - - foreach ($value[2] as $key => $item) { - $value[2][$key] = $this->normalizeValue($item); - } - - return $value; - - case Type::T_STRING: - return [$value[0], '"', [$this->compileStringContent($value)]]; - - case Type::T_NUMBER: - return $value->normalize(); - - case Type::T_INTERPOLATE: - return [Type::T_KEYWORD, $this->compileValue($value)]; - - default: - return $value; - } - } - - /** - * Add numbers - * - * @param array $left - * @param array $right - * - * @return \Leafo\ScssPhp\Node\Number - */ - protected function opAddNumberNumber($left, $right) - { - return new Node\Number($left[1] + $right[1], $left[2]); - } - - /** - * Multiply numbers - * - * @param array $left - * @param array $right - * - * @return \Leafo\ScssPhp\Node\Number - */ - protected function opMulNumberNumber($left, $right) - { - return new Node\Number($left[1] * $right[1], $left[2]); - } - - /** - * Subtract numbers - * - * @param array $left - * @param array $right - * - * @return \Leafo\ScssPhp\Node\Number - */ - protected function opSubNumberNumber($left, $right) - { - return new Node\Number($left[1] - $right[1], $left[2]); - } - - /** - * Divide numbers - * - * @param array $left - * @param array $right - * - * @return array|\Leafo\ScssPhp\Node\Number - */ - protected function opDivNumberNumber($left, $right) - { - if ($right[1] == 0) { - return [Type::T_STRING, '', [$left[1] . $left[2] . '/' . $right[1] . $right[2]]]; - } - - return new Node\Number($left[1] / $right[1], $left[2]); - } - - /** - * Mod numbers - * - * @param array $left - * @param array $right - * - * @return \Leafo\ScssPhp\Node\Number - */ - protected function opModNumberNumber($left, $right) - { - return new Node\Number($left[1] % $right[1], $left[2]); - } - - /** - * Add strings - * - * @param array $left - * @param array $right - * - * @return array|null - */ - protected function opAdd($left, $right) - { - if ($strLeft = $this->coerceString($left)) { - if ($right[0] === Type::T_STRING) { - $right[1] = ''; - } - - $strLeft[2][] = $right; - - return $strLeft; - } - - if ($strRight = $this->coerceString($right)) { - if ($left[0] === Type::T_STRING) { - $left[1] = ''; - } - - array_unshift($strRight[2], $left); - - return $strRight; - } - - return null; - } - - /** - * Boolean and - * - * @param array $left - * @param array $right - * @param boolean $shouldEval - * - * @return array|null - */ - protected function opAnd($left, $right, $shouldEval) - { - $truthy = ($left === static::$null || $right === static::$null) || - ($left === static::$false || $left === static::$true) && - ($right === static::$false || $right === static::$true); - - if (! $shouldEval) { - if (! $truthy) { - return null; - } - } - - if ($left !== static::$false && $left !== static::$null) { - return $this->reduce($right, true); - } - - return $left; - } - - /** - * Boolean or - * - * @param array $left - * @param array $right - * @param boolean $shouldEval - * - * @return array|null - */ - protected function opOr($left, $right, $shouldEval) - { - $truthy = ($left === static::$null || $right === static::$null) || - ($left === static::$false || $left === static::$true) && - ($right === static::$false || $right === static::$true); - - if (! $shouldEval) { - if (! $truthy) { - return null; - } - } - - if ($left !== static::$false && $left !== static::$null) { - return $left; - } - - return $this->reduce($right, true); - } - - /** - * Compare colors - * - * @param string $op - * @param array $left - * @param array $right - * - * @return array - */ - protected function opColorColor($op, $left, $right) - { - $out = [Type::T_COLOR]; - - foreach ([1, 2, 3] as $i) { - $lval = isset($left[$i]) ? $left[$i] : 0; - $rval = isset($right[$i]) ? $right[$i] : 0; - - switch ($op) { - case '+': - $out[] = $lval + $rval; - break; - - case '-': - $out[] = $lval - $rval; - break; - - case '*': - $out[] = $lval * $rval; - break; - - case '%': - $out[] = $lval % $rval; - break; - - case '/': - if ($rval == 0) { - $this->throwError("color: Can't divide by zero"); - break 2; - } - - $out[] = (int) ($lval / $rval); - break; - - case '==': - return $this->opEq($left, $right); - - case '!=': - return $this->opNeq($left, $right); - - default: - $this->throwError("color: unknown op $op"); - break 2; - } - } - - if (isset($left[4])) { - $out[4] = $left[4]; - } elseif (isset($right[4])) { - $out[4] = $right[4]; - } - - return $this->fixColor($out); - } - - /** - * Compare color and number - * - * @param string $op - * @param array $left - * @param array $right - * - * @return array - */ - protected function opColorNumber($op, $left, $right) - { - $value = $right[1]; - - return $this->opColorColor( - $op, - $left, - [Type::T_COLOR, $value, $value, $value] - ); - } - - /** - * Compare number and color - * - * @param string $op - * @param array $left - * @param array $right - * - * @return array - */ - protected function opNumberColor($op, $left, $right) - { - $value = $left[1]; - - return $this->opColorColor( - $op, - [Type::T_COLOR, $value, $value, $value], - $right - ); - } - - /** - * Compare number1 == number2 - * - * @param array $left - * @param array $right - * - * @return array - */ - protected function opEq($left, $right) - { - if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) { - $lStr[1] = ''; - $rStr[1] = ''; - - $left = $this->compileValue($lStr); - $right = $this->compileValue($rStr); - } - - return $this->toBool($left === $right); - } - - /** - * Compare number1 != number2 - * - * @param array $left - * @param array $right - * - * @return array - */ - protected function opNeq($left, $right) - { - if (($lStr = $this->coerceString($left)) && ($rStr = $this->coerceString($right))) { - $lStr[1] = ''; - $rStr[1] = ''; - - $left = $this->compileValue($lStr); - $right = $this->compileValue($rStr); - } - - return $this->toBool($left !== $right); - } - - /** - * Compare number1 >= number2 - * - * @param array $left - * @param array $right - * - * @return array - */ - protected function opGteNumberNumber($left, $right) - { - return $this->toBool($left[1] >= $right[1]); - } - - /** - * Compare number1 > number2 - * - * @param array $left - * @param array $right - * - * @return array - */ - protected function opGtNumberNumber($left, $right) - { - return $this->toBool($left[1] > $right[1]); - } - - /** - * Compare number1 <= number2 - * - * @param array $left - * @param array $right - * - * @return array - */ - protected function opLteNumberNumber($left, $right) - { - return $this->toBool($left[1] <= $right[1]); - } - - /** - * Compare number1 < number2 - * - * @param array $left - * @param array $right - * - * @return array - */ - protected function opLtNumberNumber($left, $right) - { - return $this->toBool($left[1] < $right[1]); - } - - /** - * Three-way comparison, aka spaceship operator - * - * @param array $left - * @param array $right - * - * @return \Leafo\ScssPhp\Node\Number - */ - protected function opCmpNumberNumber($left, $right) - { - $n = $left[1] - $right[1]; - - return new Node\Number($n ? $n / abs($n) : 0, ''); - } - - /** - * Cast to boolean - * - * @api - * - * @param mixed $thing - * - * @return array - */ - public function toBool($thing) - { - return $thing ? static::$true : static::$false; - } - - /** - * Compiles a primitive value into a CSS property value. - * - * Values in scssphp are typed by being wrapped in arrays, their format is - * typically: - * - * array(type, contents [, additional_contents]*) - * - * The input is expected to be reduced. This function will not work on - * things like expressions and variables. - * - * @api - * - * @param array $value - * - * @return string - */ - public function compileValue($value) - { - $value = $this->reduce($value); - - switch ($value[0]) { - case Type::T_KEYWORD: - return $value[1]; - - case Type::T_COLOR: - // [1] - red component (either number for a %) - // [2] - green component - // [3] - blue component - // [4] - optional alpha component - list(, $r, $g, $b) = $value; - - $r = round($r); - $g = round($g); - $b = round($b); - - if (count($value) === 5 && $value[4] !== 1) { // rgba - $a = new Node\Number($value[4], ''); - - return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')'; - } - - $h = sprintf('#%02x%02x%02x', $r, $g, $b); - - // Converting hex color to short notation (e.g. #003399 to #039) - if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) { - $h = '#' . $h[1] . $h[3] . $h[5]; - } - - return $h; - - case Type::T_NUMBER: - return $value->output($this); - - case Type::T_STRING: - return $value[1] . $this->compileStringContent($value) . $value[1]; - - case Type::T_FUNCTION: - $args = ! empty($value[2]) ? $this->compileValue($value[2]) : ''; - - return "$value[1]($args)"; - - case Type::T_LIST: - $value = $this->extractInterpolation($value); - - if ($value[0] !== Type::T_LIST) { - return $this->compileValue($value); - } - - list(, $delim, $items) = $value; - - if ($delim !== ' ') { - $delim .= ' '; - } - - $filtered = []; - - foreach ($items as $item) { - if ($item[0] === Type::T_NULL) { - continue; - } - - $filtered[] = $this->compileValue($item); - } - - return implode("$delim", $filtered); - - case Type::T_MAP: - $keys = $value[1]; - $values = $value[2]; - $filtered = []; - - for ($i = 0, $s = count($keys); $i < $s; $i++) { - $filtered[$this->compileValue($keys[$i])] = $this->compileValue($values[$i]); - } - - array_walk($filtered, function (&$value, $key) { - $value = $key . ': ' . $value; - }); - - return '(' . implode(', ', $filtered) . ')'; - - case Type::T_INTERPOLATED: - // node created by extractInterpolation - list(, $interpolate, $left, $right) = $value; - list(,, $whiteLeft, $whiteRight) = $interpolate; - - $left = count($left[2]) > 0 ? - $this->compileValue($left) . $whiteLeft : ''; - - $right = count($right[2]) > 0 ? - $whiteRight . $this->compileValue($right) : ''; - - return $left . $this->compileValue($interpolate) . $right; - - case Type::T_INTERPOLATE: - // strip quotes if it's a string - $reduced = $this->reduce($value[1]); - - switch ($reduced[0]) { - case Type::T_LIST: - $reduced = $this->extractInterpolation($reduced); - - if ($reduced[0] !== Type::T_LIST) { - break; - } - - list(, $delim, $items) = $reduced; - - if ($delim !== ' ') { - $delim .= ' '; - } - - $filtered = []; - - foreach ($items as $item) { - if ($item[0] === Type::T_NULL) { - continue; - } - - $temp = $this->compileValue([Type::T_KEYWORD, $item]); - if ($temp[0] === Type::T_STRING) { - $filtered[] = $this->compileStringContent($temp); - } elseif ($temp[0] === Type::T_KEYWORD) { - $filtered[] = $temp[1]; - } else { - $filtered[] = $this->compileValue($temp); - } - } - - $reduced = [Type::T_KEYWORD, implode("$delim", $filtered)]; - break; - - case Type::T_STRING: - $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)]; - break; - - case Type::T_NULL: - $reduced = [Type::T_KEYWORD, '']; - } - - return $this->compileValue($reduced); - - case Type::T_NULL: - return 'null'; - - default: - $this->throwError("unknown value type: $value[0]"); - } - } - - /** - * Flatten list - * - * @param array $list - * - * @return string - */ - protected function flattenList($list) - { - return $this->compileValue($list); - } - - /** - * Compile string content - * - * @param array $string - * - * @return string - */ - protected function compileStringContent($string) - { - $parts = []; - - foreach ($string[2] as $part) { - if (is_array($part) || $part instanceof \ArrayAccess) { - $parts[] = $this->compileValue($part); - } else { - $parts[] = $part; - } - } - - return implode($parts); - } - - /** - * Extract interpolation; it doesn't need to be recursive, compileValue will handle that - * - * @param array $list - * - * @return array - */ - protected function extractInterpolation($list) - { - $items = $list[2]; - - foreach ($items as $i => $item) { - if ($item[0] === Type::T_INTERPOLATE) { - $before = [Type::T_LIST, $list[1], array_slice($items, 0, $i)]; - $after = [Type::T_LIST, $list[1], array_slice($items, $i + 1)]; - - return [Type::T_INTERPOLATED, $item, $before, $after]; - } - } - - return $list; - } - - /** - * Find the final set of selectors - * - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param \Leafo\ScssPhp\Block $selfParent - * - * @return array - */ - protected function multiplySelectors(Environment $env, $selfParent = null) - { - $envs = $this->compactEnv($env); - $selectors = []; - $parentSelectors = [[]]; - - $selfParentSelectors = null; - - if (! is_null($selfParent) && $selfParent->selectors) { - $selfParentSelectors = $this->evalSelectors($selfParent->selectors); - } - - while ($env = array_pop($envs)) { - if (empty($env->selectors)) { - continue; - } - - $selectors = $env->selectors; - - do { - $stillHasSelf = false; - $prevSelectors = $selectors; - $selectors = []; - - foreach ($prevSelectors as $selector) { - foreach ($parentSelectors as $parent) { - if ($selfParentSelectors) { - foreach ($selfParentSelectors as $selfParent) { - // if no '&' in the selector, each call will give same result, only add once - $s = $this->joinSelectors($parent, $selector, $stillHasSelf, $selfParent); - $selectors[serialize($s)] = $s; - } - } else { - $s = $this->joinSelectors($parent, $selector, $stillHasSelf); - $selectors[serialize($s)] = $s; - } - } - } - } while ($stillHasSelf); - - $parentSelectors = $selectors; - } - - $selectors = array_values($selectors); - - return $selectors; - } - - /** - * Join selectors; looks for & to replace, or append parent before child - * - * @param array $parent - * @param array $child - * @param boolean &$stillHasSelf - * @param array $selfParentSelectors - - * @return array - */ - protected function joinSelectors($parent, $child, &$stillHasSelf, $selfParentSelectors = null) - { - $setSelf = false; - $out = []; - - foreach ($child as $part) { - $newPart = []; - - foreach ($part as $p) { - // only replace & once and should be recalled to be able to make combinations - if ($p === static::$selfSelector && $setSelf) { - $stillHasSelf = true; - } - - if ($p === static::$selfSelector && ! $setSelf) { - $setSelf = true; - - if (is_null($selfParentSelectors)) { - $selfParentSelectors = $parent; - } - - foreach ($selfParentSelectors as $i => $parentPart) { - if ($i > 0) { - $out[] = $newPart; - $newPart = []; - } - - foreach ($parentPart as $pp) { - if (is_array($pp)) { - $flatten = []; - array_walk_recursive($pp, function ($a) use (&$flatten) { - $flatten[] = $a; - }); - $pp = implode($flatten); - } - - $newPart[] = $pp; - } - } - } else { - $newPart[] = $p; - } - } - - $out[] = $newPart; - } - - return $setSelf ? $out : array_merge($parent, $child); - } - - /** - * Multiply media - * - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param array $childQueries - * - * @return array - */ - protected function multiplyMedia(Environment $env = null, $childQueries = null) - { - if (! isset($env) || - ! empty($env->block->type) && $env->block->type !== Type::T_MEDIA - ) { - return $childQueries; - } - - // plain old block, skip - if (empty($env->block->type)) { - return $this->multiplyMedia($env->parent, $childQueries); - } - - $parentQueries = isset($env->block->queryList) - ? $env->block->queryList - : [[[Type::T_MEDIA_VALUE, $env->block->value]]]; - - $store = [$this->env, $this->storeEnv]; - $this->env = $env; - $this->storeEnv = null; - $parentQueries = $this->evaluateMediaQuery($parentQueries); - list($this->env, $this->storeEnv) = $store; - - if ($childQueries === null) { - $childQueries = $parentQueries; - } else { - $originalQueries = $childQueries; - $childQueries = []; - - foreach ($parentQueries as $parentQuery) { - foreach ($originalQueries as $childQuery) { - $childQueries[] = array_merge( - $parentQuery, - [[Type::T_MEDIA_TYPE, [Type::T_KEYWORD, 'all']]], - $childQuery - ); - } - } - } - - return $this->multiplyMedia($env->parent, $childQueries); - } - - /** - * Convert env linked list to stack - * - * @param \Leafo\ScssPhp\Compiler\Environment $env - * - * @return array - */ - protected function compactEnv(Environment $env) - { - for ($envs = []; $env; $env = $env->parent) { - $envs[] = $env; - } - - return $envs; - } - - /** - * Convert env stack to singly linked list - * - * @param array $envs - * - * @return \Leafo\ScssPhp\Compiler\Environment - */ - protected function extractEnv($envs) - { - for ($env = null; $e = array_pop($envs);) { - $e->parent = $env; - $env = $e; - } - - return $env; - } - - /** - * Push environment - * - * @param \Leafo\ScssPhp\Block $block - * - * @return \Leafo\ScssPhp\Compiler\Environment - */ - protected function pushEnv(Block $block = null) - { - $env = new Environment; - $env->parent = $this->env; - $env->store = []; - $env->block = $block; - $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0; - - $this->env = $env; - - return $env; - } - - /** - * Pop environment - */ - protected function popEnv() - { - $this->env = $this->env->parent; - } - - /** - * Get store environment - * - * @return \Leafo\ScssPhp\Compiler\Environment - */ - protected function getStoreEnv() - { - return isset($this->storeEnv) ? $this->storeEnv : $this->env; - } - - /** - * Set variable - * - * @param string $name - * @param mixed $value - * @param boolean $shadow - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced - */ - protected function set($name, $value, $shadow = false, Environment $env = null, $valueUnreduced = null) - { - $name = $this->normalizeName($name); - - if (! isset($env)) { - $env = $this->getStoreEnv(); - } - - if ($shadow) { - $this->setRaw($name, $value, $env, $valueUnreduced); - } else { - $this->setExisting($name, $value, $env, $valueUnreduced); - } - } - - /** - * Set existing variable - * - * @param string $name - * @param mixed $value - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced - */ - protected function setExisting($name, $value, Environment $env, $valueUnreduced = null) - { - $storeEnv = $env; - - $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%'; - - for (;;) { - if (array_key_exists($name, $env->store)) { - break; - } - - if (! $hasNamespace && isset($env->marker)) { - $env = $storeEnv; - break; - } - - if (! isset($env->parent)) { - $env = $storeEnv; - break; - } - - $env = $env->parent; - } - - $env->store[$name] = $value; - - if ($valueUnreduced) { - $env->storeUnreduced[$name] = $valueUnreduced; - } - } - - /** - * Set raw variable - * - * @param string $name - * @param mixed $value - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param mixed $valueUnreduced - */ - protected function setRaw($name, $value, Environment $env, $valueUnreduced = null) - { - $env->store[$name] = $value; - - if ($valueUnreduced) { - $env->storeUnreduced[$name] = $valueUnreduced; - } - } - - /** - * Get variable - * - * @api - * - * @param string $name - * @param boolean $shouldThrow - * @param \Leafo\ScssPhp\Compiler\Environment $env - * @param boolean $unreduced - * - * @return mixed|null - */ - public function get($name, $shouldThrow = true, Environment $env = null, $unreduced = false) - { - $normalizedName = $this->normalizeName($name); - $specialContentKey = static::$namespaces['special'] . 'content'; - - if (! isset($env)) { - $env = $this->getStoreEnv(); - } - - $nextIsRoot = false; - $hasNamespace = $normalizedName[0] === '^' || $normalizedName[0] === '@' || $normalizedName[0] === '%'; - - $maxDepth = 10000; - - for (;;) { - if ($maxDepth-- <= 0) { - break; - } - - if (array_key_exists($normalizedName, $env->store)) { - if ($unreduced && isset($env->storeUnreduced[$normalizedName])) { - return $env->storeUnreduced[$normalizedName]; - } - - return $env->store[$normalizedName]; - } - - if (! $hasNamespace && isset($env->marker)) { - if (! $nextIsRoot && ! empty($env->store[$specialContentKey])) { - $env = $env->store[$specialContentKey]->scope; - continue; - } - - $env = $this->rootEnv; - continue; - } - - if (! isset($env->parent)) { - break; - } - - $env = $env->parent; - } - - if ($shouldThrow) { - $this->throwError("Undefined variable \$$name" . ($maxDepth<=0 ? " (infinite recursion)" : "")); - } - - // found nothing - return null; - } - - /** - * Has variable? - * - * @param string $name - * @param \Leafo\ScssPhp\Compiler\Environment $env - * - * @return boolean - */ - protected function has($name, Environment $env = null) - { - return $this->get($name, false, $env) !== null; - } - - /** - * Inject variables - * - * @param array $args - */ - protected function injectVariables(array $args) - { - if (empty($args)) { - return; - } - - $parser = $this->parserFactory(__METHOD__); - - foreach ($args as $name => $strValue) { - if ($name[0] === '$') { - $name = substr($name, 1); - } - - if (! $parser->parseValue($strValue, $value)) { - $value = $this->coerceValue($strValue); - } - - $this->set($name, $value); - } - } - - /** - * Set variables - * - * @api - * - * @param array $variables - */ - public function setVariables(array $variables) - { - $this->registeredVars = array_merge($this->registeredVars, $variables); - } - - /** - * Unset variable - * - * @api - * - * @param string $name - */ - public function unsetVariable($name) - { - unset($this->registeredVars[$name]); - } - - /** - * Returns list of variables - * - * @api - * - * @return array - */ - public function getVariables() - { - return $this->registeredVars; - } - - /** - * Adds to list of parsed files - * - * @api - * - * @param string $path - */ - public function addParsedFile($path) - { - if (isset($path) && file_exists($path)) { - $this->parsedFiles[realpath($path)] = filemtime($path); - } - } - - /** - * Returns list of parsed files - * - * @api - * - * @return array - */ - public function getParsedFiles() - { - return $this->parsedFiles; - } - - /** - * Add import path - * - * @api - * - * @param string|callable $path - */ - public function addImportPath($path) - { - if (! in_array($path, $this->importPaths)) { - $this->importPaths[] = $path; - } - } - - /** - * Set import paths - * - * @api - * - * @param string|array $path - */ - public function setImportPaths($path) - { - $this->importPaths = (array) $path; - } - - /** - * Set number precision - * - * @api - * - * @param integer $numberPrecision - */ - public function setNumberPrecision($numberPrecision) - { - Node\Number::$precision = $numberPrecision; - } - - /** - * Set formatter - * - * @api - * - * @param string $formatterName - */ - public function setFormatter($formatterName) - { - $this->formatter = $formatterName; - } - - /** - * Set line number style - * - * @api - * - * @param string $lineNumberStyle - */ - public function setLineNumberStyle($lineNumberStyle) - { - $this->lineNumberStyle = $lineNumberStyle; - } - - /** - * Enable/disable source maps - * - * @api - * - * @param integer $sourceMap - */ - public function setSourceMap($sourceMap) - { - $this->sourceMap = $sourceMap; - } - - /** - * Set source map options - * - * @api - * - * @param array $sourceMapOptions - */ - public function setSourceMapOptions($sourceMapOptions) - { - $this->sourceMapOptions = $sourceMapOptions; - } - - /** - * Register function - * - * @api - * - * @param string $name - * @param callable $func - * @param array $prototype - */ - public function registerFunction($name, $func, $prototype = null) - { - $this->userFunctions[$this->normalizeName($name)] = [$func, $prototype]; - } - - /** - * Unregister function - * - * @api - * - * @param string $name - */ - public function unregisterFunction($name) - { - unset($this->userFunctions[$this->normalizeName($name)]); - } - - /** - * Add feature - * - * @api - * - * @param string $name - */ - public function addFeature($name) - { - $this->registeredFeatures[$name] = true; - } - - /** - * Import file - * - * @param string $path - * @param \Leafo\ScssPhp\Formatter\OutputBlock $out - */ - protected function importFile($path, OutputBlock $out) - { - // see if tree is cached - $realPath = realpath($path); - - if (isset($this->importCache[$realPath])) { - $this->handleImportLoop($realPath); - - $tree = $this->importCache[$realPath]; - } else { - $code = file_get_contents($path); - $parser = $this->parserFactory($path); - $tree = $parser->parse($code); - - $this->importCache[$realPath] = $tree; - } - - $pi = pathinfo($path); - array_unshift($this->importPaths, $pi['dirname']); - $this->compileChildrenNoReturn($tree->children, $out); - array_shift($this->importPaths); - } - - /** - * Return the file path for an import url if it exists - * - * @api - * - * @param string $url - * - * @return string|null - */ - public function findImport($url) - { - $urls = []; - - // for "normal" scss imports (ignore vanilla css and external requests) - if (! preg_match('/\.css$|^https?:\/\//', $url)) { - // try both normal and the _partial filename - $urls = [$url, preg_replace('/[^\/]+$/', '_\0', $url)]; - } - - $hasExtension = preg_match('/[.]s?css$/', $url); - - foreach ($this->importPaths as $dir) { - if (is_string($dir)) { - // check urls for normal import paths - foreach ($urls as $full) { - $separator = ( - ! empty($dir) && - substr($dir, -1) !== '/' && - substr($full, 0, 1) !== '/' - ) ? '/' : ''; - $full = $dir . $separator . $full; - - if ($this->fileExists($file = $full . '.scss') || - ($hasExtension && $this->fileExists($file = $full)) - ) { - return $file; - } - } - } elseif (is_callable($dir)) { - // check custom callback for import path - $file = call_user_func($dir, $url); - - if ($file !== null) { - return $file; - } - } - } - - return null; - } - - /** - * Set encoding - * - * @api - * - * @param string $encoding - */ - public function setEncoding($encoding) - { - $this->encoding = $encoding; - } - - /** - * Ignore errors? - * - * @api - * - * @param boolean $ignoreErrors - * - * @return \Leafo\ScssPhp\Compiler - */ - public function setIgnoreErrors($ignoreErrors) - { - $this->ignoreErrors = $ignoreErrors; - - return $this; - } - - /** - * Throw error (exception) - * - * @api - * - * @param string $msg Message with optional sprintf()-style vararg parameters - * - * @throws \Leafo\ScssPhp\Exception\CompilerException - */ - public function throwError($msg) - { - if ($this->ignoreErrors) { - return; - } - - $line = $this->sourceLine; - $column = $this->sourceColumn; - - $loc = isset($this->sourceNames[$this->sourceIndex]) - ? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column" - : "line: $line, column: $column"; - - if (func_num_args() > 1) { - $msg = call_user_func_array('sprintf', func_get_args()); - } - - $msg = "$msg: $loc"; - - $callStackMsg = $this->callStackMessage(); - - if ($callStackMsg) { - $msg .= "\nCall Stack:\n" . $callStackMsg; - } - - throw new CompilerException($msg); - } - - /** - * Beautify call stack for output - * - * @param boolean $all - * @param null $limit - * - * @return string - */ - protected function callStackMessage($all = false, $limit = null) - { - $callStackMsg = []; - $ncall = 0; - - if ($this->callStack) { - foreach (array_reverse($this->callStack) as $call) { - if ($all || (isset($call['n']) && $call['n'])) { - $msg = "#" . $ncall++ . " " . $call['n'] . " "; - $msg .= (isset($this->sourceNames[$call[Parser::SOURCE_INDEX]]) - ? $this->sourceNames[$call[Parser::SOURCE_INDEX]] - : '(unknown file)'); - $msg .= " on line " . $call[Parser::SOURCE_LINE]; - $callStackMsg[] = $msg; - - if (! is_null($limit) && $ncall>$limit) { - break; - } - } - } - } - - return implode("\n", $callStackMsg); - } - - /** - * Handle import loop - * - * @param string $name - * - * @throws \Exception - */ - protected function handleImportLoop($name) - { - for ($env = $this->env; $env; $env = $env->parent) { - $file = $this->sourceNames[$env->block->sourceIndex]; - - if (realpath($file) === $name) { - $this->throwError('An @import loop has been found: %s imports %s', $file, basename($file)); - break; - } - } - } - - /** - * Does file exist? - * - * @param string $name - * - * @return boolean - */ - protected function fileExists($name) - { - return file_exists($name) && is_file($name); - } - - /** - * Call SCSS @function - * - * @param string $name - * @param array $argValues - * @param array $returnValue - * - * @return boolean Returns true if returnValue is set; otherwise, false - */ - protected function callScssFunction($name, $argValues, &$returnValue) - { - $func = $this->get(static::$namespaces['function'] . $name, false); - - if (! $func) { - return false; - } - - $this->pushEnv(); - - $storeEnv = $this->storeEnv; - $this->storeEnv = $this->env; - - // set the args - if (isset($func->args)) { - $this->applyArguments($func->args, $argValues); - } - - // throw away lines and children - $tmp = new OutputBlock; - $tmp->lines = []; - $tmp->children = []; - - $this->env->marker = 'function'; - - $ret = $this->compileChildren($func->children, $tmp, $this->env->marker . " " . $name); - - $this->storeEnv = $storeEnv; - - $this->popEnv(); - - $returnValue = ! isset($ret) ? static::$defaultValue : $ret; - - return true; - } - - /** - * Call built-in and registered (PHP) functions - * - * @param string $name - * @param array $args - * @param array $returnValue - * - * @return boolean Returns true if returnValue is set; otherwise, false - */ - protected function callNativeFunction($name, $args, &$returnValue) - { - // try a lib function - $name = $this->normalizeName($name); - - if (isset($this->userFunctions[$name])) { - // see if we can find a user function - list($f, $prototype) = $this->userFunctions[$name]; - } elseif (($f = $this->getBuiltinFunction($name)) && is_callable($f)) { - $libName = $f[1]; - $prototype = isset(static::$$libName) ? static::$$libName : null; - } else { - return false; - } - - @list($sorted, $kwargs) = $this->sortArgs($prototype, $args); - - if ($name !== 'if' && $name !== 'call') { - foreach ($sorted as &$val) { - $val = $this->reduce($val, true); - } - } - - $returnValue = call_user_func($f, $sorted, $kwargs); - - if (! isset($returnValue)) { - return false; - } - - $returnValue = $this->coerceValue($returnValue); - - return true; - } - - /** - * Get built-in function - * - * @param string $name Normalized name - * - * @return array - */ - protected function getBuiltinFunction($name) - { - $libName = 'lib' . preg_replace_callback( - '/_(.)/', - function ($m) { - return ucfirst($m[1]); - }, - ucfirst($name) - ); - - return [$this, $libName]; - } - - /** - * Sorts keyword arguments - * - * @param array $prototype - * @param array $args - * - * @return array - */ - protected function sortArgs($prototype, $args) - { - $keyArgs = []; - $posArgs = []; - - // separate positional and keyword arguments - foreach ($args as $arg) { - list($key, $value) = $arg; - - $key = $key[1]; - - if (empty($key)) { - $posArgs[] = empty($arg[2]) ? $value : $arg; - } else { - $keyArgs[$key] = $value; - } - } - - if (! isset($prototype)) { - return [$posArgs, $keyArgs]; - } - - // copy positional args - $finalArgs = array_pad($posArgs, count($prototype), null); - - // overwrite positional args with keyword args - foreach ($prototype as $i => $names) { - foreach ((array) $names as $name) { - if (isset($keyArgs[$name])) { - $finalArgs[$i] = $keyArgs[$name]; - } - } - } - - return [$finalArgs, $keyArgs]; - } - - /** - * Apply argument values per definition - * - * @param array $argDef - * @param array $argValues - * - * @throws \Exception - */ - protected function applyArguments($argDef, $argValues) - { - $storeEnv = $this->getStoreEnv(); - - $env = new Environment; - $env->store = $storeEnv->store; - - $hasVariable = false; - $args = []; - - foreach ($argDef as $i => $arg) { - list($name, $default, $isVariable) = $argDef[$i]; - - $args[$name] = [$i, $name, $default, $isVariable]; - $hasVariable |= $isVariable; - } - - $keywordArgs = []; - $deferredKeywordArgs = []; - $remaining = []; - - // assign the keyword args - foreach ((array) $argValues as $arg) { - if (! empty($arg[0])) { - if (! isset($args[$arg[0][1]])) { - if ($hasVariable) { - $deferredKeywordArgs[$arg[0][1]] = $arg[1]; - } else { - $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]); - break; - } - } elseif ($args[$arg[0][1]][0] < count($remaining)) { - $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]); - break; - } else { - $keywordArgs[$arg[0][1]] = $arg[1]; - } - } elseif (count($keywordArgs)) { - $this->throwError('Positional arguments must come before keyword arguments.'); - break; - } elseif ($arg[2] === true) { - $val = $this->reduce($arg[1], true); - - if ($val[0] === Type::T_LIST) { - foreach ($val[2] as $name => $item) { - if (! is_numeric($name)) { - $keywordArgs[$name] = $item; - } else { - $remaining[] = $item; - } - } - } elseif ($val[0] === Type::T_MAP) { - foreach ($val[1] as $i => $name) { - $name = $this->compileStringContent($this->coerceString($name)); - $item = $val[2][$i]; - - if (! is_numeric($name)) { - $keywordArgs[$name] = $item; - } else { - $remaining[] = $item; - } - } - } else { - $remaining[] = $val; - } - } else { - $remaining[] = $arg[1]; - } - } - - foreach ($args as $arg) { - list($i, $name, $default, $isVariable) = $arg; - - if ($isVariable) { - $val = [Type::T_LIST, ',', [], $isVariable]; - - for ($count = count($remaining); $i < $count; $i++) { - $val[2][] = $remaining[$i]; - } - - foreach ($deferredKeywordArgs as $itemName => $item) { - $val[2][$itemName] = $item; - } - } elseif (isset($remaining[$i])) { - $val = $remaining[$i]; - } elseif (isset($keywordArgs[$name])) { - $val = $keywordArgs[$name]; - } elseif (! empty($default)) { - continue; - } else { - $this->throwError("Missing argument $name"); - break; - } - - $this->set($name, $this->reduce($val, true), true, $env); - } - - $storeEnv->store = $env->store; - - foreach ($args as $arg) { - list($i, $name, $default, $isVariable) = $arg; - - if ($isVariable || isset($remaining[$i]) || isset($keywordArgs[$name]) || empty($default)) { - continue; - } - - $this->set($name, $this->reduce($default, true), true); - } - } - - /** - * Coerce a php value into a scss one - * - * @param mixed $value - * - * @return array|\Leafo\ScssPhp\Node\Number - */ - protected function coerceValue($value) - { - if (is_array($value) || $value instanceof \ArrayAccess) { - return $value; - } - - if (is_bool($value)) { - return $this->toBool($value); - } - - if ($value === null) { - return static::$null; - } - - if (is_numeric($value)) { - return new Node\Number($value, ''); - } - - if ($value === '') { - return static::$emptyString; - } - - if (preg_match('/^(#([0-9a-f]{6})|#([0-9a-f]{3}))$/i', $value, $m)) { - $color = [Type::T_COLOR]; - - if (isset($m[3])) { - $num = hexdec($m[3]); - - foreach ([3, 2, 1] as $i) { - $t = $num & 0xf; - $color[$i] = $t << 4 | $t; - $num >>= 4; - } - } else { - $num = hexdec($m[2]); - - foreach ([3, 2, 1] as $i) { - $color[$i] = $num & 0xff; - $num >>= 8; - } - } - - return $color; - } - - return [Type::T_KEYWORD, $value]; - } - - /** - * Coerce something to map - * - * @param array $item - * - * @return array - */ - protected function coerceMap($item) - { - if ($item[0] === Type::T_MAP) { - return $item; - } - - if ($item === static::$emptyList) { - return static::$emptyMap; - } - - return [Type::T_MAP, [$item], [static::$null]]; - } - - /** - * Coerce something to list - * - * @param array $item - * @param string $delim - * - * @return array - */ - protected function coerceList($item, $delim = ',') - { - if (isset($item) && $item[0] === Type::T_LIST) { - return $item; - } - - if (isset($item) && $item[0] === Type::T_MAP) { - $keys = $item[1]; - $values = $item[2]; - $list = []; - - for ($i = 0, $s = count($keys); $i < $s; $i++) { - $key = $keys[$i]; - $value = $values[$i]; - - $list[] = [ - Type::T_LIST, - '', - [[Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))], $value] - ]; - } - - return [Type::T_LIST, ',', $list]; - } - - return [Type::T_LIST, $delim, ! isset($item) ? []: [$item]]; - } - - /** - * Coerce color for expression - * - * @param array $value - * - * @return array|null - */ - protected function coerceForExpression($value) - { - if ($color = $this->coerceColor($value)) { - return $color; - } - - return $value; - } - - /** - * Coerce value to color - * - * @param array $value - * - * @return array|null - */ - protected function coerceColor($value) - { - switch ($value[0]) { - case Type::T_COLOR: - return $value; - - case Type::T_KEYWORD: - $name = strtolower($value[1]); - - if (isset(Colors::$cssColors[$name])) { - $rgba = explode(',', Colors::$cssColors[$name]); - - return isset($rgba[3]) - ? [Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3]] - : [Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]]; - } - - return null; - } - - return null; - } - - /** - * Coerce value to string - * - * @param array $value - * - * @return array|null - */ - protected function coerceString($value) - { - if ($value[0] === Type::T_STRING) { - return $value; - } - - return [Type::T_STRING, '', [$this->compileValue($value)]]; - } - - /** - * Coerce value to a percentage - * - * @param array $value - * - * @return integer|float - */ - protected function coercePercent($value) - { - if ($value[0] === Type::T_NUMBER) { - if (! empty($value[2]['%'])) { - return $value[1] / 100; - } - - return $value[1]; - } - - return 0; - } - - /** - * Assert value is a map - * - * @api - * - * @param array $value - * - * @return array - * - * @throws \Exception - */ - public function assertMap($value) - { - $value = $this->coerceMap($value); - - if ($value[0] !== Type::T_MAP) { - $this->throwError('expecting map, %s received', $value[0]); - } - - return $value; - } - - /** - * Assert value is a list - * - * @api - * - * @param array $value - * - * @return array - * - * @throws \Exception - */ - public function assertList($value) - { - if ($value[0] !== Type::T_LIST) { - $this->throwError('expecting list, %s received', $value[0]); - } - - return $value; - } - - /** - * Assert value is a color - * - * @api - * - * @param array $value - * - * @return array - * - * @throws \Exception - */ - public function assertColor($value) - { - if ($color = $this->coerceColor($value)) { - return $color; - } - - $this->throwError('expecting color, %s received', $value[0]); - } - - /** - * Assert value is a number - * - * @api - * - * @param array $value - * - * @return integer|float - * - * @throws \Exception - */ - public function assertNumber($value) - { - if ($value[0] !== Type::T_NUMBER) { - $this->throwError('expecting number, %s received', $value[0]); - } - - return $value[1]; - } - - /** - * Make sure a color's components don't go out of bounds - * - * @param array $c - * - * @return array - */ - protected function fixColor($c) - { - foreach ([1, 2, 3] as $i) { - if ($c[$i] < 0) { - $c[$i] = 0; - } - - if ($c[$i] > 255) { - $c[$i] = 255; - } - } - - return $c; - } - - /** - * Convert RGB to HSL - * - * @api - * - * @param integer $red - * @param integer $green - * @param integer $blue - * - * @return array - */ - public function toHSL($red, $green, $blue) - { - $min = min($red, $green, $blue); - $max = max($red, $green, $blue); - - $l = $min + $max; - $d = $max - $min; - - if ((int) $d === 0) { - $h = $s = 0; - } else { - if ($l < 255) { - $s = $d / $l; - } else { - $s = $d / (510 - $l); - } - - if ($red == $max) { - $h = 60 * ($green - $blue) / $d; - } elseif ($green == $max) { - $h = 60 * ($blue - $red) / $d + 120; - } elseif ($blue == $max) { - $h = 60 * ($red - $green) / $d + 240; - } - } - - return [Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1]; - } - - /** - * Hue to RGB helper - * - * @param float $m1 - * @param float $m2 - * @param float $h - * - * @return float - */ - protected function hueToRGB($m1, $m2, $h) - { - if ($h < 0) { - $h += 1; - } elseif ($h > 1) { - $h -= 1; - } - - if ($h * 6 < 1) { - return $m1 + ($m2 - $m1) * $h * 6; - } - - if ($h * 2 < 1) { - return $m2; - } - - if ($h * 3 < 2) { - return $m1 + ($m2 - $m1) * (2/3 - $h) * 6; - } - - return $m1; - } - - /** - * Convert HSL to RGB - * - * @api - * - * @param integer $hue H from 0 to 360 - * @param integer $saturation S from 0 to 100 - * @param integer $lightness L from 0 to 100 - * - * @return array - */ - public function toRGB($hue, $saturation, $lightness) - { - if ($hue < 0) { - $hue += 360; - } - - $h = $hue / 360; - $s = min(100, max(0, $saturation)) / 100; - $l = min(100, max(0, $lightness)) / 100; - - $m2 = $l <= 0.5 ? $l * ($s + 1) : $l + $s - $l * $s; - $m1 = $l * 2 - $m2; - - $r = $this->hueToRGB($m1, $m2, $h + 1/3) * 255; - $g = $this->hueToRGB($m1, $m2, $h) * 255; - $b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255; - - $out = [Type::T_COLOR, $r, $g, $b]; - - return $out; - } - - // Built in functions - - //protected static $libCall = ['name', 'args...']; - protected function libCall($args, $kwargs) - { - $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true))); - - $posArgs = []; - - foreach ($args as $arg) { - if (empty($arg[0])) { - if ($arg[2] === true) { - $tmp = $this->reduce($arg[1]); - - if ($tmp[0] === Type::T_LIST) { - foreach ($tmp[2] as $item) { - $posArgs[] = [null, $item, false]; - } - } else { - $posArgs[] = [null, $tmp, true]; - } - - continue; - } - - $posArgs[] = [null, $this->reduce($arg), false]; - continue; - } - - $posArgs[] = [null, $arg, false]; - } - - if (count($kwargs)) { - foreach ($kwargs as $key => $value) { - $posArgs[] = [[Type::T_VARIABLE, $key], $value, false]; - } - } - - return $this->reduce([Type::T_FUNCTION_CALL, $name, $posArgs]); - } - - protected static $libIf = ['condition', 'if-true', 'if-false']; - protected function libIf($args) - { - list($cond, $t, $f) = $args; - - if (! $this->isTruthy($this->reduce($cond, true))) { - return $this->reduce($f, true); - } - - return $this->reduce($t, true); - } - - protected static $libIndex = ['list', 'value']; - protected function libIndex($args) - { - list($list, $value) = $args; - - if ($value[0] === Type::T_MAP) { - return static::$null; - } - - if ($list[0] === Type::T_MAP || - $list[0] === Type::T_STRING || - $list[0] === Type::T_KEYWORD || - $list[0] === Type::T_INTERPOLATE - ) { - $list = $this->coerceList($list, ' '); - } - - if ($list[0] !== Type::T_LIST) { - return static::$null; - } - - $values = []; - - foreach ($list[2] as $item) { - $values[] = $this->normalizeValue($item); - } - - $key = array_search($this->normalizeValue($value), $values); - - return false === $key ? static::$null : $key + 1; - } - - protected static $libRgb = ['red', 'green', 'blue']; - protected function libRgb($args) - { - list($r, $g, $b) = $args; - - return [Type::T_COLOR, $r[1], $g[1], $b[1]]; - } - - protected static $libRgba = [ - ['red', 'color'], - 'green', 'blue', 'alpha']; - protected function libRgba($args) - { - if ($color = $this->coerceColor($args[0])) { - $num = isset($args[3]) ? $args[3] : $args[1]; - $alpha = $this->assertNumber($num); - $color[4] = $alpha; - - return $color; - } - - list($r, $g, $b, $a) = $args; - - return [Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]]; - } - - // helper function for adjust_color, change_color, and scale_color - protected function alterColor($args, $fn) - { - $color = $this->assertColor($args[0]); - - foreach ([1, 2, 3, 7] as $i) { - if (isset($args[$i])) { - $val = $this->assertNumber($args[$i]); - $ii = $i === 7 ? 4 : $i; // alpha - $color[$ii] = call_user_func($fn, isset($color[$ii]) ? $color[$ii] : 0, $val, $i); - } - } - - if (isset($args[4]) || isset($args[5]) || isset($args[6])) { - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - foreach ([4, 5, 6] as $i) { - if (isset($args[$i])) { - $val = $this->assertNumber($args[$i]); - $hsl[$i - 3] = call_user_func($fn, $hsl[$i - 3], $val, $i); - } - } - - $rgb = $this->toRGB($hsl[1], $hsl[2], $hsl[3]); - - if (isset($color[4])) { - $rgb[4] = $color[4]; - } - - $color = $rgb; - } - - return $color; - } - - protected static $libAdjustColor = [ - 'color', 'red', 'green', 'blue', - 'hue', 'saturation', 'lightness', 'alpha' - ]; - protected function libAdjustColor($args) - { - return $this->alterColor($args, function ($base, $alter, $i) { - return $base + $alter; - }); - } - - protected static $libChangeColor = [ - 'color', 'red', 'green', 'blue', - 'hue', 'saturation', 'lightness', 'alpha' - ]; - protected function libChangeColor($args) - { - return $this->alterColor($args, function ($base, $alter, $i) { - return $alter; - }); - } - - protected static $libScaleColor = [ - 'color', 'red', 'green', 'blue', - 'hue', 'saturation', 'lightness', 'alpha' - ]; - protected function libScaleColor($args) - { - return $this->alterColor($args, function ($base, $scale, $i) { - // 1, 2, 3 - rgb - // 4, 5, 6 - hsl - // 7 - a - switch ($i) { - case 1: - case 2: - case 3: - $max = 255; - break; - - case 4: - $max = 360; - break; - - case 7: - $max = 1; - break; - - default: - $max = 100; - } - - $scale = $scale / 100; - - if ($scale < 0) { - return $base * $scale + $base; - } - - return ($max - $base) * $scale + $base; - }); - } - - protected static $libIeHexStr = ['color']; - protected function libIeHexStr($args) - { - $color = $this->coerceColor($args[0]); - $color[4] = isset($color[4]) ? round(255 * $color[4]) : 255; - - return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]); - } - - protected static $libRed = ['color']; - protected function libRed($args) - { - $color = $this->coerceColor($args[0]); - - return $color[1]; - } - - protected static $libGreen = ['color']; - protected function libGreen($args) - { - $color = $this->coerceColor($args[0]); - - return $color[2]; - } - - protected static $libBlue = ['color']; - protected function libBlue($args) - { - $color = $this->coerceColor($args[0]); - - return $color[3]; - } - - protected static $libAlpha = ['color']; - protected function libAlpha($args) - { - if ($color = $this->coerceColor($args[0])) { - return isset($color[4]) ? $color[4] : 1; - } - - // this might be the IE function, so return value unchanged - return null; - } - - protected static $libOpacity = ['color']; - protected function libOpacity($args) - { - $value = $args[0]; - - if ($value[0] === Type::T_NUMBER) { - return null; - } - - return $this->libAlpha($args); - } - - // mix two colors - protected static $libMix = ['color-1', 'color-2', 'weight']; - protected function libMix($args) - { - list($first, $second, $weight) = $args; - - $first = $this->assertColor($first); - $second = $this->assertColor($second); - - if (! isset($weight)) { - $weight = 0.5; - } else { - $weight = $this->coercePercent($weight); - } - - $firstAlpha = isset($first[4]) ? $first[4] : 1; - $secondAlpha = isset($second[4]) ? $second[4] : 1; - - $w = $weight * 2 - 1; - $a = $firstAlpha - $secondAlpha; - - $w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0; - $w2 = 1.0 - $w1; - - $new = [Type::T_COLOR, - $w1 * $first[1] + $w2 * $second[1], - $w1 * $first[2] + $w2 * $second[2], - $w1 * $first[3] + $w2 * $second[3], - ]; - - if ($firstAlpha != 1.0 || $secondAlpha != 1.0) { - $new[] = $firstAlpha * $weight + $secondAlpha * (1 - $weight); - } - - return $this->fixColor($new); - } - - protected static $libHsl = ['hue', 'saturation', 'lightness']; - protected function libHsl($args) - { - list($h, $s, $l) = $args; - - return $this->toRGB($h[1], $s[1], $l[1]); - } - - protected static $libHsla = ['hue', 'saturation', 'lightness', 'alpha']; - protected function libHsla($args) - { - list($h, $s, $l, $a) = $args; - - $color = $this->toRGB($h[1], $s[1], $l[1]); - $color[4] = $a[1]; - - return $color; - } - - protected static $libHue = ['color']; - protected function libHue($args) - { - $color = $this->assertColor($args[0]); - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - return new Node\Number($hsl[1], 'deg'); - } - - protected static $libSaturation = ['color']; - protected function libSaturation($args) - { - $color = $this->assertColor($args[0]); - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - return new Node\Number($hsl[2], '%'); - } - - protected static $libLightness = ['color']; - protected function libLightness($args) - { - $color = $this->assertColor($args[0]); - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - - return new Node\Number($hsl[3], '%'); - } - - protected function adjustHsl($color, $idx, $amount) - { - $hsl = $this->toHSL($color[1], $color[2], $color[3]); - $hsl[$idx] += $amount; - $out = $this->toRGB($hsl[1], $hsl[2], $hsl[3]); - - if (isset($color[4])) { - $out[4] = $color[4]; - } - - return $out; - } - - protected static $libAdjustHue = ['color', 'degrees']; - protected function libAdjustHue($args) - { - $color = $this->assertColor($args[0]); - $degrees = $this->assertNumber($args[1]); - - return $this->adjustHsl($color, 1, $degrees); - } - - protected static $libLighten = ['color', 'amount']; - protected function libLighten($args) - { - $color = $this->assertColor($args[0]); - $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%'); - - return $this->adjustHsl($color, 3, $amount); - } - - protected static $libDarken = ['color', 'amount']; - protected function libDarken($args) - { - $color = $this->assertColor($args[0]); - $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%'); - - return $this->adjustHsl($color, 3, -$amount); - } - - protected static $libSaturate = ['color', 'amount']; - protected function libSaturate($args) - { - $value = $args[0]; - - if ($value[0] === Type::T_NUMBER) { - return null; - } - - $color = $this->assertColor($value); - $amount = 100 * $this->coercePercent($args[1]); - - return $this->adjustHsl($color, 2, $amount); - } - - protected static $libDesaturate = ['color', 'amount']; - protected function libDesaturate($args) - { - $color = $this->assertColor($args[0]); - $amount = 100 * $this->coercePercent($args[1]); - - return $this->adjustHsl($color, 2, -$amount); - } - - protected static $libGrayscale = ['color']; - protected function libGrayscale($args) - { - $value = $args[0]; - - if ($value[0] === Type::T_NUMBER) { - return null; - } - - return $this->adjustHsl($this->assertColor($value), 2, -100); - } - - protected static $libComplement = ['color']; - protected function libComplement($args) - { - return $this->adjustHsl($this->assertColor($args[0]), 1, 180); - } - - protected static $libInvert = ['color']; - protected function libInvert($args) - { - $value = $args[0]; - - if ($value[0] === Type::T_NUMBER) { - return null; - } - - $color = $this->assertColor($value); - $color[1] = 255 - $color[1]; - $color[2] = 255 - $color[2]; - $color[3] = 255 - $color[3]; - - return $color; - } - - // increases opacity by amount - protected static $libOpacify = ['color', 'amount']; - protected function libOpacify($args) - { - $color = $this->assertColor($args[0]); - $amount = $this->coercePercent($args[1]); - - $color[4] = (isset($color[4]) ? $color[4] : 1) + $amount; - $color[4] = min(1, max(0, $color[4])); - - return $color; - } - - protected static $libFadeIn = ['color', 'amount']; - protected function libFadeIn($args) - { - return $this->libOpacify($args); - } - - // decreases opacity by amount - protected static $libTransparentize = ['color', 'amount']; - protected function libTransparentize($args) - { - $color = $this->assertColor($args[0]); - $amount = $this->coercePercent($args[1]); - - $color[4] = (isset($color[4]) ? $color[4] : 1) - $amount; - $color[4] = min(1, max(0, $color[4])); - - return $color; - } - - protected static $libFadeOut = ['color', 'amount']; - protected function libFadeOut($args) - { - return $this->libTransparentize($args); - } - - protected static $libUnquote = ['string']; - protected function libUnquote($args) - { - $str = $args[0]; - - if ($str[0] === Type::T_STRING) { - $str[1] = ''; - } - - return $str; - } - - protected static $libQuote = ['string']; - protected function libQuote($args) - { - $value = $args[0]; - - if ($value[0] === Type::T_STRING && ! empty($value[1])) { - return $value; - } - - return [Type::T_STRING, '"', [$value]]; - } - - protected static $libPercentage = ['value']; - protected function libPercentage($args) - { - return new Node\Number($this->coercePercent($args[0]) * 100, '%'); - } - - protected static $libRound = ['value']; - protected function libRound($args) - { - $num = $args[0]; - - return new Node\Number(round($num[1]), $num[2]); - } - - protected static $libFloor = ['value']; - protected function libFloor($args) - { - $num = $args[0]; - - return new Node\Number(floor($num[1]), $num[2]); - } - - protected static $libCeil = ['value']; - protected function libCeil($args) - { - $num = $args[0]; - - return new Node\Number(ceil($num[1]), $num[2]); - } - - protected static $libAbs = ['value']; - protected function libAbs($args) - { - $num = $args[0]; - - return new Node\Number(abs($num[1]), $num[2]); - } - - protected function libMin($args) - { - $numbers = $this->getNormalizedNumbers($args); - $min = null; - - foreach ($numbers as $key => $number) { - if (null === $min || $number[1] <= $min[1]) { - $min = [$key, $number[1]]; - } - } - - return $args[$min[0]]; - } - - protected function libMax($args) - { - $numbers = $this->getNormalizedNumbers($args); - $max = null; - - foreach ($numbers as $key => $number) { - if (null === $max || $number[1] >= $max[1]) { - $max = [$key, $number[1]]; - } - } - - return $args[$max[0]]; - } - - /** - * Helper to normalize args containing numbers - * - * @param array $args - * - * @return array - */ - protected function getNormalizedNumbers($args) - { - $unit = null; - $originalUnit = null; - $numbers = []; - - foreach ($args as $key => $item) { - if ($item[0] !== Type::T_NUMBER) { - $this->throwError('%s is not a number', $item[0]); - break; - } - - $number = $item->normalize(); - - if (null === $unit) { - $unit = $number[2]; - $originalUnit = $item->unitStr(); - } elseif ($number[1] && $unit !== $number[2]) { - $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr()); - break; - } - - $numbers[$key] = $number; - } - - return $numbers; - } - - protected static $libLength = ['list']; - protected function libLength($args) - { - $list = $this->coerceList($args[0]); - - return count($list[2]); - } - - //protected static $libListSeparator = ['list...']; - protected function libListSeparator($args) - { - if (count($args) > 1) { - return 'comma'; - } - - $list = $this->coerceList($args[0]); - - if (count($list[2]) <= 1) { - return 'space'; - } - - if ($list[1] === ',') { - return 'comma'; - } - - return 'space'; - } - - protected static $libNth = ['list', 'n']; - protected function libNth($args) - { - $list = $this->coerceList($args[0]); - $n = $this->assertNumber($args[1]); - - if ($n > 0) { - $n--; - } elseif ($n < 0) { - $n += count($list[2]); - } - - return isset($list[2][$n]) ? $list[2][$n] : static::$defaultValue; - } - - protected static $libSetNth = ['list', 'n', 'value']; - protected function libSetNth($args) - { - $list = $this->coerceList($args[0]); - $n = $this->assertNumber($args[1]); - - if ($n > 0) { - $n--; - } elseif ($n < 0) { - $n += count($list[2]); - } - - if (! isset($list[2][$n])) { - $this->throwError('Invalid argument for "n"'); - - return null; - } - - $list[2][$n] = $args[2]; - - return $list; - } - - protected static $libMapGet = ['map', 'key']; - protected function libMapGet($args) - { - $map = $this->assertMap($args[0]); - $key = $this->compileStringContent($this->coerceString($args[1])); - - for ($i = count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { - return $map[2][$i]; - } - } - - return static::$null; - } - - protected static $libMapKeys = ['map']; - protected function libMapKeys($args) - { - $map = $this->assertMap($args[0]); - $keys = $map[1]; - - return [Type::T_LIST, ',', $keys]; - } - - protected static $libMapValues = ['map']; - protected function libMapValues($args) - { - $map = $this->assertMap($args[0]); - $values = $map[2]; - - return [Type::T_LIST, ',', $values]; - } - - protected static $libMapRemove = ['map', 'key']; - protected function libMapRemove($args) - { - $map = $this->assertMap($args[0]); - $key = $this->compileStringContent($this->coerceString($args[1])); - - for ($i = count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { - array_splice($map[1], $i, 1); - array_splice($map[2], $i, 1); - } - } - - return $map; - } - - protected static $libMapHasKey = ['map', 'key']; - protected function libMapHasKey($args) - { - $map = $this->assertMap($args[0]); - $key = $this->compileStringContent($this->coerceString($args[1])); - - for ($i = count($map[1]) - 1; $i >= 0; $i--) { - if ($key === $this->compileStringContent($this->coerceString($map[1][$i]))) { - return true; - } - } - - return false; - } - - protected static $libMapMerge = ['map-1', 'map-2']; - protected function libMapMerge($args) - { - $map1 = $this->assertMap($args[0]); - $map2 = $this->assertMap($args[1]); - - foreach ($map2[1] as $i2 => $key2) { - $key = $this->compileStringContent($this->coerceString($key2)); - - foreach ($map1[1] as $i1 => $key1) { - if ($key === $this->compileStringContent($this->coerceString($key1))) { - $map1[2][$i1] = $map2[2][$i2]; - continue 2; - } - } - - $map1[1][] = $map2[1][$i2]; - $map1[2][] = $map2[2][$i2]; - } - - return $map1; - } - - protected static $libKeywords = ['args']; - protected function libKeywords($args) - { - $this->assertList($args[0]); - - $keys = []; - $values = []; - - foreach ($args[0][2] as $name => $arg) { - $keys[] = [Type::T_KEYWORD, $name]; - $values[] = $arg; - } - - return [Type::T_MAP, $keys, $values]; - } - - protected function listSeparatorForJoin($list1, $sep) - { - if (! isset($sep)) { - return $list1[1]; - } - - switch ($this->compileValue($sep)) { - case 'comma': - return ','; - - case 'space': - return ''; - - default: - return $list1[1]; - } - } - - protected static $libJoin = ['list1', 'list2', 'separator']; - protected function libJoin($args) - { - list($list1, $list2, $sep) = $args; - - $list1 = $this->coerceList($list1, ' '); - $list2 = $this->coerceList($list2, ' '); - $sep = $this->listSeparatorForJoin($list1, $sep); - - return [Type::T_LIST, $sep, array_merge($list1[2], $list2[2])]; - } - - protected static $libAppend = ['list', 'val', 'separator']; - protected function libAppend($args) - { - list($list1, $value, $sep) = $args; - - $list1 = $this->coerceList($list1, ' '); - $sep = $this->listSeparatorForJoin($list1, $sep); - - return [Type::T_LIST, $sep, array_merge($list1[2], [$value])]; - } - - protected function libZip($args) - { - foreach ($args as $arg) { - $this->assertList($arg); - } - - $lists = []; - $firstList = array_shift($args); - - foreach ($firstList[2] as $key => $item) { - $list = [Type::T_LIST, '', [$item]]; - - foreach ($args as $arg) { - if (isset($arg[2][$key])) { - $list[2][] = $arg[2][$key]; - } else { - break 2; - } - } - - $lists[] = $list; - } - - return [Type::T_LIST, ',', $lists]; - } - - protected static $libTypeOf = ['value']; - protected function libTypeOf($args) - { - $value = $args[0]; - - switch ($value[0]) { - case Type::T_KEYWORD: - if ($value === static::$true || $value === static::$false) { - return 'bool'; - } - - if ($this->coerceColor($value)) { - return 'color'; - } - - // fall-thru - case Type::T_FUNCTION: - return 'string'; - - case Type::T_LIST: - if (isset($value[3]) && $value[3]) { - return 'arglist'; - } - - // fall-thru - default: - return $value[0]; - } - } - - protected static $libUnit = ['number']; - protected function libUnit($args) - { - $num = $args[0]; - - if ($num[0] === Type::T_NUMBER) { - return [Type::T_STRING, '"', [$num->unitStr()]]; - } - - return ''; - } - - protected static $libUnitless = ['number']; - protected function libUnitless($args) - { - $value = $args[0]; - - return $value[0] === Type::T_NUMBER && $value->unitless(); - } - - protected static $libComparable = ['number-1', 'number-2']; - protected function libComparable($args) - { - list($number1, $number2) = $args; - - if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER || - ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER - ) { - $this->throwError('Invalid argument(s) for "comparable"'); - - return null; - } - - $number1 = $number1->normalize(); - $number2 = $number2->normalize(); - - return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless(); - } - - protected static $libStrIndex = ['string', 'substring']; - protected function libStrIndex($args) - { - $string = $this->coerceString($args[0]); - $stringContent = $this->compileStringContent($string); - - $substring = $this->coerceString($args[1]); - $substringContent = $this->compileStringContent($substring); - - $result = strpos($stringContent, $substringContent); - - return $result === false ? static::$null : new Node\Number($result + 1, ''); - } - - protected static $libStrInsert = ['string', 'insert', 'index']; - protected function libStrInsert($args) - { - $string = $this->coerceString($args[0]); - $stringContent = $this->compileStringContent($string); - - $insert = $this->coerceString($args[1]); - $insertContent = $this->compileStringContent($insert); - - list(, $index) = $args[2]; - - $string[2] = [substr_replace($stringContent, $insertContent, $index - 1, 0)]; - - return $string; - } - - protected static $libStrLength = ['string']; - protected function libStrLength($args) - { - $string = $this->coerceString($args[0]); - $stringContent = $this->compileStringContent($string); - - return new Node\Number(strlen($stringContent), ''); - } - - protected static $libStrSlice = ['string', 'start-at', 'end-at']; - protected function libStrSlice($args) - { - if (isset($args[2]) && $args[2][1] == 0) { - return static::$nullString; - } - - $string = $this->coerceString($args[0]); - $stringContent = $this->compileStringContent($string); - - $start = (int) $args[1][1]; - - if ($start > 0) { - $start--; - } - - $end = (int) $args[2][1]; - $length = $end < 0 ? $end + 1 : ($end > 0 ? $end - $start : $end); - - $string[2] = $length - ? [substr($stringContent, $start, $length)] - : [substr($stringContent, $start)]; - - return $string; - } - - protected static $libToLowerCase = ['string']; - protected function libToLowerCase($args) - { - $string = $this->coerceString($args[0]); - $stringContent = $this->compileStringContent($string); - - $string[2] = [function_exists('mb_strtolower') ? mb_strtolower($stringContent) : strtolower($stringContent)]; - - return $string; - } - - protected static $libToUpperCase = ['string']; - protected function libToUpperCase($args) - { - $string = $this->coerceString($args[0]); - $stringContent = $this->compileStringContent($string); - - $string[2] = [function_exists('mb_strtoupper') ? mb_strtoupper($stringContent) : strtoupper($stringContent)]; - - return $string; - } - - protected static $libFeatureExists = ['feature']; - protected function libFeatureExists($args) - { - $string = $this->coerceString($args[0]); - $name = $this->compileStringContent($string); - - return $this->toBool( - array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false - ); - } - - protected static $libFunctionExists = ['name']; - protected function libFunctionExists($args) - { - $string = $this->coerceString($args[0]); - $name = $this->compileStringContent($string); - - // user defined functions - if ($this->has(static::$namespaces['function'] . $name)) { - return true; - } - - $name = $this->normalizeName($name); - - if (isset($this->userFunctions[$name])) { - return true; - } - - // built-in functions - $f = $this->getBuiltinFunction($name); - - return $this->toBool(is_callable($f)); - } - - protected static $libGlobalVariableExists = ['name']; - protected function libGlobalVariableExists($args) - { - $string = $this->coerceString($args[0]); - $name = $this->compileStringContent($string); - - return $this->has($name, $this->rootEnv); - } - - protected static $libMixinExists = ['name']; - protected function libMixinExists($args) - { - $string = $this->coerceString($args[0]); - $name = $this->compileStringContent($string); - - return $this->has(static::$namespaces['mixin'] . $name); - } - - protected static $libVariableExists = ['name']; - protected function libVariableExists($args) - { - $string = $this->coerceString($args[0]); - $name = $this->compileStringContent($string); - - return $this->has($name); - } - - /** - * Workaround IE7's content counter bug. - * - * @param array $args - * - * @return array - */ - protected function libCounter($args) - { - $list = array_map([$this, 'compileValue'], $args); - - return [Type::T_STRING, '', ['counter(' . implode(',', $list) . ')']]; - } - - protected static $libRandom = ['limit']; - protected function libRandom($args) - { - if (isset($args[0])) { - $n = $this->assertNumber($args[0]); - - if ($n < 1) { - $this->throwError("limit must be greater than or equal to 1"); - - return null; - } - - return new Node\Number(mt_rand(1, $n), ''); - } - - return new Node\Number(mt_rand(1, mt_getrandmax()), ''); - } - - protected function libUniqueId() - { - static $id; - - if (! isset($id)) { - $id = mt_rand(0, pow(36, 8)); - } - - $id += mt_rand(0, 10) + 1; - - return [Type::T_STRING, '', ['u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)]]; - } - - protected static $libInspect = ['value']; - protected function libInspect($args) - { - if ($args[0] === static::$null) { - return [Type::T_KEYWORD, 'null']; - } - - return $args[0]; - } - - /** - * Preprocess selector args - * - * @param array $arg - * - * @return array|boolean - */ - protected function getSelectorArg($arg) - { - static $parser = null; - - if (is_null($parser)) { - $parser = $this->parserFactory(__METHOD__); - } - - $arg = $this->libUnquote([$arg]); - $arg = $this->compileValue($arg); - - $parsedSelector = []; - - if ($parser->parseSelector($arg, $parsedSelector)) { - $selector = $this->evalSelectors($parsedSelector); - $gluedSelector = $this->glueFunctionSelectors($selector); - - return $gluedSelector; - } - - return false; - } - - /** - * Postprocess selector to output in right format - * - * @param array $selectors - * - * @return string - */ - protected function formatOutputSelector($selectors) - { - $selectors = $this->collapseSelectors($selectors, true); - - return $selectors; - } - - protected static $libIsSuperselector = ['super', 'sub']; - protected function libIsSuperselector($args) - { - list($super, $sub) = $args; - - $super = $this->getSelectorArg($super); - $sub = $this->getSelectorArg($sub); - - return $this->isSuperSelector($super, $sub); - } - - /** - * Test a $super selector again $sub - * - * @param array $super - * @param array $sub - * - * @return boolean - */ - protected function isSuperSelector($super, $sub) - { - // one and only one selector for each arg - if (! $super || count($super) !== 1) { - $this->throwError("Invalid super selector for isSuperSelector()"); - } - - if (! $sub || count($sub) !== 1) { - $this->throwError("Invalid sub selector for isSuperSelector()"); - } - - $super = reset($super); - $sub = reset($sub); - - $i = 0; - $nextMustMatch = false; - - foreach ($super as $node) { - $compound = ''; - - array_walk_recursive( - $node, - function ($value, $key) use (&$compound) { - $compound .= $value; - } - ); - - if ($this->isImmediateRelationshipCombinator($compound)) { - if ($node !== $sub[$i]) { - return false; - } - - $nextMustMatch = true; - $i++; - } else { - while ($i < count($sub) && ! $this->isSuperPart($node, $sub[$i])) { - if ($nextMustMatch) { - return false; - } - - $i++; - } - - if ($i >= count($sub)) { - return false; - } - - $nextMustMatch = false; - $i++; - } - } - - return true; - } - - /** - * Test a part of super selector again a part of sub selector - * - * @param array $superParts - * @param array $subParts - * - * @return boolean - */ - protected function isSuperPart($superParts, $subParts) - { - $i = 0; - - foreach ($superParts as $superPart) { - while ($i < count($subParts) && $subParts[$i] !== $superPart) { - $i++; - } - - if ($i >= count($subParts)) { - return false; - } - - $i++; - } - - return true; - } - - //protected static $libSelectorAppend = ['selector...']; - protected function libSelectorAppend($args) - { - if (count($args) < 1) { - $this->throwError("selector-append() needs at least 1 argument"); - } - - $selectors = array_map([$this, 'getSelectorArg'], $args); - - return $this->formatOutputSelector($this->selectorAppend($selectors)); - } - - /** - * Append parts of the last selector in the list to the previous, recursively - * - * @param array $selectors - * - * @return array - * - * @throws \Leafo\ScssPhp\Exception\CompilerException - */ - protected function selectorAppend($selectors) - { - $lastSelectors = array_pop($selectors); - - if (! $lastSelectors) { - $this->throwError("Invalid selector list in selector-append()"); - } - - while (count($selectors)) { - $previousSelectors = array_pop($selectors); - - if (! $previousSelectors) { - $this->throwError("Invalid selector list in selector-append()"); - } - - // do the trick, happening $lastSelector to $previousSelector - $appended = []; - - foreach ($lastSelectors as $lastSelector) { - $previous = $previousSelectors; - - foreach ($lastSelector as $lastSelectorParts) { - foreach ($lastSelectorParts as $lastSelectorPart) { - foreach ($previous as $i => $previousSelector) { - foreach ($previousSelector as $j => $previousSelectorParts) { - $previous[$i][$j][] = $lastSelectorPart; - } - } - } - } - - foreach ($previous as $ps) { - $appended[] = $ps; - } - } - - $lastSelectors = $appended; - } - - return $lastSelectors; - } - - protected static $libSelectorExtend = ['selectors', 'extendee', 'extender']; - protected function libSelectorExtend($args) - { - list($selectors, $extendee, $extender) = $args; - - $selectors = $this->getSelectorArg($selectors); - $extendee = $this->getSelectorArg($extendee); - $extender = $this->getSelectorArg($extender); - - if (! $selectors || ! $extendee || ! $extender) { - $this->throwError("selector-extend() invalid arguments"); - } - - $extended = $this->extendOrReplaceSelectors($selectors, $extendee, $extender); - - return $this->formatOutputSelector($extended); - } - - protected static $libSelectorReplace = ['selectors', 'original', 'replacement']; - protected function libSelectorReplace($args) - { - list($selectors, $original, $replacement) = $args; - - $selectors = $this->getSelectorArg($selectors); - $original = $this->getSelectorArg($original); - $replacement = $this->getSelectorArg($replacement); - - if (! $selectors || ! $original || ! $replacement) { - $this->throwError("selector-replace() invalid arguments"); - } - - $replaced = $this->extendOrReplaceSelectors($selectors, $original, $replacement, true); - - return $this->formatOutputSelector($replaced); - } - - /** - * Extend/replace in selectors - * used by selector-extend and selector-replace that use the same logic - * - * @param array $selectors - * @param array $extendee - * @param array $extender - * @param boolean $replace - * - * @return array - */ - protected function extendOrReplaceSelectors($selectors, $extendee, $extender, $replace = false) - { - $saveExtends = $this->extends; - $saveExtendsMap = $this->extendsMap; - - $this->extends = []; - $this->extendsMap = []; - - foreach ($extendee as $es) { - // only use the first one - $this->pushExtends(reset($es), $extender, null); - } - - $extended = []; - - foreach ($selectors as $selector) { - if (! $replace) { - $extended[] = $selector; - } - - $n = count($extended); - - $this->matchExtends($selector, $extended); - - // if didnt match, keep the original selector if we are in a replace operation - if ($replace and count($extended) === $n) { - $extended[] = $selector; - } - } - - $this->extends = $saveExtends; - $this->extendsMap = $saveExtendsMap; - - return $extended; - } - - //protected static $libSelectorNest = ['selector...']; - protected function libSelectorNest($args) - { - if (count($args) < 1) { - $this->throwError("selector-nest() needs at least 1 argument"); - } - - $selectorsMap = array_map([$this, 'getSelectorArg'], $args); - - $envs = []; - foreach ($selectorsMap as $selectors) { - $env = new Environment(); - $env->selectors = $selectors; - - $envs[] = $env; - } - - $envs = array_reverse($envs); - $env = $this->extractEnv($envs); - $outputSelectors = $this->multiplySelectors($env); - - return $this->formatOutputSelector($outputSelectors); - } - - protected static $libSelectorParse = ['selectors']; - protected function libSelectorParse($args) - { - $selectors = reset($args); - $selectors = $this->getSelectorArg($selectors); - - return $this->formatOutputSelector($selectors); - } - - protected static $libSelectorUnify = ['selectors1', 'selectors2']; - protected function libSelectorUnify($args) - { - list($selectors1, $selectors2) = $args; - - $selectors1 = $this->getSelectorArg($selectors1); - $selectors2 = $this->getSelectorArg($selectors2); - - if (! $selectors1 || ! $selectors2) { - $this->throwError("selector-unify() invalid arguments"); - } - - // only consider the first compound of each - $compound1 = reset($selectors1); - $compound2 = reset($selectors2); - - // unify them and that's it - $unified = $this->unifyCompoundSelectors($compound1, $compound2); - - return $this->formatOutputSelector($unified); - } - - /** - * The selector-unify magic as its best - * (at least works as expected on test cases) - * - * @param array $compound1 - * @param array $compound2 - * @return array|mixed - */ - protected function unifyCompoundSelectors($compound1, $compound2) - { - if (! count($compound1)) { - return $compound2; - } - - if (! count($compound2)) { - return $compound1; - } - - // check that last part are compatible - $lastPart1 = array_pop($compound1); - $lastPart2 = array_pop($compound2); - $last = $this->mergeParts($lastPart1, $lastPart2); - - if (! $last) { - return [[]]; - } - - $unifiedCompound = [$last]; - $unifiedSelectors = [$unifiedCompound]; - - // do the rest - while (count($compound1) || count($compound2)) { - $part1 = end($compound1); - $part2 = end($compound2); - - if ($part1 && ($match2 = $this->matchPartInCompound($part1, $compound2))) { - list($compound2, $part2, $after2) = $match2; - - if ($after2) { - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after2); - } - - $c = $this->mergeParts($part1, $part2); - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]); - $part1 = $part2 = null; - - array_pop($compound1); - } - - if ($part2 && ($match1 = $this->matchPartInCompound($part2, $compound1))) { - list($compound1, $part1, $after1) = $match1; - - if ($after1) { - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, $after1); - } - - $c = $this->mergeParts($part2, $part1); - $unifiedSelectors = $this->prependSelectors($unifiedSelectors, [$c]); - $part1 = $part2 = null; - - array_pop($compound2); - } - - $new = []; - - if ($part1 && $part2) { - array_pop($compound1); - array_pop($compound2); - - $s = $this->prependSelectors($unifiedSelectors, [$part2]); - $new = array_merge($new, $this->prependSelectors($s, [$part1])); - $s = $this->prependSelectors($unifiedSelectors, [$part1]); - $new = array_merge($new, $this->prependSelectors($s, [$part2])); - } elseif ($part1) { - array_pop($compound1); - - $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part1])); - } elseif ($part2) { - array_pop($compound2); - - $new = array_merge($new, $this->prependSelectors($unifiedSelectors, [$part2])); - } - - if ($new) { - $unifiedSelectors = $new; - } - } - - return $unifiedSelectors; - } - - /** - * Prepend each selector from $selectors with $parts - * - * @param array $selectors - * @param array $parts - * - * @return array - */ - protected function prependSelectors($selectors, $parts) - { - $new = []; - - foreach ($selectors as $compoundSelector) { - array_unshift($compoundSelector, $parts); - - $new[] = $compoundSelector; - } - - return $new; - } - - /** - * Try to find a matching part in a compound: - * - with same html tag name - * - with some class or id or something in common - * - * @param array $part - * @param array $compound - * - * @return array|boolean - */ - protected function matchPartInCompound($part, $compound) - { - $partTag = $this->findTagName($part); - $before = $compound; - $after = []; - - // try to find a match by tag name first - while (count($before)) { - $p = array_pop($before); - - if ($partTag && $partTag !== '*' && $partTag == $this->findTagName($p)) { - return [$before, $p, $after]; - } - - $after[] = $p; - } - - // try again matching a non empty intersection and a compatible tagname - $before = $compound; - $after = []; - - while (count($before)) { - $p = array_pop($before); - - if ($this->checkCompatibleTags($partTag, $this->findTagName($p))) { - if (count(array_intersect($part, $p))) { - return [$before, $p, $after]; - } - } - - $after[] = $p; - } - - return false; - } - - /** - * Merge two part list taking care that - * - the html tag is coming first - if any - * - the :something are coming last - * - * @param array $parts1 - * @param array $parts2 - * - * @return array - */ - protected function mergeParts($parts1, $parts2) - { - $tag1 = $this->findTagName($parts1); - $tag2 = $this->findTagName($parts2); - $tag = $this->checkCompatibleTags($tag1, $tag2); - - // not compatible tags - if ($tag === false) { - return []; - } - - if ($tag) { - if ($tag1) { - $parts1 = array_diff($parts1, [$tag1]); - } - - if ($tag2) { - $parts2 = array_diff($parts2, [$tag2]); - } - } - - $mergedParts = array_merge($parts1, $parts2); - $mergedOrderedParts = []; - - foreach ($mergedParts as $part) { - if (strpos($part, ':') === 0) { - $mergedOrderedParts[] = $part; - } - } - - $mergedParts = array_diff($mergedParts, $mergedOrderedParts); - $mergedParts = array_merge($mergedParts, $mergedOrderedParts); - - if ($tag) { - array_unshift($mergedParts, $tag); - } - - return $mergedParts; - } - - /** - * Check the compatibility between two tag names: - * if both are defined they should be identical or one has to be '*' - * - * @param string $tag1 - * @param string $tag2 - * - * @return array|boolean - */ - protected function checkCompatibleTags($tag1, $tag2) - { - $tags = [$tag1, $tag2]; - $tags = array_unique($tags); - $tags = array_filter($tags); - - if (count($tags)>1) { - $tags = array_diff($tags, ['*']); - } - - // not compatible nodes - if (count($tags)>1) { - return false; - } - - return $tags; - } - - /** - * Find the html tag name in a selector parts list - * - * @param array $parts - * - * @return mixed|string - */ - protected function findTagName($parts) - { - foreach ($parts as $part) { - if (! preg_match('/^[\[.:#%_-]/', $part)) { - return $part; - } - } - - return ''; - } - - protected static $libSimpleSelectors = ['selector']; - protected function libSimpleSelectors($args) - { - $selector = reset($args); - $selector = $this->getSelectorArg($selector); - - // remove selectors list layer, keeping the first one - $selector = reset($selector); - - // remove parts list layer, keeping the first part - $part = reset($selector); - - $listParts = []; - - foreach ($part as $p) { - $listParts[] = [Type::T_STRING, '', [$p]]; - } - - return [Type::T_LIST, ',', $listParts]; - } -} diff --git a/src/Compiler/Environment.php b/src/Compiler/Environment.php deleted file mode 100644 index 99231f36..00000000 --- a/src/Compiler/Environment.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -class Environment -{ - /** - * @var \Leafo\ScssPhp\Block - */ - public $block; - - /** - * @var \Leafo\ScssPhp\Compiler\Environment - */ - public $parent; - - /** - * @var array - */ - public $store; - - /** - * @var array - */ - public $storeUnreduced; - - /** - * @var integer - */ - public $depth; -} diff --git a/src/Exception/CompilerException.php b/src/Exception/CompilerException.php deleted file mode 100644 index 7ca2e2b3..00000000 --- a/src/Exception/CompilerException.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -class CompilerException extends \Exception -{ -} diff --git a/src/Exception/ParserException.php b/src/Exception/ParserException.php deleted file mode 100644 index 6d64335f..00000000 --- a/src/Exception/ParserException.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -class ParserException extends \Exception -{ -} diff --git a/src/Exception/RangeException.php b/src/Exception/RangeException.php deleted file mode 100644 index 3ba6bf14..00000000 --- a/src/Exception/RangeException.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -class RangeException extends \Exception -{ -} diff --git a/src/Exception/ServerException.php b/src/Exception/ServerException.php deleted file mode 100644 index d0ed0842..00000000 --- a/src/Exception/ServerException.php +++ /dev/null @@ -1,21 +0,0 @@ - - */ -class ServerException extends \Exception -{ -} diff --git a/src/Formatter.php b/src/Formatter.php deleted file mode 100644 index 1403859d..00000000 --- a/src/Formatter.php +++ /dev/null @@ -1,275 +0,0 @@ - - */ -abstract class Formatter -{ - /** - * @var integer - */ - public $indentLevel; - - /** - * @var string - */ - public $indentChar; - - /** - * @var string - */ - public $break; - - /** - * @var string - */ - public $open; - - /** - * @var string - */ - public $close; - - /** - * @var string - */ - public $tagSeparator; - - /** - * @var string - */ - public $assignSeparator; - - /** - * @var boolean - */ - public $keepSemicolons; - - /** - * @var \Leafo\ScssPhp\Formatter\OutputBlock - */ - protected $currentBlock; - - /** - * @var integer - */ - protected $currentLine; - - /** - * @var integer - */ - protected $currentColumn; - - /** - * @var \Leafo\ScssPhp\SourceMap\SourceMapGenerator - */ - protected $sourceMapGenerator; - - /** - * Initialize formatter - * - * @api - */ - abstract public function __construct(); - - /** - * Return indentation (whitespace) - * - * @return string - */ - protected function indentStr() - { - return ''; - } - - /** - * Return property assignment - * - * @api - * - * @param string $name - * @param mixed $value - * - * @return string - */ - public function property($name, $value) - { - return rtrim($name) . $this->assignSeparator . $value . ';'; - } - - /** - * Strip semi-colon appended by property(); it's a separator, not a terminator - * - * @api - * - * @param array $lines - */ - public function stripSemicolon(&$lines) - { - if ($this->keepSemicolons) { - return; - } - - if (($count = count($lines)) - && substr($lines[$count - 1], -1) === ';' - ) { - $lines[$count - 1] = substr($lines[$count - 1], 0, -1); - } - } - - /** - * Output lines inside a block - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * Output block selectors - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockSelectors(OutputBlock $block) - { - $inner = $this->indentStr(); - - $this->write($inner - . implode($this->tagSeparator, $block->selectors) - . $this->open . $this->break); - } - - /** - * Output block children - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockChildren(OutputBlock $block) - { - foreach ($block->children as $child) { - $this->block($child); - } - } - - /** - * Output non-empty block - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - protected function block(OutputBlock $block) - { - if (empty($block->lines) && empty($block->children)) { - return; - } - - $this->currentBlock = $block; - - $pre = $this->indentStr(); - - if (! empty($block->selectors)) { - $this->blockSelectors($block); - - $this->indentLevel++; - } - - if (! empty($block->lines)) { - $this->blockLines($block); - } - - if (! empty($block->children)) { - $this->blockChildren($block); - } - - if (! empty($block->selectors)) { - $this->indentLevel--; - - if (empty($block->children)) { - $this->write($this->break); - } - - $this->write($pre . $this->close . $this->break); - } - } - - /** - * Entry point to formatting a block - * - * @api - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block An abstract syntax tree - * @param \Leafo\ScssPhp\SourceMap\SourceMapGenerator|null $sourceMapGenerator Optional source map generator - * - * @return string - */ - public function format(OutputBlock $block, SourceMapGenerator $sourceMapGenerator = null) - { - $this->sourceMapGenerator = null; - - if ($sourceMapGenerator) { - $this->currentLine = 1; - $this->currentColumn = 0; - $this->sourceMapGenerator = $sourceMapGenerator; - } - - ob_start(); - - $this->block($block); - - $out = ob_get_clean(); - - return $out; - } - - /** - * @param string $str - */ - protected function write($str) - { - if ($this->sourceMapGenerator) { - $this->sourceMapGenerator->addMapping( - $this->currentLine, - $this->currentColumn, - $this->currentBlock->sourceLine, - //columns from parser are off by one - $this->currentBlock->sourceColumn > 0 ? $this->currentBlock->sourceColumn - 1 : 0, - $this->currentBlock->sourceName - ); - - $lines = explode("\n", $str); - $lineCount = count($lines); - $this->currentLine += $lineCount-1; - - $lastLine = array_pop($lines); - - $this->currentColumn = ($lineCount === 1 ? $this->currentColumn : 0) + strlen($lastLine); - } - - echo $str; - } -} diff --git a/src/Formatter/Compact.php b/src/Formatter/Compact.php deleted file mode 100644 index 4efa1a08..00000000 --- a/src/Formatter/Compact.php +++ /dev/null @@ -1,45 +0,0 @@ - - */ -class Compact extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ''; - $this->break = ''; - $this->open = ' {'; - $this->close = "}\n\n"; - $this->tagSeparator = ','; - $this->assignSeparator = ':'; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - public function indentStr() - { - return ' '; - } -} diff --git a/src/Formatter/Compressed.php b/src/Formatter/Compressed.php deleted file mode 100644 index ab38529d..00000000 --- a/src/Formatter/Compressed.php +++ /dev/null @@ -1,81 +0,0 @@ - - */ -class Compressed extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = ''; - $this->open = '{'; - $this->close = '}'; - $this->tagSeparator = ','; - $this->assignSeparator = ':'; - $this->keepSemicolons = false; - } - - /** - * {@inheritdoc} - */ - public function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*' && substr($line, 2, 1) !== '!') { - unset($block->lines[$index]); - } elseif (substr($line, 0, 3) === '/*!') { - $block->lines[$index] = '/*' . substr($line, 3); - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * Output block selectors - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockSelectors(OutputBlock $block) - { - $inner = $this->indentStr(); - - $this->write( - $inner - . implode( - $this->tagSeparator, - str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors) - ) - . $this->open . $this->break - ); - } -} diff --git a/src/Formatter/Crunched.php b/src/Formatter/Crunched.php deleted file mode 100644 index da740ccd..00000000 --- a/src/Formatter/Crunched.php +++ /dev/null @@ -1,79 +0,0 @@ - - */ -class Crunched extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = ''; - $this->open = '{'; - $this->close = '}'; - $this->tagSeparator = ','; - $this->assignSeparator = ':'; - $this->keepSemicolons = false; - } - - /** - * {@inheritdoc} - */ - public function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*') { - unset($block->lines[$index]); - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * Output block selectors - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - protected function blockSelectors(OutputBlock $block) - { - $inner = $this->indentStr(); - - $this->write( - $inner - . implode( - $this->tagSeparator, - str_replace([' > ', ' + ', ' ~ '], ['>', '+', '~'], $block->selectors) - ) - . $this->open . $this->break - ); - } -} diff --git a/src/Formatter/Debug.php b/src/Formatter/Debug.php deleted file mode 100644 index bfcbf41a..00000000 --- a/src/Formatter/Debug.php +++ /dev/null @@ -1,121 +0,0 @@ - - */ -class Debug extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ''; - $this->break = "\n"; - $this->open = ' {'; - $this->close = ' }'; - $this->tagSeparator = ', '; - $this->assignSeparator = ': '; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - protected function indentStr() - { - return str_repeat(' ', $this->indentLevel); - } - - /** - * {@inheritdoc} - */ - protected function blockLines(OutputBlock $block) - { - $indent = $this->indentStr(); - - if (empty($block->lines)) { - $this->write("{$indent}block->lines: []\n"); - - return; - } - - foreach ($block->lines as $index => $line) { - $this->write("{$indent}block->lines[{$index}]: $line\n"); - } - } - - /** - * {@inheritdoc} - */ - protected function blockSelectors(OutputBlock $block) - { - $indent = $this->indentStr(); - - if (empty($block->selectors)) { - $this->write("{$indent}block->selectors: []\n"); - - return; - } - - foreach ($block->selectors as $index => $selector) { - $this->write("{$indent}block->selectors[{$index}]: $selector\n"); - } - } - - /** - * {@inheritdoc} - */ - protected function blockChildren(OutputBlock $block) - { - $indent = $this->indentStr(); - - if (empty($block->children)) { - $this->write("{$indent}block->children: []\n"); - - return; - } - - $this->indentLevel++; - - foreach ($block->children as $i => $child) { - $this->block($child); - } - - $this->indentLevel--; - } - - /** - * {@inheritdoc} - */ - protected function block(OutputBlock $block) - { - $indent = $this->indentStr(); - - $this->write("{$indent}block->type: {$block->type}\n" . - "{$indent}block->depth: {$block->depth}\n"); - - $this->currentBlock = $block; - - $this->blockSelectors($block); - $this->blockLines($block); - $this->blockChildren($block); - } -} diff --git a/src/Formatter/Expanded.php b/src/Formatter/Expanded.php deleted file mode 100644 index d8c1e887..00000000 --- a/src/Formatter/Expanded.php +++ /dev/null @@ -1,68 +0,0 @@ - - */ -class Expanded extends Formatter -{ - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = "\n"; - $this->open = ' {'; - $this->close = '}'; - $this->tagSeparator = ', '; - $this->assignSeparator = ': '; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - protected function indentStr() - { - return str_repeat($this->indentChar, $this->indentLevel); - } - - /** - * {@inheritdoc} - */ - protected function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*') { - $block->lines[$index] = preg_replace('/(\r|\n)+/', $glue, $line); - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (empty($block->selectors) || ! empty($block->children)) { - $this->write($this->break); - } - } -} diff --git a/src/Formatter/Nested.php b/src/Formatter/Nested.php deleted file mode 100644 index 8f72206f..00000000 --- a/src/Formatter/Nested.php +++ /dev/null @@ -1,201 +0,0 @@ - - */ -class Nested extends Formatter -{ - /** - * @var integer - */ - private $depth; - - /** - * {@inheritdoc} - */ - public function __construct() - { - $this->indentLevel = 0; - $this->indentChar = ' '; - $this->break = "\n"; - $this->open = ' {'; - $this->close = ' }'; - $this->tagSeparator = ', '; - $this->assignSeparator = ': '; - $this->keepSemicolons = true; - } - - /** - * {@inheritdoc} - */ - protected function indentStr() - { - $n = $this->depth - 1; - - return str_repeat($this->indentChar, max($this->indentLevel + $n, 0)); - } - - /** - * {@inheritdoc} - */ - protected function blockLines(OutputBlock $block) - { - $inner = $this->indentStr(); - - $glue = $this->break . $inner; - - foreach ($block->lines as $index => $line) { - if (substr($line, 0, 2) === '/*') { - $block->lines[$index] = preg_replace('/(\r|\n)+/', $glue, $line); - } - } - - $this->write($inner . implode($glue, $block->lines)); - - if (! empty($block->children)) { - $this->write($this->break); - } - } - - /** - * {@inheritdoc} - */ - protected function blockSelectors(OutputBlock $block) - { - $inner = $this->indentStr(); - - $this->write($inner - . implode($this->tagSeparator, $block->selectors) - . $this->open . $this->break); - } - - /** - * {@inheritdoc} - */ - protected function blockChildren(OutputBlock $block) - { - foreach ($block->children as $i => $child) { - $this->block($child); - - if ($i < count($block->children) - 1) { - $this->write($this->break); - - if (isset($block->children[$i + 1])) { - $next = $block->children[$i + 1]; - - if ($next->depth === max($block->depth, 1) && $child->depth >= $next->depth) { - $this->write($this->break); - } - } - } - } - } - - /** - * {@inheritdoc} - */ - protected function block(OutputBlock $block) - { - if ($block->type === 'root') { - $this->adjustAllChildren($block); - } - - if (empty($block->lines) && empty($block->children)) { - return; - } - - $this->currentBlock = $block; - - - $this->depth = $block->depth; - - if (! empty($block->selectors)) { - $this->blockSelectors($block); - - $this->indentLevel++; - } - - if (! empty($block->lines)) { - $this->blockLines($block); - } - - if (! empty($block->children)) { - $this->blockChildren($block); - } - - if (! empty($block->selectors)) { - $this->indentLevel--; - - $this->write($this->close); - } - - if ($block->type === 'root') { - $this->write($this->break); - } - } - - /** - * Adjust the depths of all children, depth first - * - * @param \Leafo\ScssPhp\Formatter\OutputBlock $block - */ - private function adjustAllChildren(OutputBlock $block) - { - // flatten empty nested blocks - $children = []; - - foreach ($block->children as $i => $child) { - if (empty($child->lines) && empty($child->children)) { - if (isset($block->children[$i + 1])) { - $block->children[$i + 1]->depth = $child->depth; - } - - continue; - } - - $children[] = $child; - } - - $count = count($children); - - for ($i = 0; $i < $count; $i++) { - $depth = $children[$i]->depth; - $j = $i + 1; - - if (isset($children[$j]) && $depth < $children[$j]->depth) { - $childDepth = $children[$j]->depth; - - for (; $j < $count; $j++) { - if ($depth < $children[$j]->depth && $childDepth >= $children[$j]->depth) { - $children[$j]->depth = $depth + 1; - } - } - } - } - - $block->children = $children; - - // make relative to parent - foreach ($block->children as $child) { - $this->adjustAllChildren($child); - - $child->depth = $child->depth - $block->depth; - } - } -} diff --git a/src/Formatter/OutputBlock.php b/src/Formatter/OutputBlock.php deleted file mode 100644 index 5eb589c9..00000000 --- a/src/Formatter/OutputBlock.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ -class OutputBlock -{ - /** - * @var string - */ - public $type; - - /** - * @var integer - */ - public $depth; - - /** - * @var array - */ - public $selectors; - - /** - * @var array - */ - public $lines; - - /** - * @var array - */ - public $children; - - /** - * @var \Leafo\ScssPhp\Formatter\OutputBlock - */ - public $parent; - - /** - * @var string - */ - public $sourceName; - - /** - * @var integer - */ - public $sourceLine; - - /** - * @var integer - */ - public $sourceColumn; -} diff --git a/src/Node.php b/src/Node.php deleted file mode 100644 index b9f7945a..00000000 --- a/src/Node.php +++ /dev/null @@ -1,40 +0,0 @@ - - */ -abstract class Node -{ - /** - * @var string - */ - public $type; - - /** - * @var integer - */ - public $sourceIndex; - - /** - * @var integer - */ - public $sourceLine; - - /** - * @var integer - */ - public $sourceColumn; -} diff --git a/src/Node/Number.php b/src/Node/Number.php deleted file mode 100644 index 42c16803..00000000 --- a/src/Node/Number.php +++ /dev/null @@ -1,330 +0,0 @@ - - */ -class Number extends Node implements \ArrayAccess -{ - /** - * @var integer - */ - static public $precision = 10; - - /** - * @see http://www.w3.org/TR/2012/WD-css3-values-20120308/ - * - * @var array - */ - static protected $unitTable = [ - 'in' => [ - 'in' => 1, - 'pc' => 6, - 'pt' => 72, - 'px' => 96, - 'cm' => 2.54, - 'mm' => 25.4, - 'q' => 101.6, - ], - 'turn' => [ - 'deg' => 360, - 'grad' => 400, - 'rad' => 6.28318530717958647692528676, // 2 * M_PI - 'turn' => 1, - ], - 's' => [ - 's' => 1, - 'ms' => 1000, - ], - 'Hz' => [ - 'Hz' => 1, - 'kHz' => 0.001, - ], - 'dpi' => [ - 'dpi' => 1, - 'dpcm' => 2.54, - 'dppx' => 96, - ], - ]; - - /** - * @var integer|float - */ - public $dimension; - - /** - * @var array - */ - public $units; - - /** - * Initialize number - * - * @param mixed $dimension - * @param mixed $initialUnit - */ - public function __construct($dimension, $initialUnit) - { - $this->type = Type::T_NUMBER; - $this->dimension = $dimension; - $this->units = is_array($initialUnit) - ? $initialUnit - : ($initialUnit ? [$initialUnit => 1] - : []); - } - - /** - * Coerce number to target units - * - * @param array $units - * - * @return \Leafo\ScssPhp\Node\Number - */ - public function coerce($units) - { - if ($this->unitless()) { - return new Number($this->dimension, $units); - } - - $dimension = $this->dimension; - - foreach (static::$unitTable['in'] as $unit => $conv) { - $from = isset($this->units[$unit]) ? $this->units[$unit] : 0; - $to = isset($units[$unit]) ? $units[$unit] : 0; - $factor = pow($conv, $from - $to); - $dimension /= $factor; - } - - return new Number($dimension, $units); - } - - /** - * Normalize number - * - * @return \Leafo\ScssPhp\Node\Number - */ - public function normalize() - { - $dimension = $this->dimension; - $units = []; - - $this->normalizeUnits($dimension, $units, 'in'); - - return new Number($dimension, $units); - } - - /** - * {@inheritdoc} - */ - public function offsetExists($offset) - { - if ($offset === -3) { - return $this->sourceColumn !== null; - } - - if ($offset === -2) { - return $this->sourceLine !== null; - } - - if ($offset === -1 - || $offset === 0 - || $offset === 1 - || $offset === 2 - ) { - return true; - } - - return false; - } - - /** - * {@inheritdoc} - */ - public function offsetGet($offset) - { - switch ($offset) { - case -3: - return $this->sourceColumn; - - case -2: - return $this->sourceLine; - - case -1: - return $this->sourceIndex; - - case 0: - return $this->type; - - case 1: - return $this->dimension; - - case 2: - return $this->units; - } - } - - /** - * {@inheritdoc} - */ - public function offsetSet($offset, $value) - { - if ($offset === 1) { - $this->dimension = $value; - } elseif ($offset === 2) { - $this->units = $value; - } elseif ($offset == -1) { - $this->sourceIndex = $value; - } elseif ($offset == -2) { - $this->sourceLine = $value; - } elseif ($offset == -3) { - $this->sourceColumn = $value; - } - } - - /** - * {@inheritdoc} - */ - public function offsetUnset($offset) - { - if ($offset === 1) { - $this->dimension = null; - } elseif ($offset === 2) { - $this->units = null; - } elseif ($offset === -1) { - $this->sourceIndex = null; - } elseif ($offset === -2) { - $this->sourceLine = null; - } elseif ($offset === -3) { - $this->sourceColumn = null; - } - } - - /** - * Returns true if the number is unitless - * - * @return boolean - */ - public function unitless() - { - return ! array_sum($this->units); - } - - /** - * Returns unit(s) as the product of numerator units divided by the product of denominator units - * - * @return string - */ - public function unitStr() - { - $numerators = []; - $denominators = []; - - foreach ($this->units as $unit => $unitSize) { - if ($unitSize > 0) { - $numerators = array_pad($numerators, count($numerators) + $unitSize, $unit); - continue; - } - - if ($unitSize < 0) { - $denominators = array_pad($denominators, count($denominators) + $unitSize, $unit); - continue; - } - } - - return implode('*', $numerators) . (count($denominators) ? '/' . implode('*', $denominators) : ''); - } - - /** - * Output number - * - * @param \Leafo\ScssPhp\Compiler $compiler - * - * @return string - */ - public function output(Compiler $compiler = null) - { - $dimension = round($this->dimension, static::$precision); - - $units = array_filter($this->units, function ($unitSize) { - return $unitSize; - }); - - if (count($units) > 1 && array_sum($units) === 0) { - $dimension = $this->dimension; - $units = []; - - $this->normalizeUnits($dimension, $units, 'in'); - - $dimension = round($dimension, static::$precision); - $units = array_filter($units, function ($unitSize) { - return $unitSize; - }); - } - - $unitSize = array_sum($units); - - if ($compiler && ($unitSize > 1 || $unitSize < 0 || count($units) > 1)) { - $compiler->throwError((string) $dimension . $this->unitStr() . " isn't a valid CSS value."); - } - - reset($units); - $unit = key($units); - $dimension = number_format($dimension, static::$precision, '.', ''); - - return (static::$precision ? rtrim(rtrim($dimension, '0'), '.') : $dimension) . $unit; - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return $this->output(); - } - - /** - * Normalize units - * - * @param integer|float $dimension - * @param array $units - * @param string $baseUnit - */ - private function normalizeUnits(&$dimension, &$units, $baseUnit = 'in') - { - $dimension = $this->dimension; - $units = []; - - foreach ($this->units as $unit => $exp) { - if (isset(static::$unitTable[$baseUnit][$unit])) { - $factor = pow(static::$unitTable[$baseUnit][$unit], $exp); - - $unit = $baseUnit; - $dimension /= $factor; - } - - $units[$unit] = $exp + (isset($units[$unit]) ? $units[$unit] : 0); - } - } -} diff --git a/src/Parser.php b/src/Parser.php deleted file mode 100644 index c05e4ee8..00000000 --- a/src/Parser.php +++ /dev/null @@ -1,2824 +0,0 @@ - - */ -class Parser -{ - const SOURCE_INDEX = -1; - const SOURCE_LINE = -2; - const SOURCE_COLUMN = -3; - - /** - * @var array - */ - protected static $precedence = [ - '=' => 0, - 'or' => 1, - 'and' => 2, - '==' => 3, - '!=' => 3, - '<=>' => 3, - '<=' => 4, - '>=' => 4, - '<' => 4, - '>' => 4, - '+' => 5, - '-' => 5, - '*' => 6, - '/' => 6, - '%' => 6, - ]; - - protected static $commentPattern; - protected static $operatorPattern; - protected static $whitePattern; - - protected $cache; - - private $sourceName; - private $sourceIndex; - private $sourcePositions; - private $charset; - private $count; - private $env; - private $inParens; - private $eatWhiteDefault; - private $buffer; - private $utf8; - private $encoding; - private $patternModifiers; - private $commentsSeen; - - /** - * Constructor - * - * @api - * - * @param string $sourceName - * @param integer $sourceIndex - * @param string $encoding - * @param \Leafo\ScssPhp\Cache $cache - */ - public function __construct($sourceName, $sourceIndex = 0, $encoding = 'utf-8', $cache = null) - { - $this->sourceName = $sourceName ?: '(stdin)'; - $this->sourceIndex = $sourceIndex; - $this->charset = null; - $this->utf8 = ! $encoding || strtolower($encoding) === 'utf-8'; - $this->patternModifiers = $this->utf8 ? 'Aisu' : 'Ais'; - $this->commentsSeen = []; - - if (empty(static::$operatorPattern)) { - static::$operatorPattern = '([*\/%+-]|[!=]\=|\>\=?|\<\=\>|\<\=?|and|or)'; - - $commentSingle = '\/\/'; - $commentMultiLeft = '\/\*'; - $commentMultiRight = '\*\/'; - - static::$commentPattern = $commentMultiLeft . '.*?' . $commentMultiRight; - static::$whitePattern = $this->utf8 - ? '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisuS' - : '/' . $commentSingle . '[^\n]*\s*|(' . static::$commentPattern . ')\s*|\s+/AisS'; - } - - if ($cache) { - $this->cache = $cache; - } - } - - /** - * Get source file name - * - * @api - * - * @return string - */ - public function getSourceName() - { - return $this->sourceName; - } - - /** - * Throw parser error - * - * @api - * - * @param string $msg - * - * @throws \Leafo\ScssPhp\Exception\ParserException - */ - public function throwParseError($msg = 'parse error') - { - list($line, $column) = $this->getSourcePosition($this->count); - - $loc = empty($this->sourceName) - ? "line: $line, column: $column" - : "$this->sourceName on line $line, at column $column"; - - if ($this->peek("(.*?)(\n|$)", $m, $this->count)) { - throw new ParserException("$msg: failed at `$m[1]` $loc"); - } - - throw new ParserException("$msg: $loc"); - } - - /** - * Parser buffer - * - * @api - * - * @param string $buffer - * - * @return \Leafo\ScssPhp\Block - */ - public function parse($buffer) - { - if ($this->cache) { - $cacheKey = $this->sourceName . ":" . md5($buffer); - $parseOptions = [ - 'charset' => $this->charset, - 'utf8' => $this->utf8, - ]; - $v = $this->cache->getCache("parse", $cacheKey, $parseOptions); - - if (! is_null($v)) { - return $v; - } - } - - // strip BOM (byte order marker) - if (substr($buffer, 0, 3) === "\xef\xbb\xbf") { - $buffer = substr($buffer, 3); - } - - $this->buffer = rtrim($buffer, "\x00..\x1f"); - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - - $this->saveEncoding(); - $this->extractLineNumbers($buffer); - - $this->pushBlock(null); // root block - $this->whitespace(); - $this->pushBlock(null); - $this->popBlock(); - - while ($this->parseChunk()) { - ; - } - - if ($this->count !== strlen($this->buffer)) { - $this->throwParseError(); - } - - if (! empty($this->env->parent)) { - $this->throwParseError('unclosed block'); - } - - if ($this->charset) { - array_unshift($this->env->children, $this->charset); - } - - $this->restoreEncoding(); - - if ($this->cache) { - $this->cache->setCache("parse", $cacheKey, $this->env, $parseOptions); - } - - return $this->env; - } - - /** - * Parse a value or value list - * - * @api - * - * @param string $buffer - * @param string $out - * - * @return boolean - */ - public function parseValue($buffer, &$out) - { - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - $this->buffer = (string) $buffer; - - $this->saveEncoding(); - - $list = $this->valueList($out); - - $this->restoreEncoding(); - - return $list; - } - - /** - * Parse a selector or selector list - * - * @api - * - * @param string $buffer - * @param string $out - * - * @return boolean - */ - public function parseSelector($buffer, &$out) - { - $this->count = 0; - $this->env = null; - $this->inParens = false; - $this->eatWhiteDefault = true; - $this->buffer = (string) $buffer; - - $this->saveEncoding(); - - $selector = $this->selectors($out); - - $this->restoreEncoding(); - - return $selector; - } - - /** - * Parse a single chunk off the head of the buffer and append it to the - * current parse environment. - * - * Returns false when the buffer is empty, or when there is an error. - * - * This function is called repeatedly until the entire document is - * parsed. - * - * This parser is most similar to a recursive descent parser. Single - * functions represent discrete grammatical rules for the language, and - * they are able to capture the text that represents those rules. - * - * Consider the function Compiler::keyword(). (All parse functions are - * structured the same.) - * - * The function takes a single reference argument. When calling the - * function it will attempt to match a keyword on the head of the buffer. - * If it is successful, it will place the keyword in the referenced - * argument, advance the position in the buffer, and return true. If it - * fails then it won't advance the buffer and it will return false. - * - * All of these parse functions are powered by Compiler::match(), which behaves - * the same way, but takes a literal regular expression. Sometimes it is - * more convenient to use match instead of creating a new function. - * - * Because of the format of the functions, to parse an entire string of - * grammatical rules, you can chain them together using &&. - * - * But, if some of the rules in the chain succeed before one fails, then - * the buffer position will be left at an invalid state. In order to - * avoid this, Compiler::seek() is used to remember and set buffer positions. - * - * Before parsing a chain, use $s = $this->count to remember the current - * position into $s. Then if a chain fails, use $this->seek($s) to - * go back where we started. - * - * @return boolean - */ - protected function parseChunk() - { - $s = $this->count; - - // the directives - if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] === '@') { - if ($this->literal('@at-root', 8) && - ($this->selectors($selector) || true) && - ($this->map($with) || true) && - $this->matchChar('{') - ) { - $atRoot = $this->pushSpecialBlock(Type::T_AT_ROOT, $s); - $atRoot->selector = $selector; - $atRoot->with = $with; - - return true; - } - - $this->seek($s); - - if ($this->literal('@media', 6) && $this->mediaQueryList($mediaQueryList) && $this->matchChar('{')) { - $media = $this->pushSpecialBlock(Type::T_MEDIA, $s); - $media->queryList = $mediaQueryList[2]; - - return true; - } - - $this->seek($s); - - if ($this->literal('@mixin', 6) && - $this->keyword($mixinName) && - ($this->argumentDef($args) || true) && - $this->matchChar('{') - ) { - $mixin = $this->pushSpecialBlock(Type::T_MIXIN, $s); - $mixin->name = $mixinName; - $mixin->args = $args; - - return true; - } - - $this->seek($s); - - if ($this->literal('@include', 8) && - $this->keyword($mixinName) && - ($this->matchChar('(') && - ($this->argValues($argValues) || true) && - $this->matchChar(')') || true) && - ($this->end() || - $this->matchChar('{') && $hasBlock = true) - ) { - $child = [Type::T_INCLUDE, $mixinName, isset($argValues) ? $argValues : null, null]; - - if (! empty($hasBlock)) { - $include = $this->pushSpecialBlock(Type::T_INCLUDE, $s); - $include->child = $child; - } else { - $this->append($child, $s); - } - - return true; - } - - $this->seek($s); - - if ($this->literal('@scssphp-import-once', 20) && - $this->valueList($importPath) && - $this->end() - ) { - $this->append([Type::T_SCSSPHP_IMPORT_ONCE, $importPath], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@import', 7) && - $this->valueList($importPath) && - $this->end() - ) { - $this->append([Type::T_IMPORT, $importPath], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@import', 7) && - $this->url($importPath) && - $this->end() - ) { - $this->append([Type::T_IMPORT, $importPath], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@extend', 7) && - $this->selectors($selectors) && - $this->end() - ) { - // check for '!flag' - $optional = $this->stripOptionalFlag($selectors); - $this->append([Type::T_EXTEND, $selectors, $optional], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@function', 9) && - $this->keyword($fnName) && - $this->argumentDef($args) && - $this->matchChar('{') - ) { - $func = $this->pushSpecialBlock(Type::T_FUNCTION, $s); - $func->name = $fnName; - $func->args = $args; - - return true; - } - - $this->seek($s); - - if ($this->literal('@break', 6) && $this->end()) { - $this->append([Type::T_BREAK], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@continue', 9) && $this->end()) { - $this->append([Type::T_CONTINUE], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@return', 7) && ($this->valueList($retVal) || true) && $this->end()) { - $this->append([Type::T_RETURN, isset($retVal) ? $retVal : [Type::T_NULL]], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@each', 5) && - $this->genericList($varNames, 'variable', ',', false) && - $this->literal('in', 2) && - $this->valueList($list) && - $this->matchChar('{') - ) { - $each = $this->pushSpecialBlock(Type::T_EACH, $s); - - foreach ($varNames[2] as $varName) { - $each->vars[] = $varName[1]; - } - - $each->list = $list; - - return true; - } - - $this->seek($s); - - if ($this->literal('@while', 6) && - $this->expression($cond) && - $this->matchChar('{') - ) { - $while = $this->pushSpecialBlock(Type::T_WHILE, $s); - $while->cond = $cond; - - return true; - } - - $this->seek($s); - - if ($this->literal('@for', 4) && - $this->variable($varName) && - $this->literal('from', 4) && - $this->expression($start) && - ($this->literal('through', 7) || - ($forUntil = true && $this->literal('to', 2))) && - $this->expression($end) && - $this->matchChar('{') - ) { - $for = $this->pushSpecialBlock(Type::T_FOR, $s); - $for->var = $varName[1]; - $for->start = $start; - $for->end = $end; - $for->until = isset($forUntil); - - return true; - } - - $this->seek($s); - - if ($this->literal('@if', 3) && $this->valueList($cond) && $this->matchChar('{')) { - $if = $this->pushSpecialBlock(Type::T_IF, $s); - $if->cond = $cond; - $if->cases = []; - - return true; - } - - $this->seek($s); - - if ($this->literal('@debug', 6) && - $this->valueList($value) && - $this->end() - ) { - $this->append([Type::T_DEBUG, $value], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@warn', 5) && - $this->valueList($value) && - $this->end() - ) { - $this->append([Type::T_WARN, $value], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@error', 6) && - $this->valueList($value) && - $this->end() - ) { - $this->append([Type::T_ERROR, $value], $s); - - return true; - } - - $this->seek($s); - - if ($this->literal('@content', 8) && $this->end()) { - $this->append([Type::T_MIXIN_CONTENT], $s); - - return true; - } - - $this->seek($s); - - $last = $this->last(); - - if (isset($last) && $last[0] === Type::T_IF) { - list(, $if) = $last; - - if ($this->literal('@else', 5)) { - if ($this->matchChar('{')) { - $else = $this->pushSpecialBlock(Type::T_ELSE, $s); - } elseif ($this->literal('if', 2) && $this->valueList($cond) && $this->matchChar('{')) { - $else = $this->pushSpecialBlock(Type::T_ELSEIF, $s); - $else->cond = $cond; - } - - if (isset($else)) { - $else->dontAppend = true; - $if->cases[] = $else; - - return true; - } - } - - $this->seek($s); - } - - // only retain the first @charset directive encountered - if ($this->literal('@charset', 8) && - $this->valueList($charset) && - $this->end() - ) { - if (! isset($this->charset)) { - $statement = [Type::T_CHARSET, $charset]; - - list($line, $column) = $this->getSourcePosition($s); - - $statement[static::SOURCE_LINE] = $line; - $statement[static::SOURCE_COLUMN] = $column; - $statement[static::SOURCE_INDEX] = $this->sourceIndex; - - $this->charset = $statement; - } - - return true; - } - - $this->seek($s); - - // doesn't match built in directive, do generic one - if ($this->matchChar('@', false) && - $this->keyword($dirName) && - ($this->variable($dirValue) || $this->openString('{', $dirValue) || true) && - $this->matchChar('{') - ) { - if ($dirName === 'media') { - $directive = $this->pushSpecialBlock(Type::T_MEDIA, $s); - } else { - $directive = $this->pushSpecialBlock(Type::T_DIRECTIVE, $s); - $directive->name = $dirName; - } - - if (isset($dirValue)) { - $directive->value = $dirValue; - } - - return true; - } - - $this->seek($s); - - return false; - } - - // property shortcut - // captures most properties before having to parse a selector - if ($this->keyword($name, false) && - $this->literal(': ', 2) && - $this->valueList($value) && - $this->end() - ) { - $name = [Type::T_STRING, '', [$name]]; - $this->append([Type::T_ASSIGN, $name, $value], $s); - - return true; - } - - $this->seek($s); - - // variable assigns - if ($this->variable($name) && - $this->matchChar(':') && - $this->valueList($value) && - $this->end() - ) { - // check for '!flag' - $assignmentFlags = $this->stripAssignmentFlags($value); - $this->append([Type::T_ASSIGN, $name, $value, $assignmentFlags], $s); - - return true; - } - - $this->seek($s); - - // misc - if ($this->literal('-->', 3)) { - return true; - } - - // opening css block - if ($this->selectors($selectors) && $this->matchChar('{', false)) { - $this->pushBlock($selectors, $s); - - if ($this->eatWhiteDefault) { - $this->whitespace(); - $this->append(null); // collect comments at the begining if needed - } - - return true; - } - - $this->seek($s); - - // property assign, or nested assign - if ($this->propertyName($name) && $this->matchChar(':')) { - $foundSomething = false; - - if ($this->valueList($value)) { - if (empty($this->env->parent)) { - $this->throwParseError('expected "{"'); - } - - $this->append([Type::T_ASSIGN, $name, $value], $s); - $foundSomething = true; - } - - if ($this->matchChar('{')) { - $propBlock = $this->pushSpecialBlock(Type::T_NESTED_PROPERTY, $s); - $propBlock->prefix = $name; - $foundSomething = true; - } elseif ($foundSomething) { - $foundSomething = $this->end(); - } - - if ($foundSomething) { - return true; - } - } - - $this->seek($s); - - // closing a block - if ($this->matchChar('}')) { - $block = $this->popBlock(); - - if (isset($block->type) && $block->type === Type::T_INCLUDE) { - $include = $block->child; - unset($block->child); - $include[3] = $block; - $this->append($include, $s); - } elseif (empty($block->dontAppend)) { - $type = isset($block->type) ? $block->type : Type::T_BLOCK; - $this->append([$type, $block], $s); - } - - return true; - } - - // extra stuff - if ($this->matchChar(';') || - $this->literal(' -baz {bar: baz} - - -/* - * foo - */ -bar {baz: bang} - - -E, F { - a: b; } - - -E F, G H { - a: b; } - - -E > F, G > H { - a: b; } - - -/* This is a CSS comment. */ -.one {color: green;} /* Another comment */ -/* The following should not be used: -.two {color: red;} */ -.three {color: green; /* color: red; */} -/** -.four {color: red;} */ -.five {color: green;} -/**/ -.six {color: green;} -/*********/ -.seven {color: green;} -/* a comment **/ -.eight {color: green;} - - -foo { - a: \foo bar; - b: foo\ bar; - c: \2022 \0020; - d: foo\\bar; - e: foo\"\'bar; } - - -foo { - a: "\foo bar"; - b: "foo\ bar"; - c: "\2022 \0020"; - d: "foo\\bar"; - e: "foo\"'bar"; } - - -foo { - _name: val; - *name: val; - :name: val; - .name: val; - #name: val; - name/**/: val; - name/*\**/: val; - name: val; } - - -@foo "bar" ; - -foo { - a: -moz-element(#foo); - b: -webkit-element(#foo); - b: -foobar-element(#foo); } - - -@foo {} - -@foo { -} - - -@foo; - -foo {;;;; - bar: baz;;;; - ;;} - - -#foo .bar {} - -#foo .bar { -} - - -0% { - a: b; } - - -60% { - a: b; } - - -100% { - a: b; } - - -12px { - a: b; } - - -"foo" { - a: b; } - - -foo { - a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); } - - -:foo("bar") { - a: b; } - - -:foo(bar) { - a: b; } - - -:foo(12px) { - a: b; } - - -:foo(+) { - a: b; } - - -:foo(-) { - a: b; } - - -:foo(+"bar") { - a: b; } - - -:foo(-++--baz-"bar"12px) { - a: b; } - - -foo { - a: foo-bar(12); - b: -foo-bar-baz(13, 14 15); } - - -@import "foo.css"; - -@import 'foo.css'; - -@import url("foo.css"); - -@import url('foo.css'); - -@import url(foo.css); - -@import "foo.css" screen; - -@import "foo.css" screen, print; - -@import "foo.css" screen, print and (foo: 0); - -@import "foo.css" screen, only print, screen and (foo: 0); - -foo { - a: foo !important; - b: foo bar !important; - b: foo, bar !important; } - - -foo { - a: -moz-bar-baz; - b: foo -o-bar-baz; } - - -foo {a: /* b; c: */ d} - - -foo {a /*: b; c */: d} - - -/* Foo - * Bar */ - - -.foo { - /* Foo - * Bar */ } - - -[foo] { - a: b; } - - -[foo="bar"] { - a: b; } - - -[foo~="bar"] { - a: b; } - - -[foo^="bar"] { - a: b; } - - -[foo$="bar"] { - a: b; } - - -[foo*="bar"] { - a: b; } - - -[foo|="en"] { - a: b; } - - -:root { - a: b; } - - -:nth-child(n) { - a: b; } - - -:nth-last-child(n) { - a: b; } - - -:nth-of-type(n) { - a: b; } - - -:nth-last-of-type(n) { - a: b; } - - -:first-child { - a: b; } - - -:last-child { - a: b; } - - -:first-of-type { - a: b; } - - -:last-of-type { - a: b; } - - -:only-child { - a: b; } - - -:only-of-type { - a: b; } - - -:empty { - a: b; } - - -:link { - a: b; } - - -:visited { - a: b; } - - -:active { - a: b; } - - -:hover { - a: b; } - - -:focus { - a: b; } - - -:target { - a: b; } - - -:lang(fr) { - a: b; } - - -:enabled { - a: b; } - - -:disabled { - a: b; } - - -:checked { - a: b; } - - -::first-line { - a: b; } - - -::first-letter { - a: b; } - - -::before { - a: b; } - - -::after { - a: b; } - - -.warning { - a: b; } - - -#myid { - a: b; } - - -:not(s) { - a: b; } - - -@media all { - rule1 { - prop: val; } - - rule2 { - prop: val; } } - - -@media screen, print { - rule1 { - prop: val; } - - rule2 { - prop: val; } } - - -@media screen and (-webkit-min-device-pixel-ratio:0) { - a: b; } - - -@media only screen, print and (foo: 0px) and (bar: flam(12px solid)) { - a: b; } - - -:-moz-any(h1, h2, h3) { - a: b; } - - -:-moz-any(.foo) { - a: b; } - - -:-moz-any(foo bar, .baz > .bang) { - a: b; } - - -@-moz-document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), - domain(mozilla.org), - regexp("^https:.*") { - .foo {a: b} -} - - -foo { - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); - filter:progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); } - - -foo { - filter: alpha(opacity=20); - filter: alpha(opacity=20, enabled=true); - filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); } - - -@foo bar { - a: b; } - -@bar baz { - c: d; } - - -@foo bar; -@bar baz; - - -/* Foo - * Bar */ -/* Baz - * Bang */ - - -.foo { - /* Foo - * Bar */ - /* Baz - * Bang */ } - - -.foo { - /* Foo Bar *//* Baz Bang */ } - - -@namespace "http://www.w3.org/Profiles/xhtml1-strict"; - -@namespace url(http://www.w3.org/Profiles/xhtml1-strict); - -@namespace html url("http://www.w3.org/Profiles/xhtml1-strict"); - -[foo|bar=baz] { - a: b; } - - -[*|bar=baz] { - a: b; } - - -[foo|bar|=baz] { - a: b; } - - -foo|E { - a: b; } - - -*|E { - a: b; } - - -foo|* { - a: b; } - - -*|* { - a: b; } - - -:not(foo|bar) { - a: b; } - - -:not(*|bar) { - a: b; } - - -:not(foo|*) { - a: b; } - - -:not(*|*) { - a: b; } - - -:not(#blah) { - a: b; } - - -:not(.blah) { - a: b; } - - -:not([foo]) { - a: b; } - - -:not([foo^="bar"]) { - a: b; } - - -:not([baz|foo~="bar"]) { - a: b; } - - -:not(:hover) { - a: b; } - - -:not(:nth-child(2n + 3)) { - a: b; } - - -:not(:not(#foo)) { - a: b; } - - -:not(a#foo.bar) { - a: b; } - - -:not(#foo .bar > baz) { - a: b; } - - -:not(h1, h2, h3) { - a: b; } - - -@mixin foo { - a: b; } - - -foo { - a: "bang #{1 + " bar "} bip"; } - - -:nth-child(-n) { - a: b; } - - -:nth-child(+n) { - a: b; } - - -:nth-child(even) { - a: b; } - - -:nth-child(odd) { - a: b; } - - -:nth-child(50) { - a: b; } - - -:nth-child(-50) { - a: b; } - - -:nth-child(+50) { - a: b; } - - -:nth-child(2n+3) { - a: b; } - - -:nth-child(2n-3) { - a: b; } - - -:nth-child(+2n-3) { - a: b; } - - -:nth-child(-2n+3) { - a: b; } - - -:nth-child(-2n+ 3) { - a: b; } - - -:nth-child( 2n + 3 ) { - a: b; } - - -foo { - a: foo bar baz; - b: foo, #aabbcc, -12; - c: 1px/2px/-3px; - d: foo bar, baz/bang; } - - -@page { - prop1: val; - prop2: val; } - - -@page flap { - prop1: val; - prop2: val; } - - -@page :first { - prop1: val; - prop2: val; } - - -@page flap:first { - prop1: val; - prop2: val; } - - -.foo { - /* Foo */ - a: b; } - - -.foo { - /* Foo - * Bar */a: b; } - - -/* Foo */ -.foo { - a: b; } - - -/* Foo - * Bar */.foo { - a: b; } - - -.foo /* .a #foo */ #bar:baz(/* bang )*/ bip) { - a: b; } - - -> E { - a: b; } - - -+ E { - a: b; } - - -~ E { - a: b; } - - -> > E { - a: b; } - - ->> E { - a: b; } - - -E* { - a: b; } - - -E*.foo { - a: b; } - - -E*:hover { - a: b; } - - -E, -F { - a: b; } - - -E -F { - a: b; } - - -E, F -G, H { - a: b; } - - -body { - /* - //comment here - */ -} - - -E>F { a: b;} - -E~F { a: b;} - -E+F { a: b;} - -* { - a: b; } - - -E { - a: b; } - - -E[foo] { - a: b; } - - -E[foo="bar"] { - a: b; } - - -E[foo~="bar"] { - a: b; } - - -E[foo^="bar"] { - a: b; } - - -E[foo$="bar"] { - a: b; } - - -E[foo*="bar"] { - a: b; } - - -E[foo|="en"] { - a: b; } - - -E:root { - a: b; } - - -E:nth-child(n) { - a: b; } - - -E:nth-last-child(n) { - a: b; } - - -E:nth-of-type(n) { - a: b; } - - -E:nth-last-of-type(n) { - a: b; } - - -E:first-child { - a: b; } - - -E:last-child { - a: b; } - - -E:first-of-type { - a: b; } - - -E:last-of-type { - a: b; } - - -E:only-child { - a: b; } - - -E:only-of-type { - a: b; } - - -E:empty { - a: b; } - - -E:link { - a: b; } - - -E:visited { - a: b; } - - -E:active { - a: b; } - - -E:hover { - a: b; } - - -E:focus { - a: b; } - - -E:target { - a: b; } - - -E:lang(fr) { - a: b; } - - -E:enabled { - a: b; } - - -E:disabled { - a: b; } - - -E:checked { - a: b; } - - -E::first-line { - a: b; } - - -E::first-letter { - a: b; } - - -E::before { - a: b; } - - -E::after { - a: b; } - - -E.warning { - a: b; } - - -E#myid { - a: b; } - - -E:not(s) { - a: b; } - - -E F { - a: b; } - - -E > F { - a: b; } - - -E + F { - a: b; } - - -E ~ F { - a: b; } - - -@supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) { - .foo { - a: b; - } -} - - -@-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) { - .foo { - a: b; - } -} - - -foo { - foo: bar; - #baz: bang; - #bip: bop; } - - -foo { - a: -2; - b: -2.3em; - c: -50%; - d: -foo(bar baz); } - - -foo { - a: -0.5em; - b: +0.5em; - c: -foo(12px); - d: +foo(12px); - } - - -@charset "UTF-8"; - -foo { - -moz-foo-bar: blat; - -o-flat-blang: wibble; } - -foo { - a: foo(); - b: bar baz-bang() bip; } - -.alpha { - color: #1f2526bf; - background-color: #1f2526ff; } - -$id: 4c29f540779d8549daf934275faea11; -$selector: '.shortcode-' + $id; -#{$selector} { - color: red; -} diff --git a/tests/inputs/selector_functions.scss b/tests/inputs/selector_functions.scss deleted file mode 100644 index 258aa8f9..00000000 --- a/tests/inputs/selector_functions.scss +++ /dev/null @@ -1,148 +0,0 @@ -.foo, .bar, .foo2 .bar2, .foo3 > .bar3 { - @each $selector in & { - content: "#{$selector}"; - } -} - - -.main aside:hover, -.sidebar p { - @each $selector in & { - content: "#{$selector}"; - } -} - -.is-superselector { - content: is-superselector(".is-superselector", ".selector"); /* false */ -} -.is-superselector1 { - content: is-superselector("a", "a.disabled"); /*true*/ -} -.is-superselector2 { - content: is-superselector("a", "a:not(:visited)"); /*true*/ -} - -.is-superselector3 { - content: is-superselector("a", "a[href]"); /*true*/ -} - -.is-superselector4 { - content: is-superselector("a.disabled", "a"); /*false*/ -} - -.is-superselector5 { - content: is-superselector("a.disabled", "a.foo.disabled"); /* true*/ -} - -.is-superselector6 { - content: is-superselector("a.disabled", "a.foo#disabled"); /* false*/ -} - -.is-superselector7 { - content: is-superselector("a", "sidebar a"); /* true*/ -} -.is-superselector8 { - content: is-superselector("sidebar a", "a"); /* false*/ -} -.is-superselector9 { - content: is-superselector("a", "a"); /* true*/ -} - -#{selector-append("a", ".disabled")} { - content:'a.disabled'; -} - -#{selector-append(".accordion", "__copy")} { - content:'.accordion__copy'; -} - -#{selector-append(".accordion", "__copy, __image")} { - content:'.accordion__copy, .accordion__image'; -} - -#{selector-append(".accordion, .slider", "__copy, __image")} { - content:'.accordion__copy, .slider__copy, .accordion__image, .slider__image'; -} - -#{selector-extend("a.disabled", "a", ".link")} { - content: "a.disabled, .link.disabled"; -} -#{selector-extend("a.disabled", "h1", "h2")} { - content: "a.disabled"; -} - -#{selector-extend(".guide .info", ".info", ".content nav.sidebar")} { - content: ".guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar"; -} - -#{selector-nest("ul", "li")} { - content: "ul li"; -} - -#{selector-nest(".alert, .warning", "p")} { - content: ".alert p, .warning p"; -} - -#{selector-nest(".alert", "&:hover")} { - content: ".alert:hover"; -} - -#{selector-nest(".accordion", "&__copy")} { - content: ".accordion__copy"; -} - -@each $selector in selector-parse(".main aside:hover, .sidebar p") { - #{$selector} { - @each $part in $selector { - content: "#{$part}"; - } - } -} - -#{selector-replace("a.disabled", "a", ".link")} { - content: ".link.disabled"; -} -#{selector-replace("a.disabled", "h1", "h2")} { - content: "a.disabled"; -} - -#{selector-replace(".guide .info", ".info", ".content nav.sidebar")} { - content: ".guide .content nav.sidebar, .content .guide nav.sidebar"; -} - -#{simple-selectors("a.disabled")} { - /* a, .disabled */ - @each $part in simple-selectors("a.disabled") { - content:"#{$part}"; - } -} -#{simple-selectors("main.blog:after")} { - /* main, .blog, :after */ - @each $part in simple-selectors("main.blog:after") { - content:"#{$part}"; - } -} - -#{selector-unify("a", ".disabled")} { - content:"a.disabled"; -} - -#{selector-unify("a.disabled", "a.outgoing")} { - content: "a.disabled.outgoing"; -} - -#{selector-unify("a", "h1")} { - content: "null"; -} - -#{selector-unify(".warning a", "main a")} { - content: ".warning main a, main .warning a"; -} - -#{selector-unify("main.warning a", "main a.disabled")} { - content: "main.warning a.disabled"; -} - -#{selector-unify("main .warning a", "main a")} { - content: "main .warning a"; -} diff --git a/tests/inputs/selectors.scss b/tests/inputs/selectors.scss deleted file mode 100644 index 0b9092c2..00000000 --- a/tests/inputs/selectors.scss +++ /dev/null @@ -1,299 +0,0 @@ -* { color: blue; } -E { color: blue; } - -E:not(:link) { color: blue; } -E:not(:link):not(:visited) { color: blue; } -E:not(:link, :visited) { color: blue; } -E:matches(:hover, :focus) { color: blue; } - -E.warning { color: blue; } -E#id { color: blue; } -E[foo] { color: blue; } -E[foo="barbar"] { color: blue; } -E[foo="barbar" i] { color: blue; } -E[foo~="hello#$@%@$#^"] { color: blue; } -E[foo^="color: green;"] { color: blue; } -E[foo$="239023"] { color: blue; } -E[foo*="29302"] { color: blue; } -E[foo|="239032"] { color: blue; } - -[foo] { color: blue; } -[foo] .helloWorld { color: blue; } -[foo].helloWorld { color: blue; } -[foo="barbar"] { color: blue; } -[foo~="hello#$@%@$#^"] { color: blue; } -[foo^="color: green;"] { color: blue; } -[foo$="239023"] { color: blue; } -[foo*="29302"] { color: blue; } -[foo|="239032"] { color: blue; } - -E:dir(ltr) { color: blue; } -E:lang(en) { color: blue; } -E:lang(en, fr) { color: blue; } - -E:any-link { color: blue; } -E:link { color: blue; } -E:visited { color: blue; } -E:local-link { color: blue; } -E:local-link(0) { color: red; } -E:local-link(1) { color: white; } -E:local-link(2) { color: red; } -E:target { color: blue; } -E:scope { color: blue; } - -E:current { color: blue; } -E:current(:link) { color: blue; } -E:past { color: blue; } -E:future { color: blue; } - -E:active { color: blue; } -E:hover { color: blue; } -E:focus { color: blue; } -E:enabled { color: blue; } -E:disabled { color: blue; } -E:indeterminate { color: blue; } -E:default { color: blue; } -E:in-range { color: blue; } -E:out-of-range { color: blue; } -E:required { color: blue; } -E:optional { color: blue; } -E:read-only { color: blue; } -E:read-write { color: blue; } - -E:root { color: blue; } -E:empty { color: blue; } -E:first-child { color: blue; } -E:nth-child(odd) { color: blue; } -E:nth-child(2n+1) { color: blue; } -E:nth-child(5) { color: blue; } -E:last-child { color: blue; } -E:nth-last-child(-n+2) { color: blue; } -E:only-child { color: blue; } -E:first-of-type { color: blue; } -E:nth-of-type(2n) { color: blue; } -E:last-of-type { color: blue; } -E:nth-last-of-type(n) { color: blue; } -E:only-of-type { color: blue; } -E:nth-match(odd) { color: blue; } -E:nth-last-match(odd) { color: blue; } - -E:column(n) { color: blue; } -E:nth-column(n) { color: blue; } -E:nth-last-column(n) { color: blue; } - -E F { color: blue; } -E > F { color: blue; } -E + F { color: blue; } -E ~ F { color: blue; } -E /foo/ F { color: blue; } -E! > F { color: blue; } - -// namespaces -[foo|att=val] { color: blue } -[*|att] { color: yellow } -[|att] { color: green } -[att] { color: green } - -// CSS2.1 -E::first-line { color: blue; } -E::first-letter { color: blue; } -E::before { color: blue; } -E::after { color: blue; } - -// CSS3 UI (at risk) -E::choices { color: blue; } -E::value { color: blue; } -E::repeat-index { color: blue; } -E::repeat-item { color: blue; } - -E:first { color: blue; } -E:first-line { color: blue; } -E:first-letter { color: blue; } -E:before{ color: blue; } -E:after { color: blue; } -E:checked { color: blue; } -E:invalid { color: blue; } -E:valid { color: blue; } -E:left { color: blue; } -E:right { color: blue; } - -// -moz experimental -E:any(ol) { color: blue; } -E::selection { color: blue; } - -// one of these is nested property, -// the other is a css block. -div { - font:something { - size: 30em; - } - - font: something { - size: 30em; - } - -} - -// self selector - -.something { - &.world { - color: blue; - } - - & .mold { - height: 200px; - } - - .dog & { - color: blue; - } -} - -.simple { - .dad & .wolf { - color: blue; - } - - .rad&.bad { - color: blue; - } - -} - -div { - .something & .what { - &.world { - color: blue; - } - } -} - -div { - &.foo & { - color: blue; - } - & + & { - color: green; - } -} - -.main, div { - .message div { - .title { - .nice-fonts & { - font-size: 24px; - } - } - } -} - -$name: escape; -.#{$name}\% { - color: red; -} - -.escape-plan\% { - color: green; -} - -.element { - #{".one, .two"} { - property: value; - } -} - -@function H($el:false) -{ - $h: (); - $newList: (); - @each $ord in 1,2,3,4,5,6 { - @if $el { - $h: h#{$ord $el}; - } @else { - $h: h#{$ord}; - } - $newList: append($newList, $h, comma); - } - @return $newList; -} - -@mixin H($prop, $val, $el:false) { - $list: H($el); - #{$list} { - #{$prop}: $val; - } -} - -#secondary { - @include H(color, #e6e6e6); -} - -@function tester() { - @return (foo, bar); -} -.test { - #{tester()} { - border: 1px dashed red; - } -} - -$span: 'span'; -$p: 'p'; -$div: 'div'; - -$all: $span, $p, $div; - -#{$all} { - a { - color: red; - } -} - -.parent { - $sub: unquote(".child"); - $self: unquote("&.self2"); - &.self { // works perfectly - content: "should match .parent.self"; - } - #{$sub} { // works as it should - content: "should match .parent .child"; - } - #{$self} { // does not work (see below) - content: "should match .parent.self2"; - } -} - -.parent { - $selfMultiple: unquote("&.self1, &.self2"); - #{$selfMultiple} { - content: "should match .parent.self1, .parent.self2"; - } - - $trailingSelf: unquote(".self1 &"); - #{$trailingSelf} { - content: "should match .self1 .parent"; - } - - $doubleSelf: unquote("& + &"); - #{$doubleSelf} { - content: "should match .parent + .parent"; - } -} - -// combinatorial self -ul, ol { - & & { - display: block; - } -} - -// unicode -.👤 { - display: inline-block; -} - -.❮ { - display:inline; - content:'↦'; -} diff --git a/tests/inputs/short_circuit.scss b/tests/inputs/short_circuit.scss deleted file mode 100644 index 84f317a7..00000000 --- a/tests/inputs/short_circuit.scss +++ /dev/null @@ -1,3 +0,0 @@ -$test: if(true, 1, $undefined); -$test: false and $undefined; -$test: true or $undefined; diff --git a/tests/inputs/shorthand.scss b/tests/inputs/shorthand.scss deleted file mode 100644 index ac1d712d..00000000 --- a/tests/inputs/shorthand.scss +++ /dev/null @@ -1,47 +0,0 @@ -/* short-hand properties */ -div { - // position / background-size - background: 0px 0px / 12px; - background: 25% 75% / cover; - background: center / 50%; - background: left / 3em; - background: right / auto; - background: top / contain; - background: 0px 0px, center / 50% auto; - background: 0px 0px, center / 3em 25%; - - // size / line-height - font: 0.8em / normal; - font: 12px / normal; - font: 80% / normal; - font: large / 34%; - font: large / 3.5; - font: large / 3em; - font: larger / normal; - font: 0.8em / 3.5; - font: 12px / 3em; - font: 80% / 34%; - - /* size | family */ - font: 2em "Open Sans", sans-serif; - - /* style | size | family */ - font: italic 2em "Open Sans", sans-serif; - - /* style | variant | weight | size/line-height | family */ - font: italic small-caps bolder 16px/3 cursive; - - /* The font used in system dialogs */ - font: message-box; - - grid-column: 1 / 3; - grid-column: 2 / -1; - grid-column: auto / auto; - grid-column: span 3 / 6; - grid-column: 5 somegridarea span / 2 span; - grid-row: 1 / 3; - grid-row: 2 / -1; - grid-row: auto / auto; - grid-row: span 3 / 6; - grid-row: 5 somegridarea span / 2 span; -} diff --git a/tests/inputs/values.scss b/tests/inputs/values.scss deleted file mode 100644 index b4111ddb..00000000 --- a/tests/inputs/values.scss +++ /dev/null @@ -1,59 +0,0 @@ - -#values { - color: #eee; - color: #eeeeee; - height: 20px; - width: 80%; - color: "hello world"; - height: url("http://google.com"); - background-image: url(//host/image.png -); - dads: url(http://leafo.net); - padding: 10px 10px 10px 10px, 3px 3px 3px; - textblock: "This is a \ -multiline block \ -#not { color: #eee;}"; - margin: 4,3,1; - content: "This is a \ -multiline string."; - border-radius: -1px -1px -1px black; - grid-template-columns: [avatar] 2fr [body] 6fr; -} - -#subtraction { - lit: 10 -11; - lit: 10 - 11; - lit: 10- 11; - lit: 10-11; - - $num: 100; - var: 10 -$num; - var: 10 - $num; - var: 10- $num; - var: 10-$num; -} - - -#special { - a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); -} - -#unary { - b: +0.5em; - c: -foo(12px); - d: +foo(12px); -} - -#self { - $self1: #{&}; - $self2: &; - content:'#{$self2}'; -} - -@font-face { - unicode-range: U+26; - unicode-range: U+0-7F; - unicode-range: U+0025-00FF; - unicode-range: U+4??; - unicode-range: U+0025-00FF, U+4??; -} diff --git a/tests/inputs/variables.scss b/tests/inputs/variables.scss deleted file mode 100644 index d6461a86..00000000 --- a/tests/inputs/variables.scss +++ /dev/null @@ -1,89 +0,0 @@ - -$color: red, two, three; - -div { - height: $color; -} - -$a: 1000; - -div { - $a: 2000 !default; - num: $a; -} - -div { - $b: 2000 !default; - num: $b; -} - -$cool_color: null; -$cool_color: blue !default; - -pre { - color: $cool_color; -} - -$something_man: 100px; -cool: $something_man; - - -del { - $something: blue; - - div { - $something: red; - pre { - color: $something; - } - } - - color: $something; -} - -$font-family-simple: Arial !default; -$font-family-spaces: Helvetica Neue !default; -$font-family-quotes: "Helvetica Neue" !default; -$font-family-commas: Helvetica, Arial, sans-serif !default; -$font-family-sans: "Helvetica Neue", Helvetica, Arial, sans-serif !default; - -body { - font-family: $font-family-simple; - font-family: $font-family-spaces; - font-family: $font-family-quotes; - font-family: $font-family-commas; - font-family: $font-family-sans; -} - -#main { - $width: 5em !global; - width: $width; -} - -#sidebar { - width: $width; -} - -@mixin example { - $color: red; -} - -A { - $color: green; - @include example; - color: $color; -} - -$цвет : #000; - -body -{ - color: $цвет; -} - -$test: 12 !default !global; - -* { - // Expected: 12 - data: $test; -} diff --git a/tests/outputs/at_root.css b/tests/outputs/at_root.css deleted file mode 100644 index 6fe091bf..00000000 --- a/tests/outputs/at_root.css +++ /dev/null @@ -1,113 +0,0 @@ -.parent-inline-selector { - color: white; } - .child { - color: black; } - -.parent-block { - color: white; } - .child1 { - color: green; } - .child2 { - color: blue; } - .parent-block .step-child { - color: black; } - -.first { - color: red; } - -body .second { - color: white; - color: black; } - .nested1 { - color: blue; - color: orange; } - .nested2 { - color: yellow; } - -.third { - color: green; } - -@media print { - .page { - width: 8in; } } - .page { - color: red; } - -@media (min-width: 300px) { - .my-widget .inside-mq { - inside-style: mq; } } - .my-widget .outside-mq { - outside-style: mq; } - .outside-class { - color: blue; } - @media (min-width: 300px) { - .with-only { - color: pink; } } - -@media screen and (max-width: 320px) { - .foo { - margin: 0; } } - -@media screen and (max-width: 320px) { - .bar { - padding: 0; } } - .baar { - padding: 0; } - .foo .barr { - padding: 0; } - - - .foo .bar { - width: 0; } - @supports ( display: flex ) { - .baz { - height: 0; } } - -@media screen and (max-width: 640px) { - .qux { - margin: 0; } } - -@media screen and (max-width: 640px) { - .foo .quux { - padding: 0; } } - .foo .quix { - padding: 0; } - -.test .test2 { - padding: 0px; } - tbody { - padding: 10px; } - -a.badge { - text-decoration: none; } - -.badge-primary { - background-color: blue; } - a.badge-primary:focus, a.badge-primary.focus { - outline: 0; } - -.badge-secondary { - background-color: yellow; } - a.badge-secondary:focus, a.badge-secondary.focus { - outline: 0; } - -.table-hover tbody tr:hover, .table2#id tbody tr:hover { - color: #ddd; - background-color: #eee; } - .table-hover tbody tr.foo, .table2#id tbody tr.foo { - color: red; } - -.badge { - display: inline-block; } - @media (prefers-reduced-motion: reduce) { - .badge { - transition: none; } } - a.badge:hover, a.badge:focus { - text-decoration: none; } - -.btn:hover, .btn:focus { - text-decoration: none; } - -.other { - content: "bar"; - content: "foo"; } diff --git a/tests/outputs/builtins.css b/tests/outputs/builtins.css deleted file mode 100644 index 94f29b4e..00000000 --- a/tests/outputs/builtins.css +++ /dev/null @@ -1,174 +0,0 @@ -#color { - color: #22ea18; - red: 34; - green: 234; - blue: 24; - color: rgba(1, 2, 4, 0.5); - a1: 1; - a2: 0.5; - mix: #020304; - rgba: rgba(170, 119, 204, 0.4); - rgba: rgba(170, 119, 204, 0.4); - green: 139; } - -#hsl { - color: #79c653; - color: rgba(121, 198, 83, 0.5); - hue: 100deg; - sat: 50%; - lig: 55%; } - -#more-color { - light: #7e3d9e; - dark: #432154; - sat: #632782; - desat: #5e3871; - gray: #545454; - comp: #48792f; - inv: #9fd086; } - -#more-more-color { - op: 0.5; - opacify: rgba(1, 2, 3, 0.6); - opacify: rgba(1, 2, 3, 0.6); - transparentize: rgba(1, 2, 3, 0.4); - transparentize: rgba(1, 2, 3, 0.4); - transparentize: rgba(52, 130, 3, 0.9); } - -#more-more-more-color { - color: rgba(65, 110, 79, 0.4); - color: rgba(20, 255, 216, 0); - color: rgba(55, 100, 69, 0.4); - color: rgba(0, 255, 213, 0); - color: rgba(145, 10, 10, 0); - color: rgba(5, 10, 10, 0); - color: rgba(145, 145, 145, 0); - color: rgba(5, 5, 5, 0); - color: #000A0A0A; - color: #FFAABBCC; } - -#string { - color: hello what is going on; - color: "yeah"; - color: "I do?"; - color: 2; - color: sinserttring; - color: s\\tring; - color: 6; - color: tri; - color: trin; - color: 'string'; - color: STRING; - color: string; - color: string; - color: tring; - color: ring; - color: ing; - color: ng; - color: g; - color: ng; - color: ing; - color: ring; - color: tring; - color: s; - color: st; - color: string; - color: strin; } - -#number { - color: 250%; - color: 50%; - color: 3; - color: 3; - color: 4; - top: 10px; - top: 1ex; - width: 200%; - bottom: 10px; - padding: 3em 1in 96px 72pt; } - -#list { - len: 3; - len: 1; - n: hello; - hello: one, two, three, hello; - hello: one, two, three, hello, world, what, is, going; - hello: one, two, three, hello; - index: 2; - index: 3; - index: 1; - index: 1; - index: 2; - index: 2; - index: 1; - display: 1; - world: one, two, three, great, job; - world: one, two, three, great job; - cool: one two three great job; - cool: great job one two three; - zip: 1px solid, 2px dashed; - zip: 1px solid red, 2px dashed green; } - -#introspection { - t: number; - t: string; - t: string; - t: bool; - t: color; - t: color; - t: list; - u: ""; - u: "px"; - u: "em"; - l: true; - l: false; - c: true; - c: false; - c: true; - c: true; - c: false; - c: true; } - -#if { - color: yes; - color: no; - color: yes; - color: yes; } - -.transparent { - r: 0; - g: 0; - b: 0; - a: 0; } - -.alpha { - a: 1; - a: 1; - a: 1; - a: 0.5; - a: alpha(currentColor); } - -#exists { - a: true; - b: true; - c: false; } - -div.call-tests { - a: #0a64ff; - b: #0058ef; - c: b; } - -div.unquote-test { - a: [type='text']; } - -.does-compile-1 { - color: #666; } - -.does-compile-2 { - color: #666; } - -.does-compile-3 { - color: #666; } - -.does-compile-4 { - color: #666; } diff --git a/tests/outputs/comments.css b/tests/outputs/comments.css deleted file mode 100644 index c66b30bf..00000000 --- a/tests/outputs/comments.css +++ /dev/null @@ -1,42 +0,0 @@ -/** what the heck **/ -/** - Here is a block comment - **/ -/*hello*/ -div { - /*yeah*/ - border: 1px solid red; - /* another property */ - color: url('http://mage-page.com'); - string: "hello /* this is not a comment */"; - world: "// neither is this"; - string: 'hello /* this is not a comment */'; - /*what if this is a comment */ - world: '// neither is this'; - what-ever: 100px; - background: url(); - /*this is not a comment?*/ } - -.dummy { - color: blue; } -/* comment 1 */ -a { - /* comment 2 */ - /* comment 3 */ - color: red; - /* comment 4 */ - background-color: red; - /* comment 5 */ - /* comment 6 */ } -/* comment 7 */ -/* коммент */ -/* This is a comment with vars references: -color:red -and a fake #{ doing nothing -radius:2px - */ -.textimage-background-fullheight .background { - /* @noflip */ - display: block; - /* hop */ - width: 100%; } diff --git a/tests/outputs/compass_extract.css b/tests/outputs/compass_extract.css deleted file mode 100644 index 8ae7f379..00000000 --- a/tests/outputs/compass_extract.css +++ /dev/null @@ -1,28 +0,0 @@ -#test-0 { - unit: false; - unit: true; - rhythm: 1.5em; - size: 1; - size: 1; - size: 1; - size: 2; - size: 2; } - -#test-1 { - margin-top: 7.5em; - padding-top: 9em; - padding-bottom: 10.5em; - margin-bottom: 0em; } - -#test-2 { - border-style: solid; - border-width: 0.0625em; - padding: 1.4375em; } - -#test-3 { - border-top-style: solid; - border-top-width: 0.0625em; - padding-top: 1.4375em; - border-bottom-style: solid; - border-bottom-width: 0.0625em; - padding-bottom: 1.4375em; } diff --git a/tests/outputs/content.css b/tests/outputs/content.css deleted file mode 100644 index 6b24aca3..00000000 --- a/tests/outputs/content.css +++ /dev/null @@ -1,42 +0,0 @@ -* html #logo { - background-image: url(/logo.gif); } - -.colors { - background-color: blue; - color: white; - border-color: blue; } - -@media only screen and (max-width: 480px) { - body { - color: red; } } - -#sidebar { - width: 300px; } - @media only screen and (max-width: 480px) { - #sidebar { - width: 100px; } } - -@media only screen and (min-width: 40em) { - .grid-1 { - width: 100%; } - .grid-2 { - width: 100%; } } - -@media only screen and (min-width: 40em) { - .grid-1 { - width: 100%; } - .grid-2 { - width: 100%; } } - -* html * body #logo { - background-image: url(/logo.gif); } - -A { - top: 10px; } - -.test { - display: none; } - -.test_empty_content { - display: inline; - font-weight: bold; } diff --git a/tests/outputs/content_with_function.css b/tests/outputs/content_with_function.css deleted file mode 100644 index 185fe666..00000000 --- a/tests/outputs/content_with_function.css +++ /dev/null @@ -1,2 +0,0 @@ -body { - padding: 1 px; } diff --git a/tests/outputs/default_args.css b/tests/outputs/default_args.css deleted file mode 100644 index 19379e0c..00000000 --- a/tests/outputs/default_args.css +++ /dev/null @@ -1,3 +0,0 @@ -div { - height: red; - margin: 100px; } diff --git a/tests/outputs/directives.css b/tests/outputs/directives.css deleted file mode 100644 index 1cb99889..00000000 --- a/tests/outputs/directives.css +++ /dev/null @@ -1,121 +0,0 @@ -@charset "hello-world"; -@page :left { - div { - color: red; } } - -@page test { - @media yes { - div { - color: red; } } } - -@media something { - @page { - @media else { - div { - height: 200px; } } } } - -div { - color: red; } - @page yeah { - div pre { - height: 20px; } } - -@font-face { - color: red; - height: 20px; } - -@keyframes 'bounce' { - from { - top: 100px; - animation-timing-function: ease-out; } - - 25% { - top: 50px; - animation-timing-function: ease-in; } - - 50% { - top: 100px; - animation-timing-function: ease-out; } - - 75% { - top: 75px; - animation-timing-function: ease-in; } - - to { - top: 100px; } } - -@-webkit-keyframes flowouttoleft { - 0% { - -webkit-transform: translateX(0) scale(1); } - - 60%, 70% { - -webkit-transform: translateX(0) scale(0.7); } - - 100% { - -webkit-transform: translateX(-100%) scale(0.7); } } - -div { - animation-name: 'diagonal-slide'; - animation-duration: 5s; - animation-iteration-count: 10; } - -@keyframes 'diagonal-slide' { - from { - left: 0; - top: 0; } - - to { - left: 100px; - top: 100px; } } - -@document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), - domain(mozilla.org), - regexp("https:.*") { - body { - color: purple; - background: yellow; } } - -@keyframes anim-rotate { - 0% { - transform: rotate(0); } - - 100% { - transform: rotate(360deg); } } - -.bold, .icon-ajax { - font-weight: 700; } - -.custom-selector { - color: blue; } - -@-webkit-keyframes zoomer { - from { - transform: scale(0.5); } - to { - transform: scale(1); } } - -@keyframes zoomer { - from { - transform: scale(0.5); } - to { - transform: scale(1); } } - -@supports (position: sticky) { - .sticky-top .top2 { - position: sticky; } } - -@supports (position: sticky) { - .sticky-top { - position: sticky; - top: 0; } } - -@supports (position: sticky) { - .sticky-top2 { - position: sticky; } } - -@media print { - .table-bordered th, .table-bordered td { - border: 1px solid #ddd !important; } } - @font-face { - font-family: "Glyphicons Halflings"; } diff --git a/tests/outputs/extending_compound_selector.css b/tests/outputs/extending_compound_selector.css deleted file mode 100644 index 5e14829f..00000000 --- a/tests/outputs/extending_compound_selector.css +++ /dev/null @@ -1,10 +0,0 @@ -.foo:after, .bar:after, .bar:before, .baz.bar:before { - color: red; } - .foo:hover:after, .bar:hover:after, .bar:before:hover, .baz.bar:before:hover { - color: blue; } - -a, a:link, a:visited, a:active, a:hover { - color: #fff; } - -.nest a.some-class, .nest a:link.some-class, .nest a:visited.some-class, .nest a:active.some-class, .nest a:hover.some-class { - color: #ccc; } diff --git a/tests/outputs/extends.css b/tests/outputs/extends.css deleted file mode 100644 index bd6b0c9f..00000000 --- a/tests/outputs/extends.css +++ /dev/null @@ -1,174 +0,0 @@ -error, pre seriousError, span seriousError, other, hello { - border: 1px #f00; - background-color: #fdd; } - -pre seriousError, span seriousError { - font-size: 20px; } - -hello { - color: green; } - hello div { - margin: 10px; } - -.cool, .me { - color: red; } - -.blue, .me { - color: purple; } - -a:hover, .hoverlink, #demo .overview .fakelink:hover { - text-decoration: underline; } - -div.hello.world.hmm, pre div.okay.span.world.hmm, pre #butt .umm div.sure.span.world.hmm, #butt .umm pre div.sure.span.world.hmm, code div.okay.span.world.hmm, code #butt .umm div.sure.span.world.hmm, #butt .umm code div.sure.span.world.hmm { - color: blue; } - -.xxxxx .xxxxx .xxxxx, code .xxxxx .xxxxx, code code .xxxxx, code code code, code .xxxxx code, .xxxxx code .xxxxx, .xxxxx code code, .xxxxx .xxxxx code { - color: green; } - -code { - color: red; } - -.alpha, .beta, .gama { - color: red; } - -.beta, .gama { - color: white; } - -.gama { - color: blue; } - -#admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink { - font-weight: bold; } - -a1 b1 c1 d1, x1 y1 z1 w1 b1 c1 d1 { - color: red; } - -a2 b2 c2 d2, a2 x2 y2 z2 w2 c2 d2, x2 y2 z2 a2 w2 c2 d2 { - color: red; } - -a3 b3 c3 d3, a3 b3 x3 y3 z3 w3 d3, x3 y3 z3 a3 b3 w3 d3 { - color: red; } - -a4 b4 c4 d4, a4 b4 c4 x4 y4 z4 w4, x4 y4 z4 a4 b4 c4 w4 { - color: red; } - -#butt .yeah .okay, #butt .yeah .umm .sure, #butt .umm .yeah .sure { - font-weight: bold; } - -a9 b9 s9 t9 v9, a9 b9 s9 t9 x9 y9 z9, a9 b9 x9 y9 s9 t9 z9 { - color: red; } - -@media print { - horse, man { - color: blue; } } - -man { - color: red; } - -wassup { - color: blue; } - -.foo .wassup { - color: blue; } - -#something, .x, .y { - color: red; } - -.nav-justified, .nav-tabs.nav-justified { - text-align: justify; } - -.btn:hover, .edit .actions button:hover, .edit .new .actions button:hover, .btn:active, .edit .actions button:active, .edit .new .actions button:active, .btn.active, .edit .actions button.active, .edit .new .actions button.active, .btn.disabled, .edit .actions button.disabled, .edit .new .actions button.disabled, .btn[disabled], .edit .actions button[disabled], .edit .new .actions button[disabled] { - color: red; } - -.edit .actions button { - float: right; } - -.edit .new .actions { - padding: 0; } - .z, .parent .self.z { - color: red; } - -#content .social-login { - display: block; - float: right; - margin-right: 15px; - width: 250px; } - #content .social-login .facebook, #content .social-login .twitter { - display: block; - width: 255px; - height: 42px; - background: transparent url('images/login-btns.png') no-repeat; - background-position: 0 0; } - #content .social-login .facebook:hover, #content .social-login .twitter:hover { - background-position: 0 -43px; } - #content .social-login .facebook:focus, #content .social-login .twitter:focus, #content .social-login .facebook:active, #content .social-login .twitter:active { - background-position: 0 -86px; } - #content .social-login .twitter { - background-position: 0 -129px; } - #content .social-login .twitter:hover { - background-position: 0 -172px; } - #content .social-login .twitter:active, #content .social-login .twitter:focus { - background-position: 0 -215px; } - -body .to-extend, body .test { - color: red; } - .navbar .navbar-brand, .navbar .navbar-brand:hover { - font-weight: bold; - text-shadow: none; - color: #fff; } - .foo__bar#test, input { - background: red; } - -.selector1, .master-class { - color: blue; } - -.selector2, .master-class { - background: #ccc; } - -.main .block__element, .main .block__element--modifier { - font-size: 14px; } - .main .block__element--modifier { - font-weight: bold; } - -.pagination-bullet { - width: 6px; - height: 6px; - margin-left: 5px; } - .pagination-bullet:first-child { - margin-left: 0; } - .pagination-bullet.is-active { - background-color: white; } - -.parent-nested-foo-include .in-nested-foo .child-nested-foo-include, .parent-nested-foo-include .in-nested-foo .beard + .mustache { - color: green; } - -.btn-group > .btn-lg, .btn-group-lg.btn-group > .btn, .edit .actions .btn-group-lg.btn-group > button, .edit .new .actions .btn-group-lg.btn-group > button { - padding-right: 12px; - padding-left: 12px; } - -.fp-content-center form + div { - padding-left: 0; } - -.form-inline + .a .form-group > b, .form-inline + .a .fp-content-center form + div > b, .fp-content-center .form-inline + .a form + div > b { - margin-bottom: 0; } - -canvas, object, embed.bar { - color: yellow; } - -.popup, input, img.bar, .prepend input.foo, .prepend div.foo { - color: red; } - -div.popup, .prepend div.foo { - color: blue; } - -.before span.popup .after { - color: green; } - -.class1:not(:last-child), .class2:not(.foo):not(:last-child), .class3:not(:last-child) { - color: red; } - -.inline-menu:hover > .sub-menu, .header-menu:hover > .sub-menu { - border-radius: 5px; } - -.myclass { - color: red; } diff --git a/tests/outputs/extends_nesting.css b/tests/outputs/extends_nesting.css deleted file mode 100644 index af3b841a..00000000 --- a/tests/outputs/extends_nesting.css +++ /dev/null @@ -1,33 +0,0 @@ -.btn, .extend .the-button { - padding: 1px; } - -.btn-lg, .btn-group-lg > .btn, .extend .btn-group-lg > .the-button { - font-size: 10px; } - -.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret, .dropup .extend .btn-group-lg > .the-button .caret, .extend .dropup .btn-group-lg > .the-button .caret { - border-width: 100px; } - -.dropup .btn, .dropup .extend .the-button, .extend .dropup .the-button { - content: "dropup btn"; } - .dropup .btn .caret, .dropup .extend .the-button .caret, .extend .dropup .the-button .caret { - content: "dropup btn caret"; } - -.dropup > .btn, .extend .dropup > .the-button { - content: "dropup > btn"; } - .dropup > .btn > .caret, .extend .dropup > .the-button > .caret { - content: "dropup > btn > caret"; } - -.dropup + .btn, .extend .dropup + .the-button { - content: "dropup + btn"; } - .dropup + .btn + .caret, .extend .dropup + .the-button + .caret { - content: "dropup + btn + caret"; } - -.dropup.btn, .extend .the-button.dropup { - content: "dropupbtn"; } - .dropup.btn.caret, .extend .the-button.dropup.caret { - content: "dropupbtncaret"; } - -.nav-bar, header ul { - background: #eee; } - .nav-bar > .item, header ul > .item, header ul > li, header ul.nav-bar > li { - margin: 0 10px; } diff --git a/tests/outputs/filter_effects.css b/tests/outputs/filter_effects.css deleted file mode 100644 index 7d0bee83..00000000 --- a/tests/outputs/filter_effects.css +++ /dev/null @@ -1,20 +0,0 @@ -#number { - -webkit-filter: grayscale(1) sepia(0.5) saturate(0.1) invert(1) opacity(0.5) brightness(0.5) contrast(0.5); } - -#percentage { - -webkit-filter: grayscale(100%) sepia(50%) saturate(10%) invert(100%) opacity(50%) brightness(50%) contrast(50%); } - -#misc { - -webkit-filter: hue-rotate(90deg) blur(10px) drop-shadow(10px -16px 30px purple); } - -#decimal { - opacity: 0.5; - filter: alpha(opacity=50, style=1); } - -#percent { - opacity: 0.5; - filter: alpha(opacity=50); } - -.row { - background-color: #071c23; - color: #2284a1; } diff --git a/tests/outputs/functions.css b/tests/outputs/functions.css deleted file mode 100644 index e89beb8f..00000000 --- a/tests/outputs/functions.css +++ /dev/null @@ -1,54 +0,0 @@ -div { - color: 14px; - sum: 23; } - -div { - hello: 10 55; - hello: 1010 55; - hello: "hello 10 and 55"; } - -del { - color: 1000; } - -div { - hello: "hello foo and bar"; - hello: "hello bar and default"; - hello: "hello Alice, Bob, Tom"; } - -.foo { - test2: -moz-art; } - -div span { - height: 3px; } - -div { - width: 2; } - -p { - color: arglist; } - -.test { - display: 'global'; - display: 'test-mixin'; - display: 'test-mixin'; - display: 'global'; } - -.test-inspect { - n: null; - b1: true; - b2: false; - n1: 0; - s1: ''; - s2: 'hello'; - l1: 1 2; - l2: 3 4; - l3: 5, 6; - l4: (a: 1, b: 2); - l5: (a: 1, b: 2); } - -div { - margin: 1px 1px 2px 2px; - padding: 1px 1px 2px 2px; } - -.test { - color: rgba(159, 159, 159, 0.625); } diff --git a/tests/outputs/ie7.css b/tests/outputs/ie7.css deleted file mode 100644 index 7196fb19..00000000 --- a/tests/outputs/ie7.css +++ /dev/null @@ -1,8 +0,0 @@ -#foo:before { - content: counter(item,".") ": "; } - -#bar:before { - content: counter(item,"."); } - -#fu:before { - content: counter(item); } diff --git a/tests/outputs/if.css b/tests/outputs/if.css deleted file mode 100644 index b9d05205..00000000 --- a/tests/outputs/if.css +++ /dev/null @@ -1,21 +0,0 @@ -div { - color: blue; } - -pre { - val-1: "red"; - val-2: "blue"; - val-3: "blue"; - val-4: "red"; - val-5: "red"; } - -span { - color: blue; - height: 10px; - width: 20px; } - -div { - color: blue; - border-color: green; } - -del { - thing: no; } diff --git a/tests/outputs/if_on_null.css b/tests/outputs/if_on_null.css deleted file mode 100644 index 2dfca956..00000000 --- a/tests/outputs/if_on_null.css +++ /dev/null @@ -1,2 +0,0 @@ -body { - background-color: "red"; } diff --git a/tests/outputs/import.css b/tests/outputs/import.css deleted file mode 100644 index 1cd9b6b4..00000000 --- a/tests/outputs/import.css +++ /dev/null @@ -1,27 +0,0 @@ -@import "foo.css"; -@import "foo" screen; -@import "http://foo.com/bar"; -@import url(foo); -div { - height: 200px; - color: red; } - -pre { - color: red; } - pre div { - height: 200px; - color: red; } - -code div { - height: 200px; - color: red; } - code div { - height: 200px; - color: red; } - -#partial { - color: blue; } - -body { - color: #7c2; - background: gray; } diff --git a/tests/outputs/interpolation.css b/tests/outputs/interpolation.css deleted file mode 100644 index 1b61ba1f..00000000 --- a/tests/outputs/interpolation.css +++ /dev/null @@ -1,82 +0,0 @@ -div { - color: redwhite blue; - color: red white blue; - color: red whiteblue; - color: redwhiteblue; - color: ummyeahwhat; - color: stacked; - font-size: 10px/something; - font-size: 10px / something; - test: "whatworldwrong"; - test: "whatworldwrong"; - test: "whatworldwrong"; - test: "what"world"wrong"; - hi: "what is 16 end"; } - -pre var { - color: red; } - pre var dad { - color: red; } - pre bedvardad { - color: red; } - -cool .thing-1 { - color: red; } - cool .thing-2 { - color: red; } - cool .thing-3 { - color: red; } - cool .thing-4 { - color: red; } - cool .thing-5 { - color: red; } - -abcde { - color: red; } - -#hello, .world { - color: red; } - -#abchelloyeah, .coolworldyes { - color: red; } - -div.element:nth-child(2n) { - display: none; } - -div { - hello: world; - coolhello: world; - helloone: world; - twohelloone: world; - oneabtwo: cool; - hello-world: red; - hello-mold: white; - hello-hello: blue; } - -body { - color: 3; } - -foo, x, y { - color: #abc; } - -div { - prop: a, b; } - -a.badge { - text-decoration: none; } - -.btn-primary { - background: yellow; } - .btn-primary:not(.disabled) { - border-color: red; } - .btn-primary:not(.disabled):focus { - border-width: 3px; } - -.pagination .page-item:first-child .page-link { - border-radius: 5px; } - -.element { - border: 2px solid #000; } - -div > p > strong, div > h1 > strong { - color: red; } diff --git a/tests/outputs/keyword_args.css b/tests/outputs/keyword_args.css deleted file mode 100644 index 441c4ab3..00000000 --- a/tests/outputs/keyword_args.css +++ /dev/null @@ -1,6 +0,0 @@ -pre { - out: alpha fort three palace; } - -div { - hello: 5; - world: -5; } diff --git a/tests/outputs/list.css b/tests/outputs/list.css deleted file mode 100644 index 2e2f542b..00000000 --- a/tests/outputs/list.css +++ /dev/null @@ -1,25 +0,0 @@ -div { - padding: 10px 20px 30px 40px; - margin: 0 10px 10px 10px; - background: linear-gradient(black, white); } - -p { - background: linear-gradient(red, blue); } - -.bracket-list { - background: linear-gradient(red, blue); } - -div { - x: 2; - z: 2; } - -div { - a: 10px; - b: -20px; - c: 30px; - d: 30px; } - -div { - x: space; - y: comma; - z: space; } diff --git a/tests/outputs/looping.css b/tests/outputs/looping.css deleted file mode 100644 index 2d313b1f..00000000 --- a/tests/outputs/looping.css +++ /dev/null @@ -1,85 +0,0 @@ -div { - color: what; - color: is; - color: this; - font: what; - font: is; - font: this; - background: what; - background: is; - background: this; - border: what; - border: is; - border: this; - background: what what; - background: is is; - background: this this; - background: what what; - background: is is; - background: this this; - color: red; } - div h1 { - font-size: 2em; } - div h2 { - font-size: 1.5em; } - div h3 { - font-size: 1.2em; } - -span { - color: 0; - color: 1; - color: 2; - color: 3; - color: 4; - color: 5; - color: 6; - color: 7; - color: 8; - color: 9; - color: 10; } - -pre { - color: 1; - color: 2; - color: 3; - color: 4; - height: 1; - height: 2; - height: 3; - height: 4; - height: 5; - cool: 10; - cool: 9; - cool: 8; - cool: 7; - cool: 6; - cool: 5; - cool: 4; - cool: 3; } - -div { - a: false; - b: true; - c: true; - c: true; } - -body.each { - color: 1; - background-color: 2; - color: 3; - background-color: 4; - color: 5; } - -body.for { - color: 1; - background-color: 2; - color: 3; - background-color: 4; - color: 5; } - -body.while { - color: 1; - background-color: 2; - color: 3; - background-color: 4; - color: 5; } diff --git a/tests/outputs/map.css b/tests/outputs/map.css deleted file mode 100644 index a8898915..00000000 --- a/tests/outputs/map.css +++ /dev/null @@ -1,24 +0,0 @@ -div { - color: black; - color: red; - foo: black, red, #0f0; - bar: color, length; - baz: (color: #fff, color2: red, 'color3': #0f0, length: 40em); - foo: (length: 40em); - bar: true; } - -div { - foo: color black; - bar: color; } - .black { - background-color: #000 !important; } - .grey { - background-color: #888 !important; } - .white { - background-color: #fff !important; } - -div { - a: 1; - b: 2; - color: 1; - background-color: 2; } diff --git a/tests/outputs/media.css b/tests/outputs/media.css deleted file mode 100644 index 8ef1f821..00000000 --- a/tests/outputs/media.css +++ /dev/null @@ -1,131 +0,0 @@ -@media { - div { - color: blue; } } - -@media what { - div { - color: blue; } } - -@media (cool) { - div { - color: blue; } } - -@media (cool: blue) { - div { - color: blue; } } - -@media hello and (world) and (butt: man) { - div { - color: blue; } } - -@media (max-width: 940px) { - color: red; } - -@media not hello and (world) { - color: blue; - pre { - color: blue; } } - @media not hello and (world) { - @media butt { - color: red; - div { - color: red; } } } - -@media c { - color: blue; } - -div { - color: blue; } - @media screen and (-webkit-min-device-pixel-ratio: 1.5) { - div .sidebar { - width: 500px; } } - -div { - position: absolute; } - @media screen { - div { - top: 0; - bottom: 8em; - color: red; } - div p { - margin: 5px; } - - div .success { - color: green; } } - -.button { - width: 300px; - height: 100px; - background: #eee; } - .button :hover { - background: #aaa; } - @media only screen and (max-width: 300px) { - .button { - width: 100px; - height: 100px; } } - -code { - position: absolute; } - @media screen { - code { - height: 10px; } - code pre { - height: 20px; } } - -@media screen and (color: blue) { - dt { - height: 10px; } } - -@media screen { - .screen { - width: 12px; } } - @media only screen { - .only-screen { - height: 11px; } } - -@media only screen { - .only-screen { - width: 14px; } } - @media only screen { - .only-screen { - height: 16px; } } - -@media print { - .only-print { - height: 12px; } } - -@media screen { - .only-print { - height: 12px; } } - -@media not screen { - .not-screen { - height: 15px; } } - -@media only screen and (color: blue) and (width: 13) { - .only-screen { - height: 15px; } } - -@media screen and (max-width: 749px) and (max-width: 600px) and (min-width: 361px) { - .item { - color: red; } } - - - @media not all and (max-width: 450px) { - @media not all and (max-width: 690px) and (orientation: portrait) { - @media (max-width: 1000px) { - a { - color: red; } } } } - - - @media not all and (max-width: 450px) { - @media (max-width: 690px) and (orientation: portrait) and (max-width: 1000px) { - a { - color: red; } } } - - - @media (max-width: 450px) { - @media not all and (max-width: 690px) and (orientation: portrait) { - @media not all and (max-width: 1000px) { - a { - color: red; } } } } diff --git a/tests/outputs/mixins.css b/tests/outputs/mixins.css deleted file mode 100644 index ee692574..00000000 --- a/tests/outputs/mixins.css +++ /dev/null @@ -1,104 +0,0 @@ -div { - color: blue; - color: red; } - div pre { - height: 200px; } - -span { - color: blue; } - span div { - height: 20px; } - -html { - height: 43px; } - -del { - height: 20px; } - -div { - color: white; - color: blue; - color: white; } - -div { - background-image: linear-gradient(left top, red, green); } - -div { - -moz-box-shadow: 10px 10px 5px #888; - -webkit-box-shadow: 10px 10px 5px #888; - box-shadow: 10px 10px 5px #888; - -moz-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; - -webkit-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; - box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; } - -div p { - color: red; - color: blue; } - div p .class { - color: red; } - div p .class div { - height: 20px; } - div p div { - height: 20px; } - div p .top { - top: 0; } - div p .top div { - color: red; } - -div.mixin-content-simple { - color: red; } - -div.mixin-content-with-arg { - background: blue; - color: red; } - -div.mixin-content-with-arg { - background: purple; - height: 20px; } - -div.mixin-content-simple { - height: 43px; } - -div.mixin-content-simple { - color: orange; } - div.mixin-content-simple div { - height: 20px; } - -div.mixin-content-with-arg { - background: purple; - height: 43px; } - -div.mixin-content-with-arg { - background: purple; - color: orange; } - div.mixin-content-with-arg div { - height: 20px; } - -#please-wait { - background: url(/images/logo.png); - position: absolute; - top: 1em; - right: 0; - bottom: 3em; - left: 4em; } - -div.parameter-name-scope { - -webkit-transform: translateX(50px); } - -@-webkit-keyframes change-color { - 0% { - color: green; } - - 100% { - color: red; } } - -@media screen and (min-width:0\0) { - .test { - color: #000; } } - -div { - content: "div"; - content: "div"; } - div p { - content: "p"; - content: "p"; } diff --git a/tests/outputs/nested_mixins.css b/tests/outputs/nested_mixins.css deleted file mode 100644 index a2835432..00000000 --- a/tests/outputs/nested_mixins.css +++ /dev/null @@ -1,18 +0,0 @@ -div .container { - width: 10px; } - div .container .container { - width: 10px; - max-width: 12px; } - div .container .foo { - width: 10px; } - div .container .bar { - width: 12px; } - -@media print, screen and (min-width:640px) { - .position-left { - color: red; - background: yellow; } } - -@media print, screen and (min-width:640px) { - .element { - float: left; } } diff --git a/tests/outputs/nesting.css b/tests/outputs/nesting.css deleted file mode 100644 index 23be1881..00000000 --- a/tests/outputs/nesting.css +++ /dev/null @@ -1,22 +0,0 @@ -div: blue; -body { - color: red; } - -div { - color: red; - height: yes; } - div pre { - color: blue; } - -div { - font: 10px hello world; - font-size: 10px; - font-color: blue; - border-left: 1px solid blue; - border-right: 2px dashed green; } - -#nested-nesting { - bar: baz; - bang-bop: bar; - bang-bip: 1px; - bang-blat-baf: bort; } diff --git a/tests/outputs/null.css b/tests/outputs/null.css deleted file mode 100644 index b21aa46e..00000000 --- a/tests/outputs/null.css +++ /dev/null @@ -1,21 +0,0 @@ -.div { - one: null; - one: world; - one: NULL world; - one: a, b; - two: a, b; } - -p:before { - content: "I ate pies!"; } - -.foo { - -webkit-border-radius: 10; - border-radius: 10; } - -.fu { - -webkit-border-radius: 20; - border-radius: 20; } - -.bar { - -webkit-border-top-left-radius: 30; - border-top-left-radius: 30; } diff --git a/tests/outputs/operators.css b/tests/outputs/operators.css deleted file mode 100644 index 1ec77ea0..00000000 --- a/tests/outputs/operators.css +++ /dev/null @@ -1,185 +0,0 @@ -body { - color: 8; - color: 16; - height: 10px/10px; - color: 6px; - color: 5px; - top: 1.5em; - left: -1cm; - top: 6.2992125984; } - -div { - color: false; - color: true; - color: true; - color: false; - color: what > 3; - color: 0; - color: -1; - color: 1; } - -#units { - test: 2.5748031496in; - test: 13mm; - test: 4em; - test: 11mm; - test: 1.1cm; } - -#modulo { - test: 1; - test: 1cm; } - -#colors { - color: #ff0203; - color: #fe0000; - color: rgba(3, 8, 15, 0.5); - color: rgba(5, 7, 10, 0.5); - color: rgba(2, 4, 6, 0.5); - color: rgba(0, 1, 1, 0.5); - color: rgba(3, 4, 5, 0.5); - color: rgba(0, 0, 1, 0.5); - color: #22f; - color: false; - color: true; - color: true; - color: false; } - -#preserve { - hello: what -going; - hello: what - going; } - -#strings { - hello: what -going; - hello: whatgoing; - hello: whatgoing; - hello: whatgoing; - hello: whatgoing; - hello: "whatgoing"; - hello: goingwhat; - hello: "whatwhat"; } - -#negation { - a: -60; - b: -90; - b: -90; } - -#bools-fail { - and: false and two; - and: one and two; - and: one and false; - or: false or two; - or: one or two; - or: one or false; } - -#bools { - and: false; - and: two; - and: false; - or: two; - or: one; - or: one; - or: two; } - -#nots-fail { - not: false2; - not: not false; - not: not 0; - not: not 1; - not: not ""; - not: not hello; } - -#nots { - not: false2; - not: true; - not: false; - not: false; - not: false; - not: false; - not: true; } - -#string-test { - str: true; - str: false; - str: true; - str: true; - str: xhellohellofalse; - str: true; } - -#special { - cancel-unit: 1; } - -.row .a { - margin: -0.5em; } - -.row .b { - margin: -0.5em; } - -.row .c { - margin: -0.5em; } - -.row .d { - margin: -0.5em; } - -.row .e { - margin: 0 -0.5em; } - -.alt .a { - margin: -0.5em; } - -.alt .b { - margin: -0.5em; } - -.alt .c { - margin: -0.5em; } - -.alt .d { - margin: 0 -0.5em; } - -.alt .e { - margin: 0 -0.5em; } - -.row .f { - margin: -2em; } - -.row .g { - margin: -2em; } - -.row .h { - margin: -2em; } - -.row .i { - margin: -2em; } - -.row .j { - margin: 0 -2em; } - -.alt .f { - margin: -2em; } - -.alt .g { - margin: -2em; } - -.alt .h { - margin: -2em; } - -.alt .i { - margin: 0 -2em; } - -.alt .j { - margin: 0 -2em; } - -div { - *margin-left: 2.0744680851%; } - -.foo { - width: 12.5%; } - -#bools-test { - a: false; - b: true; - f: false; - n: true; - o: true; - p: false; - r: one; - s: one; } diff --git a/tests/outputs/parsing_comments.css b/tests/outputs/parsing_comments.css deleted file mode 100644 index 67d63378..00000000 --- a/tests/outputs/parsing_comments.css +++ /dev/null @@ -1,50 +0,0 @@ -/* comment 1 */ -a { - /* comment 2 */ - color: red; - /* comment 3 */ - /* comment 4 */ } -/* comment 5 */ -/*! comment 1 */ -b { - /*! comment 2 */ - color: red; - /*! comment 3 */ - /*! comment 4 */ } -/*! comment 5 */ -/* - * multi-line comment 1 - */ -c { - /* - * multi-line comment 2 - */ - color: red; - /* - * multi-line comment 3 - */ - /* - * multi-line comment 4 - */ } -/* - * multi-line comment 5 - */ -/*! - * multi-line comment 1 - */ -d { - /*! - * multi-line comment 2 - */ - color: red; - /*! - * multi-line comment 3 - */ - /*! - * multi-line comment 4 - */ } -/*! - * multi-line comment 5 - */ -e { - color: red; } diff --git a/tests/outputs/placeholder_selector.css b/tests/outputs/placeholder_selector.css deleted file mode 100644 index 5c630174..00000000 --- a/tests/outputs/placeholder_selector.css +++ /dev/null @@ -1,10 +0,0 @@ -p a.notice span, p a.error span, #context a.notice span, #context a.error span { - color: blue; - font-weight: bold; - font-size: 2em; } - -p { - padding: 2em; } - -.layout { - color: red; } diff --git a/tests/outputs/scss_css.css b/tests/outputs/scss_css.css deleted file mode 100644 index 3e6270da..00000000 --- a/tests/outputs/scss_css.css +++ /dev/null @@ -1,776 +0,0 @@ -@charset "UTF-8"; -@import "foo.css"; -@import 'foo.css'; -@import url("foo.css"); -@import url('foo.css'); -@import url(foo.css); -@import "foo.css" screen; -@import "foo.css" screen, print; -@import "foo.css" screen, print and (foo: 0); -@import "foo.css" screen, only print, screen and (foo: 0); -[foo~=bar] { - a: b; } - -[foo^=bar] { - a: b; } - -[foo$=bar] { - a: b; } - -[foo*=bar] { - a: b; } - -[foo|=en] { - a: b; } - -foo { - a: 2; - b: 2.3em; - c: 50%; - d: "fraz bran"; - e: flanny-blanny-blan; - f: url(http://sass-lang.com); - h: #abc; } - -selector { - property: value; - property2: value; } - -sel { - p: v; } - -.foo { - /* Foo - Bar - Baz */ - a: b; } - -.foo { - /* Foo - Bar - Baz */ - a: b; } - -.foo { - /* Foo - Bar */ - a: b; } - -.foo { - /* Foo - Bar - Baz */ - a: b; } - -@foo { - a: b; - rule { - a: b; } } - -@foo { - a: b; } - -@bar { - a: b; } - -@foo "bar" - -foo { - a: 12px calc(100%/3 - 2*1em - 2*1px); - b: 12px -moz-calc(100%/3 - 2*1em - 2*1px); - b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px); - b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); } - -foo { - bar: baz; } - -bar { - bar: baz; } - -baz { - bar: baz; } -/* - * foo - */ -bar { - baz: bang; } - -E, F { - a: b; } - -E F, G H { - a: b; } - -E > F, G > H { - a: b; } -/* This is a CSS comment. */ -.one { - color: green; } -/* Another comment */ -/* The following should not be used: - .two {color: red;} */ -.three { - color: green; - /* color: red; */ } -/** - .four {color: red;} */ -.five { - color: green; } -/**/ -.six { - color: green; } -/*********/ -.seven { - color: green; } -/* a comment **/ -.eight { - color: green; } - -foo { - a: \foo bar; - b: foo\ bar; - c: \2022 \0020; - d: foo\\bar; - e: foo\"\'bar; } - -foo { - a: "\foo bar"; - b: "foo\ bar"; - c: "\2022 \0020"; - d: "foo\\bar"; - e: "foo\"'bar"; } - -foo { - _name: val; - *name: val; - :name: val; - .name: val; - #name: val; - name/**/: val; - name/*\**/: val; - name: val; } - -@foo "bar" ; - -foo { - a: -moz-element(#foo); - b: -webkit-element(#foo); - b: -foobar-element(#foo); } - -@foo ; - -foo { - bar: baz; } - -0% { - a: b; } - -60% { - a: b; } - -100% { - a: b; } - -12px { - a: b; } - -foo { - a: b; } - -foo { - a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); } - -:foo("bar") { - a: b; } - -:foo(bar) { - a: b; } - -:foo(12px) { - a: b; } - -:foo(+) { - a: b; } - -:foo(-) { - a: b; } - -:foo(+"bar") { - a: b; } - -:foo(-++--baz-"bar"12px) { - a: b; } - -foo { - a: foo-bar(12); - b: -foo-bar-baz(13, 14 15); } - -foo { - a: foo !important; - b: foo bar !important; - b: foo, bar !important; } - -foo { - a: -moz-bar-baz; - b: foo -o-bar-baz; } - -foo { - a: d; - /* b; c: */ } - -foo { - a: d; - /*: b; c */ } -/* Foo - * Bar */ -.foo { - /* Foo - * Bar */ } - -[foo] { - a: b; } - -[foo="bar"] { - a: b; } - -[foo~="bar"] { - a: b; } - -[foo^="bar"] { - a: b; } - -[foo$="bar"] { - a: b; } - -[foo*="bar"] { - a: b; } - -[foo|="en"] { - a: b; } - -:root { - a: b; } - -:nth-child(n) { - a: b; } - -:nth-last-child(n) { - a: b; } - -:nth-of-type(n) { - a: b; } - -:nth-last-of-type(n) { - a: b; } - -:first-child { - a: b; } - -:last-child { - a: b; } - -:first-of-type { - a: b; } - -:last-of-type { - a: b; } - -:only-child { - a: b; } - -:only-of-type { - a: b; } - -:empty { - a: b; } - -:link { - a: b; } - -:visited { - a: b; } - -:active { - a: b; } - -:hover { - a: b; } - -:focus { - a: b; } - -:target { - a: b; } - -:lang(fr) { - a: b; } - -:enabled { - a: b; } - -:disabled { - a: b; } - -:checked { - a: b; } - -::first-line { - a: b; } - -::first-letter { - a: b; } - -::before { - a: b; } - -::after { - a: b; } - -.warning { - a: b; } - -#myid { - a: b; } - -:not(s) { - a: b; } - -@media all { - rule1 { - prop: val; } - - rule2 { - prop: val; } } - -@media screen, print { - rule1 { - prop: val; } - - rule2 { - prop: val; } } - -@media screen and (-webkit-min-device-pixel-ratio: 0) { - a: b; } - -@media only screen, print and (foo: 0px) and (bar: flam(12px solid)) { - a: b; } - -:-moz-any(h1, h2, h3) { - a: b; } - -:-moz-any(.foo) { - a: b; } - -:-moz-any(foo bar, .baz > .bang) { - a: b; } - -@-moz-document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), - domain(mozilla.org), - regexp("^https:.*") { - .foo { - a: b; } } - -foo { - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); } - -foo { - filter: alpha(opacity=20); - filter: alpha(opacity=20, enabled=true); - filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); } - -@foo bar { - a: b; } - -@bar baz { - c: d; } - -@foo bar; -@bar baz; - - -/* Foo - * Bar */ -/* Baz - * Bang */ - - -.foo { - /* Foo - * Bar */ - /* Baz - * Bang */ } - -.foo { - /* Foo Bar */ - /* Baz Bang */ } - -@namespace "http://www.w3.org/Profiles/xhtml1-strict"; - -@namespace url(http://www.w3.org/Profiles/xhtml1-strict); - -@namespace html url("http://www.w3.org/Profiles/xhtml1-strict"); - -[foo|bar=baz] { - a: b; } - -[*|bar=baz] { - a: b; } - -[foo|bar|=baz] { - a: b; } - -foo|E { - a: b; } - -*|E { - a: b; } - -foo|* { - a: b; } - -*|* { - a: b; } - -:not(foo|bar) { - a: b; } - -:not(*|bar) { - a: b; } - -:not(foo|*) { - a: b; } - -:not(*|*) { - a: b; } - -:not(#blah) { - a: b; } - -:not(.blah) { - a: b; } - -:not([foo]) { - a: b; } - -:not([foo^="bar"]) { - a: b; } - -:not([baz|foo~="bar"]) { - a: b; } - -:not(:hover) { - a: b; } - -:not(:nth-child(2n + 3)) { - a: b; } - -:not(:not(#foo)) { - a: b; } - -:not(a#foo.bar) { - a: b; } - -:not(#foo .bar > baz) { - a: b; } - -:not(h1, h2, h3) { - a: b; } - -foo { - a: "bang 1 bar bip"; } - -:nth-child(-n) { - a: b; } - -:nth-child(+n) { - a: b; } - -:nth-child(even) { - a: b; } - -:nth-child(odd) { - a: b; } - -:nth-child(50) { - a: b; } - -:nth-child(-50) { - a: b; } - -:nth-child(+50) { - a: b; } - -:nth-child(2n+3) { - a: b; } - -:nth-child(2n-3) { - a: b; } - -:nth-child(+2n-3) { - a: b; } - -:nth-child(-2n+3) { - a: b; } - -:nth-child(-2n+ 3) { - a: b; } - -:nth-child( 2n + 3) { - a: b; } - -foo { - a: foo bar baz; - b: foo, #abc, -12; - c: 1px/2px/-3px; - d: foo bar, baz/bang; } - -@page { - prop1: val; - prop2: val; } - -@page flap { - prop1: val; - prop2: val; } - -@page :first { - prop1: val; - prop2: val; } - -@page flap:first { - prop1: val; - prop2: val; } - -.foo { - /* Foo */ - a: b; } - -.foo { - /* Foo - * Bar */ - a: b; } -/* Foo */ -.foo { - a: b; } -/* Foo - * Bar */ -.foo { - a: b; } - -.foo #bar:baz(/* bang )*/ bip) { - /* .a #foo */ - a: b; } - -> E { - a: b; } - -+ E { - a: b; } - -~ E { - a: b; } - -> > E { - a: b; } - ->> E { - a: b; } - -E* { - a: b; } - -E*.foo { - a: b; } - -E*:hover { - a: b; } - -E, F { - a: b; } - -E F { - a: b; } - -E, F G, H { - a: b; } - -body { - /* - //comment here - */ } - -E > F { - a: b; } - -E ~ F { - a: b; } - -E + F { - a: b; } - -* { - a: b; } - -E { - a: b; } - -E[foo] { - a: b; } - -E[foo="bar"] { - a: b; } - -E[foo~="bar"] { - a: b; } - -E[foo^="bar"] { - a: b; } - -E[foo$="bar"] { - a: b; } - -E[foo*="bar"] { - a: b; } - -E[foo|="en"] { - a: b; } - -E:root { - a: b; } - -E:nth-child(n) { - a: b; } - -E:nth-last-child(n) { - a: b; } - -E:nth-of-type(n) { - a: b; } - -E:nth-last-of-type(n) { - a: b; } - -E:first-child { - a: b; } - -E:last-child { - a: b; } - -E:first-of-type { - a: b; } - -E:last-of-type { - a: b; } - -E:only-child { - a: b; } - -E:only-of-type { - a: b; } - -E:empty { - a: b; } - -E:link { - a: b; } - -E:visited { - a: b; } - -E:active { - a: b; } - -E:hover { - a: b; } - -E:focus { - a: b; } - -E:target { - a: b; } - -E:lang(fr) { - a: b; } - -E:enabled { - a: b; } - -E:disabled { - a: b; } - -E:checked { - a: b; } - -E::first-line { - a: b; } - -E::first-letter { - a: b; } - -E::before { - a: b; } - -E::after { - a: b; } - -E.warning { - a: b; } - -E#myid { - a: b; } - -E:not(s) { - a: b; } - -E F { - a: b; } - -E > F { - a: b; } - -E + F { - a: b; } - -E ~ F { - a: b; } - -@supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) { - .foo { - a: b; } } - -@-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) { - .foo { - a: b; } } - -foo { - foo: bar; - #baz: bang; - #bip: bop; } - -foo { - a: -2; - b: -2.3em; - c: -50%; - d: -foo(bar baz); } - -foo { - a: -0.5em; - b: 0.5em; - c: -foo(12px); - d: +foo(12px); } - -foo { - -moz-foo-bar: blat; - -o-flat-blang: wibble; } - -foo { - a: foo(); - b: bar baz-bang() bip; } - -.alpha { - color: rgba(31, 37, 38, 0.749); - background-color: #1f2526; } - -.shortcode-4c29f540779d8549daf934275faea11 { - color: red; } diff --git a/tests/outputs/selector_functions.css b/tests/outputs/selector_functions.css deleted file mode 100644 index b071ef6b..00000000 --- a/tests/outputs/selector_functions.css +++ /dev/null @@ -1,126 +0,0 @@ -.foo, .bar, .foo2 .bar2, .foo3 > .bar3 { - content: ".foo"; - content: ".bar"; - content: ".foo2 .bar2"; - content: ".foo3 > .bar3"; } - -.main aside:hover, .sidebar p { - content: ".main aside:hover"; - content: ".sidebar p"; } - -.is-superselector { - content: false; - /* false */ } - -.is-superselector1 { - content: true; - /*true*/ } - -.is-superselector2 { - content: true; - /*true*/ } - -.is-superselector3 { - content: true; - /*true*/ } - -.is-superselector4 { - content: false; - /*false*/ } - -.is-superselector5 { - content: true; - /* true*/ } - -.is-superselector6 { - content: false; - /* false*/ } - -.is-superselector7 { - content: true; - /* true*/ } - -.is-superselector8 { - content: false; - /* false*/ } - -.is-superselector9 { - content: true; - /* true*/ } - -a.disabled { - content: 'a.disabled'; } - -.accordion__copy { - content: '.accordion__copy'; } - -.accordion__copy, .accordion__image { - content: '.accordion__copy, .accordion__image'; } - -.accordion__copy, .slider__copy, .accordion__image, .slider__image { - content: '.accordion__copy, .slider__copy, .accordion__image, .slider__image'; } - -a.disabled, .link.disabled { - content: "a.disabled, .link.disabled"; } - -a.disabled { - content: "a.disabled"; } - -.guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar { - content: ".guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar"; } - -ul li { - content: "ul li"; } - -.alert p, .warning p { - content: ".alert p, .warning p"; } - -.alert:hover { - content: ".alert:hover"; } - -.accordion__copy { - content: ".accordion__copy"; } - .main aside:hover { - content: ".main"; - content: "aside:hover"; } - .sidebar p { - content: ".sidebar"; - content: "p"; } - -.link.disabled { - content: ".link.disabled"; } - -a.disabled { - content: "a.disabled"; } - -.guide .content nav.sidebar, .content .guide nav.sidebar { - content: ".guide .content nav.sidebar, .content .guide nav.sidebar"; } - -a, .disabled { - /* a, .disabled */ - content: "a"; - content: ".disabled"; } - -main, .blog, :after { - /* main, .blog, :after */ - content: "main"; - content: ".blog"; - content: ":after"; } - -a.disabled { - content: "a.disabled"; } - -a.disabled.outgoing { - content: "a.disabled.outgoing"; } - - { - content: "null"; } - -.warning main a, main .warning a { - content: ".warning main a, main .warning a"; } - -main.warning a.disabled { - content: "main.warning a.disabled"; } - -main .warning a { - content: "main .warning a"; } diff --git a/tests/outputs/selectors.css b/tests/outputs/selectors.css deleted file mode 100644 index 66a6ab15..00000000 --- a/tests/outputs/selectors.css +++ /dev/null @@ -1,379 +0,0 @@ -* { - color: blue; } - -E { - color: blue; } - -E:not(:link) { - color: blue; } - -E:not(:link):not(:visited) { - color: blue; } - -E:not(:link, :visited) { - color: blue; } - -E:matches(:hover, :focus) { - color: blue; } - -E.warning { - color: blue; } - -E#id { - color: blue; } - -E[foo] { - color: blue; } - -E[foo="barbar"] { - color: blue; } - -E[foo="barbar" i] { - color: blue; } - -E[foo~="hello#$@%@$#^"] { - color: blue; } - -E[foo^="color: green;"] { - color: blue; } - -E[foo$="239023"] { - color: blue; } - -E[foo*="29302"] { - color: blue; } - -E[foo|="239032"] { - color: blue; } - -[foo] { - color: blue; } - -[foo] .helloWorld { - color: blue; } - -[foo].helloWorld { - color: blue; } - -[foo="barbar"] { - color: blue; } - -[foo~="hello#$@%@$#^"] { - color: blue; } - -[foo^="color: green;"] { - color: blue; } - -[foo$="239023"] { - color: blue; } - -[foo*="29302"] { - color: blue; } - -[foo|="239032"] { - color: blue; } - -E:dir(ltr) { - color: blue; } - -E:lang(en) { - color: blue; } - -E:lang(en, fr) { - color: blue; } - -E:any-link { - color: blue; } - -E:link { - color: blue; } - -E:visited { - color: blue; } - -E:local-link { - color: blue; } - -E:local-link(0) { - color: red; } - -E:local-link(1) { - color: white; } - -E:local-link(2) { - color: red; } - -E:target { - color: blue; } - -E:scope { - color: blue; } - -E:current { - color: blue; } - -E:current(:link) { - color: blue; } - -E:past { - color: blue; } - -E:future { - color: blue; } - -E:active { - color: blue; } - -E:hover { - color: blue; } - -E:focus { - color: blue; } - -E:enabled { - color: blue; } - -E:disabled { - color: blue; } - -E:indeterminate { - color: blue; } - -E:default { - color: blue; } - -E:in-range { - color: blue; } - -E:out-of-range { - color: blue; } - -E:required { - color: blue; } - -E:optional { - color: blue; } - -E:read-only { - color: blue; } - -E:read-write { - color: blue; } - -E:root { - color: blue; } - -E:empty { - color: blue; } - -E:first-child { - color: blue; } - -E:nth-child(odd) { - color: blue; } - -E:nth-child(2n+1) { - color: blue; } - -E:nth-child(5) { - color: blue; } - -E:last-child { - color: blue; } - -E:nth-last-child(-n+2) { - color: blue; } - -E:only-child { - color: blue; } - -E:first-of-type { - color: blue; } - -E:nth-of-type(2n) { - color: blue; } - -E:last-of-type { - color: blue; } - -E:nth-last-of-type(n) { - color: blue; } - -E:only-of-type { - color: blue; } - -E:nth-match(odd) { - color: blue; } - -E:nth-last-match(odd) { - color: blue; } - -E:column(n) { - color: blue; } - -E:nth-column(n) { - color: blue; } - -E:nth-last-column(n) { - color: blue; } - -E F { - color: blue; } - -E > F { - color: blue; } - -E + F { - color: blue; } - -E ~ F { - color: blue; } - -E /foo/ F { - color: blue; } - -E! > F { - color: blue; } - -[foo|att=val] { - color: blue; } - -[*|att] { - color: yellow; } - -[|att] { - color: green; } - -[att] { - color: green; } - -E::first-line { - color: blue; } - -E::first-letter { - color: blue; } - -E::before { - color: blue; } - -E::after { - color: blue; } - -E::choices { - color: blue; } - -E::value { - color: blue; } - -E::repeat-index { - color: blue; } - -E::repeat-item { - color: blue; } - -E:first { - color: blue; } - -E:first-line { - color: blue; } - -E:first-letter { - color: blue; } - -E:before { - color: blue; } - -E:after { - color: blue; } - -E:checked { - color: blue; } - -E:invalid { - color: blue; } - -E:valid { - color: blue; } - -E:left { - color: blue; } - -E:right { - color: blue; } - -E:any(ol) { - color: blue; } - -E::selection { - color: blue; } - -div { - font: something; - font-size: 30em; } - div font:something { - size: 30em; } - -.something.world { - color: blue; } - .something .mold { - height: 200px; } - .dog .something { - color: blue; } - -.dad .simple .wolf { - color: blue; } - .rad.simple.bad { - color: blue; } - -.something div .what.world { - color: blue; } - -div.foo div { - color: blue; } - div + div { - color: green; } - -.nice-fonts .main .message div .title, .nice-fonts div .message div .title { - font-size: 24px; } - -.escape\% { - color: red; } - -.escape-plan\% { - color: green; } - -.element .one, .element .two { - property: value; } - -#secondary h1, #secondary h2, #secondary h3, #secondary h4, #secondary h5, #secondary h6 { - color: #e6e6e6; } - -.test foo, .test bar { - border: 1px dashed red; } - -span a, p a, div a { - color: red; } - -.parent.self { - content: "should match .parent.self"; } - .parent .child { - content: "should match .parent .child"; } - .parent.self2 { - content: "should match .parent.self2"; } - -.parent.self1, .parent.self2 { - content: "should match .parent.self1, .parent.self2"; } - .self1 .parent { - content: "should match .self1 .parent"; } - .parent + .parent { - content: "should match .parent + .parent"; } - -ul ul, ul ol, ol ul, ol ol { - display: block; } - -.👤 { - display: inline-block; } - -.❮ { - display: inline; - content: '↦'; } diff --git a/tests/outputs/short_circuit.css b/tests/outputs/short_circuit.css deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/outputs/shorthand.css b/tests/outputs/shorthand.css deleted file mode 100644 index 5d587e04..00000000 --- a/tests/outputs/shorthand.css +++ /dev/null @@ -1,38 +0,0 @@ -/* short-hand properties */ -div { - background: 0px 0px / 12px; - background: 25% 75% / cover; - background: center / 50%; - background: left / 3em; - background: right / auto; - background: top / contain; - background: 0px 0px, center / 50% auto; - background: 0px 0px, center / 3em 25%; - font: 0.8em / normal; - font: 12px / normal; - font: 80% / normal; - font: large / 34%; - font: large / 3.5; - font: large / 3em; - font: larger / normal; - font: 0.8em / 3.5; - font: 12px / 3em; - font: 80% / 34%; - /* size | family */ - font: 2em "Open Sans", sans-serif; - /* style | size | family */ - font: italic 2em "Open Sans", sans-serif; - /* style | variant | weight | size/line-height | family */ - font: italic small-caps bolder 16px/3 cursive; - /* The font used in system dialogs */ - font: message-box; - grid-column: 1 / 3; - grid-column: 2 / -1; - grid-column: auto / auto; - grid-column: span 3 / 6; - grid-column: 5 somegridarea span / 2 span; - grid-row: 1 / 3; - grid-row: 2 / -1; - grid-row: auto / auto; - grid-row: span 3 / 6; - grid-row: 5 somegridarea span / 2 span; } diff --git a/tests/outputs/values.css b/tests/outputs/values.css deleted file mode 100644 index 473ce76b..00000000 --- a/tests/outputs/values.css +++ /dev/null @@ -1,43 +0,0 @@ -#values { - color: #eee; - color: #eee; - height: 20px; - width: 80%; - color: "hello world"; - height: url("http://google.com"); - background-image: url(//host/image.png); - dads: url(http://leafo.net); - padding: 10px 10px 10px 10px, 3px 3px 3px; - textblock: "This is a multiline block #not { color: #eee;}"; - margin: 4, 3, 1; - content: "This is a multiline string."; - border-radius: -1px -1px -1px black; - grid-template-columns: [avatar] 2fr [body] 6fr; } - -#subtraction { - lit: 10 -11; - lit: -1; - lit: -1; - lit: -1; - var: -90; - var: -90; - var: -90; - var: -90; } - -#special { - a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); } - -#unary { - b: 0.5em; - c: -foo(12px); - d: +foo(12px); } - -#self { - content: "#self"; } - -@font-face { - unicode-range: U+26; - unicode-range: U+0-7F; - unicode-range: U+0025-00FF; - unicode-range: U+4??; - unicode-range: U+0025-00FF, U+4??; } diff --git a/tests/outputs/variables.css b/tests/outputs/variables.css deleted file mode 100644 index 430efc14..00000000 --- a/tests/outputs/variables.css +++ /dev/null @@ -1,39 +0,0 @@ -cool: 100px; -div { - height: red, two, three; } - -div { - num: 1000; } - -div { - num: 2000; } - -pre { - color: blue; } - -del { - color: blue; } - del div pre { - color: red; } - -body { - font-family: Arial; - font-family: Helvetica Neue; - font-family: "Helvetica Neue"; - font-family: Helvetica, Arial, sans-serif; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } - -#main { - width: 5em; } - -#sidebar { - width: 5em; } - -A { - color: green; } - -body { - color: #000; } - -* { - data: 12; } diff --git a/tests/outputs_numbered/at_root.css b/tests/outputs_numbered/at_root.css deleted file mode 100644 index 84d79764..00000000 --- a/tests/outputs_numbered/at_root.css +++ /dev/null @@ -1,168 +0,0 @@ -/* line 1, inputs/at_root.scss */ -.parent-inline-selector { - color: white; } -/* line 3, inputs/at_root.scss */ -.child { - color: black; } -/* line 6, inputs/at_root.scss */ -.parent-block { - color: white; } -/* line 9, inputs/at_root.scss */ -.child1 { - color: green; } -/* line 10, inputs/at_root.scss */ -.child2 { - color: blue; } -/* line 12, inputs/at_root.scss */ -.parent-block .step-child { - color: black; } -/* line 15, inputs/at_root.scss */ -.first { - color: red; } -/* line 18, inputs/at_root.scss */ -/* line 19, inputs/at_root.scss */ - -body .second { - color: white; - color: black; } -/* line 23, inputs/at_root.scss */ -.nested1 { - color: blue; - color: orange; } -/* line 26, inputs/at_root.scss */ -.nested2 { - color: yellow; } -/* line 36, inputs/at_root.scss */ -.third { - color: green; } - -@media print { -/* line 41, inputs/at_root.scss */ -.page { - width: 8in; } } - -.page { - color: red; } -/* line 49, inputs/at_root.scss */ -@media (min-width: 300px) { -/* line 50, inputs/at_root.scss */ -/* line 51, inputs/at_root.scss */ - .my-widget .inside-mq { - inside-style: mq; } } - -/* line 56, inputs/at_root.scss */ -.my-widget .outside-mq { -outside-style: mq; } -/* line 63, inputs/at_root.scss */ -.outside-class { - color: blue; } - -@media (min-width: 300px) { -/* line 71, inputs/at_root.scss */ -.with-only { - color: pink; } } - -@media screen and (max-width: 320px) { -/* line 81, inputs/at_root.scss */ -.foo { - margin: 0; } } - -@media screen and (max-width: 320px) { -/* line 85, inputs/at_root.scss */ -.bar { - padding: 0; } } -/* line 90, inputs/at_root.scss */ -.baar { - padding: 0; } - -/* line 95, inputs/at_root.scss */ -.foo .barr { -padding: 0; } - -@media screen and (max-width: 640px) { -/* line 104, inputs/at_root.scss */ } -/* line 107, inputs/at_root.scss */ -.foo .bar { - width: 0; } - -@supports ( display: flex ) { -/* line 112, inputs/at_root.scss */ -.baz { - height: 0; } } - -@media screen and (max-width: 640px) { -/* line 117, inputs/at_root.scss */ -.qux { - margin: 0; } } - -@media screen and (max-width: 640px) { -/* line 122, inputs/at_root.scss */ -.foo .quux { - padding: 0; } } -/* line 127, inputs/at_root.scss */ -.foo .quix { - padding: 0; } -/* line 144, inputs/at_root.scss */ -/* line 145, inputs/at_root.scss */ - -.test .test2 { - padding: 0px; } -/* line 139, inputs/at_root.scss */ -tbody { - padding: 10px; } -/* line 151, inputs/at_root.scss */ -/* line 152, inputs/at_root.scss */ - -a.badge { - text-decoration: none; } -/* line 168, inputs/at_root.scss */ -.badge-primary { - background-color: blue; } -/* line 160, inputs/at_root.scss */ -/* line 161, inputs/at_root.scss */ - -a.badge-primary:focus, a.badge-primary.focus { - outline: 0; } -/* line 171, inputs/at_root.scss */ -.badge-secondary { - background-color: yellow; } -/* line 160, inputs/at_root.scss */ -/* line 161, inputs/at_root.scss */ - -a.badge-secondary:focus, a.badge-secondary.focus { - outline: 0; } -/* line 183, inputs/at_root.scss */ -/* line 184, inputs/at_root.scss */ - -/* line 177, inputs/at_root.scss */ - -.table-hover tbody tr:hover, .table2#id tbody tr:hover { - color: #ddd; - background-color: #eee; } -/* line 178, inputs/at_root.scss */ -.table-hover tbody tr.foo, .table2#id tbody tr.foo { - color: red; } -/* line 206, inputs/at_root.scss */ -.badge { - display: inline-block; } - -@media (prefers-reduced-motion: reduce) { -/* line 194, inputs/at_root.scss */ -.badge { - transition: none; } } -/* line 210, inputs/at_root.scss */ -/* line 200, inputs/at_root.scss */ - -a.badge:hover, a.badge:focus { - text-decoration: none; } -/* line 218, inputs/at_root.scss */ -/* line 200, inputs/at_root.scss */ - -.btn:hover, .btn:focus { - text-decoration: none; } -/* line 226, inputs/at_root.scss */ -/* line 229, inputs/at_root.scss */ - -.other { - content: "bar"; - content: "foo"; } diff --git a/tests/outputs_numbered/builtins.css b/tests/outputs_numbered/builtins.css deleted file mode 100644 index 559b6a30..00000000 --- a/tests/outputs_numbered/builtins.css +++ /dev/null @@ -1,175 +0,0 @@ -/* line 2, inputs/builtins.scss */ -#color { - color: #22ea18; - red: 34; - green: 234; - blue: 24; - color: rgba(1, 2, 4, 0.5); - a1: 1; - a2: 0.5; - mix: #020304; - rgba: rgba(170, 119, 204, 0.4); - rgba: rgba(170, 119, 204, 0.4); - green: 139; } -/* line 21, inputs/builtins.scss */ -#hsl { - color: #79c653; - color: rgba(121, 198, 83, 0.5); - hue: 100deg; - sat: 50%; - lig: 55%; } -/* line 30, inputs/builtins.scss */ -#more-color { - light: #7e3d9e; - dark: #432154; - sat: #632782; - desat: #5e3871; - gray: #545454; - comp: #48792f; - inv: #9fd086; } -/* line 44, inputs/builtins.scss */ -#more-more-color { - op: 0.5; - opacify: rgba(1, 2, 3, 0.6); - opacify: rgba(1, 2, 3, 0.6); - transparentize: rgba(1, 2, 3, 0.4); - transparentize: rgba(1, 2, 3, 0.4); - transparentize: rgba(52, 130, 3, 0.9); } -/* line 56, inputs/builtins.scss */ -#more-more-more-color { - color: rgba(65, 110, 79, 0.4); - color: rgba(20, 255, 216, 0); - color: rgba(55, 100, 69, 0.4); - color: rgba(0, 255, 213, 0); - color: rgba(145, 10, 10, 0); - color: rgba(5, 10, 10, 0); - color: rgba(145, 145, 145, 0); - color: rgba(5, 5, 5, 0); - color: #000A0A0A; - color: #FFAABBCC; } -/* line 74, inputs/builtins.scss */ -#string { - color: hello what is going on; - color: "yeah"; - color: "I do?"; - color: 2; - color: sinserttring; - color: s\\tring; - color: 6; - color: tri; - color: trin; - color: 'string'; - color: STRING; - color: string; - color: string; - color: tring; - color: ring; - color: ing; - color: ng; - color: g; - color: ng; - color: ing; - color: ring; - color: tring; - color: s; - color: st; - color: string; - color: strin; } -/* line 106, inputs/builtins.scss */ -#number { - color: 250%; - color: 50%; - color: 3; - color: 3; - color: 4; - top: 10px; - top: 1ex; - width: 200%; - bottom: 10px; - padding: 3em 1in 96px 72pt; } -/* line 120, inputs/builtins.scss */ -#list { - len: 3; - len: 1; - n: hello; - hello: one, two, three, hello; - hello: one, two, three, hello, world, what, is, going; - hello: one, two, three, hello; - index: 2; - index: 3; - index: 1; - index: 1; - index: 2; - index: 2; - index: 1; - display: 1; - world: one, two, three, great, job; - world: one, two, three, great job; - cool: one two three great job; - cool: great job one two three; - zip: 1px solid, 2px dashed; - zip: 1px solid red, 2px dashed green; } -/* line 156, inputs/builtins.scss */ -#introspection { - t: number; - t: string; - t: string; - t: bool; - t: color; - t: color; - t: list; - u: ""; - u: "px"; - u: "em"; - l: true; - l: false; - c: true; - c: false; - c: true; - c: true; - c: false; - c: true; } -/* line 180, inputs/builtins.scss */ -#if { - color: yes; - color: no; - color: yes; - color: yes; } -/* line 187, inputs/builtins.scss */ -.transparent { - r: 0; - g: 0; - b: 0; - a: 0; } -/* line 194, inputs/builtins.scss */ -.alpha { - a: 1; - a: 1; - a: 1; - a: 0.5; - a: alpha(currentColor); } -/* line 203, inputs/builtins.scss */ -#exists { - a: true; - b: true; - c: false; } -/* line 210, inputs/builtins.scss */ -div.call-tests { - a: #0a64ff; - b: #0058ef; - c: b; } -/* line 217, inputs/builtins.scss */ -div.unquote-test { - a: [type='text']; } -/* line 221, inputs/builtins.scss */ -.does-compile-1 { - color: #666; } -/* line 225, inputs/builtins.scss */ -.does-compile-2 { - color: #666; } -/* line 231, inputs/builtins.scss */ -.does-compile-3 { - color: #666; } -/* line 236, inputs/builtins.scss */ -.does-compile-4 { - color: #666; } diff --git a/tests/outputs_numbered/comments.css b/tests/outputs_numbered/comments.css deleted file mode 100644 index f7256abb..00000000 --- a/tests/outputs_numbered/comments.css +++ /dev/null @@ -1,46 +0,0 @@ -/** what the heck **/ -/** - Here is a block comment - **/ -/*hello*/ -/* line 16, inputs/comments.scss */ -div { - /*yeah*/ - border: 1px solid red; - /* another property */ - color: url('http://mage-page.com'); - string: "hello /* this is not a comment */"; - world: "// neither is this"; - string: 'hello /* this is not a comment */'; - /*what if this is a comment */ - world: '// neither is this'; - what-ever: 100px; - background: url(); - /*this is not a comment?*/ } -/* line 31, inputs/comments.scss */ -.dummy { - color: blue; } -/* comment 1 */ -/* line 36, inputs/comments.scss */ -a { - /* comment 2 */ - /* comment 3 */ - color: red; - /* comment 4 */ - background-color: red; - /* comment 5 */ - /* comment 6 */ } -/* comment 7 */ -/* коммент */ -/* This is a comment with vars references: -color:red -and a fake #{ doing nothing -radius:2px - */ -/* line 60, inputs/comments.scss */ -/* line 61, inputs/comments.scss */ - .textimage-background-fullheight .background { - /* @noflip */ - display: block; - /* hop */ - width: 100%; } diff --git a/tests/outputs_numbered/compass_extract.css b/tests/outputs_numbered/compass_extract.css deleted file mode 100644 index 2c6002d8..00000000 --- a/tests/outputs_numbered/compass_extract.css +++ /dev/null @@ -1,29 +0,0 @@ -/* line 224, inputs/compass_extract.scss */ -#test-0 { - unit: false; - unit: true; - rhythm: 1.5em; - size: 1; - size: 1; - size: 1; - size: 2; - size: 2; } -/* line 236, inputs/compass_extract.scss */ -#test-1 { - margin-top: 7.5em; - padding-top: 9em; - padding-bottom: 10.5em; - margin-bottom: 0em; } -/* line 240, inputs/compass_extract.scss */ -#test-2 { - border-style: solid; - border-width: 0.0625em; - padding: 1.4375em; } -/* line 244, inputs/compass_extract.scss */ -#test-3 { - border-top-style: solid; - border-top-width: 0.0625em; - padding-top: 1.4375em; - border-bottom-style: solid; - border-bottom-width: 0.0625em; - padding-bottom: 1.4375em; } diff --git a/tests/outputs_numbered/content.css b/tests/outputs_numbered/content.css deleted file mode 100644 index c01a1085..00000000 --- a/tests/outputs_numbered/content.css +++ /dev/null @@ -1,53 +0,0 @@ -/* line 3, inputs/content.scss */ -/* line 8, inputs/content.scss */ - * html #logo { - background-image: url(/logo.gif); } -/* line 20, inputs/content.scss */ -.colors { - background-color: blue; - color: white; - border-color: blue; } - -@media only screen and (max-width: 480px) { -/* line 26, inputs/content.scss */ -/* line 32, inputs/content.scss */ - body { - color: red; } } -/* line 36, inputs/content.scss */ -#sidebar { - width: 300px; } - @media only screen and (max-width: 480px) { - #sidebar { - width: 100px; } } - -@media only screen and (min-width: 40em) { -/* line 46, inputs/content.scss */ -/* line 51, inputs/content.scss */ - .grid-1 { - width: 100%; } -/* line 51, inputs/content.scss */ -.grid-2 { - width: 100%; } } - -@media only screen and (min-width: 40em) { - /* line 58, inputs/content.scss */ - .grid-1 { - width: 100%; } -/* line 58, inputs/content.scss */ -.grid-2 { - width: 100%; } } -/* line 70, inputs/content.scss */ -/* line 64, inputs/content.scss */ - /* line 78, inputs/content.scss */ - * html * body #logo { - background-image: url(/logo.gif); } -/* line 91, inputs/content.scss */ -A { - top: 10px; } -/* line 114, inputs/content.scss */ -.test { - display: none; } -/* line 123, inputs/content.scss */ -.test_empty_content { - display: inline; - font-weight: bold; } diff --git a/tests/outputs_numbered/content_with_function.css b/tests/outputs_numbered/content_with_function.css deleted file mode 100644 index 864ff558..00000000 --- a/tests/outputs_numbered/content_with_function.css +++ /dev/null @@ -1,3 +0,0 @@ -/* line 13, inputs/content_with_function.scss */ -body { - padding: 1 px; } diff --git a/tests/outputs_numbered/default_args.css b/tests/outputs_numbered/default_args.css deleted file mode 100644 index 3ac81e14..00000000 --- a/tests/outputs_numbered/default_args.css +++ /dev/null @@ -1,4 +0,0 @@ -/* line 11, inputs/default_args.scss */ -div { - height: red; - margin: 100px; } diff --git a/tests/outputs_numbered/directives.css b/tests/outputs_numbered/directives.css deleted file mode 100644 index 4c17a831..00000000 --- a/tests/outputs_numbered/directives.css +++ /dev/null @@ -1,141 +0,0 @@ -@charset "hello-world"; -@page :left { -/* line 3, inputs/directives.scss */ -div { - color: red; } } - -@page test { - @media yes { -/* line 12, inputs/directives.scss */ -div { - color: red; } } } - -@media something { - @page { - @media else { -/* line 29, inputs/directives.scss */ -div { - height: 200px; } } } } -/* line 37, inputs/directives.scss */ -div { - color: red; } - @page yeah { -/* line 40, inputs/directives.scss */ -div pre { -height: 20px; } } - -@font-face { - color: red; - height: 20px; } - -@keyframes 'bounce' { -/* line 53, inputs/directives.scss */ -from { - top: 100px; - animation-timing-function: ease-out; } -/* line 58, inputs/directives.scss */ -25% { - top: 50px; - animation-timing-function: ease-in; } -/* line 63, inputs/directives.scss */ -50% { - top: 100px; - animation-timing-function: ease-out; } -/* line 68, inputs/directives.scss */ -75% { - top: 75px; - animation-timing-function: ease-in; } -/* line 73, inputs/directives.scss */ -to { - top: 100px; } } - -@-webkit-keyframes flowouttoleft { -/* line 79, inputs/directives.scss */ -0% { - -webkit-transform: translateX(0) scale(1); } -/* line 80, inputs/directives.scss */ -60%, 70% { - -webkit-transform: translateX(0) scale(0.7); } -/* line 81, inputs/directives.scss */ -100% { - -webkit-transform: translateX(-100%) scale(0.7); } } -/* line 84, inputs/directives.scss */ -div { - animation-name: 'diagonal-slide'; - animation-duration: 5s; - animation-iteration-count: 10; } - -@keyframes 'diagonal-slide' { -/* line 92, inputs/directives.scss */ -from { - left: 0; - top: 0; } -/* line 97, inputs/directives.scss */ -to { - left: 100px; - top: 100px; } } - -@document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), - domain(mozilla.org), - regexp("https:.*") { -/* line 109, inputs/directives.scss */ -body { - color: purple; - background: yellow; } } - -@keyframes anim-rotate { -/* line 113, inputs/directives.scss */ -0% { - transform: rotate(0); } -/* line 116, inputs/directives.scss */ -100% { - transform: rotate(360deg); } } -/* line 121, inputs/directives.scss */ -.bold, .icon-ajax { - font-weight: 700; } -/* line 125, inputs/directives.scss */ -/* line 129, inputs/directives.scss */ - -/* line 131, inputs/directives.scss */ - .custom-selector { - color: blue; } - -@-webkit-keyframes zoomer { -/* line 136, inputs/directives.scss */ -from { - transform: scale(0.5); } -/* line 140, inputs/directives.scss */ -to { - transform: scale(1); } } - -@keyframes zoomer { -/* line 146, inputs/directives.scss */ -from { - transform: scale(0.5); } -/* line 150, inputs/directives.scss */ -to { - transform: scale(1); } } -/* line 157, inputs/directives.scss */ -@supports (position: sticky) { -/* line 159, inputs/directives.scss */ -.sticky-top .top2 { - position: sticky; } } -/* line 164, inputs/directives.scss */ -@supports (position: sticky) { - .sticky-top { - position: sticky; - top: 0; } } - -@supports (position: sticky) { -/* line 172, inputs/directives.scss */ -.sticky-top2 { - position: sticky; } } - -@media print { -/* line 178, inputs/directives.scss */ -/* line 179, inputs/directives.scss */ - .table-bordered th, .table-bordered td { - border: 1px solid #ddd !important; } } - @font-face { - font-family: "Glyphicons Halflings"; } diff --git a/tests/outputs_numbered/extending_compound_selector.css b/tests/outputs_numbered/extending_compound_selector.css deleted file mode 100644 index 5be74586..00000000 --- a/tests/outputs_numbered/extending_compound_selector.css +++ /dev/null @@ -1,27 +0,0 @@ -/* line 1, inputs/extending_compound_selector.scss */ -/* line 2, inputs/extending_compound_selector.scss */ - .foo:after, .bar:after, .bar:before, .baz.bar:before { - color: red; } -/* line 5, inputs/extending_compound_selector.scss */ -.foo:hover:after, .bar:hover:after, .bar:before:hover, .baz.bar:before:hover { - color: blue; } -/* line 10, inputs/extending_compound_selector.scss */ -/* line 12, inputs/extending_compound_selector.scss */ - -/* line 17, inputs/extending_compound_selector.scss */ - -/* line 21, inputs/extending_compound_selector.scss */ - -a, a:link, a:visited, a:active, a:hover { - color: #fff; } -/* line 25, inputs/extending_compound_selector.scss */ -/* line 29, inputs/extending_compound_selector.scss */ - -/* line 33, inputs/extending_compound_selector.scss */ - -/* line 37, inputs/extending_compound_selector.scss */ - -/* line 41, inputs/extending_compound_selector.scss */ - -.nest a.some-class, .nest a:link.some-class, .nest a:visited.some-class, .nest a:active.some-class, .nest a:hover.some-class { - color: #ccc; } diff --git a/tests/outputs_numbered/extends.css b/tests/outputs_numbered/extends.css deleted file mode 100644 index eeffb9c7..00000000 --- a/tests/outputs_numbered/extends.css +++ /dev/null @@ -1,286 +0,0 @@ -/* line 2, inputs/extends.scss */ -error, pre seriousError, span seriousError, other, hello { - border: 1px #f00; - background-color: #fdd; } -/* line 7, inputs/extends.scss */ -/* line 8, inputs/extends.scss */ - pre seriousError, span seriousError { - font-size: 20px; } -/* line 14, inputs/extends.scss */ -hello { - color: green; } -/* line 17, inputs/extends.scss */ -hello div { - margin: 10px; } -/* line 22, inputs/extends.scss */ -.cool, .me { - color: red; } -/* line 26, inputs/extends.scss */ -.blue, .me { - color: purple; } -/* line 30, inputs/extends.scss */ -/* line 34, inputs/extends.scss */ - -/* line 35, inputs/extends.scss */ - -a:hover, .hoverlink, #demo .overview .fakelink:hover { - text-decoration: underline; } -/* line 40, inputs/extends.scss */ -div.hello.world.hmm, pre div.okay.span.world.hmm, pre #butt .umm div.sure.span.world.hmm, #butt .umm pre div.sure.span.world.hmm, code div.okay.span.world.hmm, code #butt .umm div.sure.span.world.hmm, #butt .umm code div.sure.span.world.hmm { - color: blue; } -/* line 44, inputs/extends.scss */ -/* line 45, inputs/extends.scss */ - -/* line 51, inputs/extends.scss */ - -.xxxxx .xxxxx .xxxxx, code .xxxxx .xxxxx, code code .xxxxx, code code code, code .xxxxx code, .xxxxx code .xxxxx, .xxxxx code code, .xxxxx .xxxxx code { - color: green; } -/* line 55, inputs/extends.scss */ -code { - color: red; } -/* line 63, inputs/extends.scss */ -.alpha, .beta, .gama { - color: red; } -/* line 67, inputs/extends.scss */ -.beta, .gama { - color: white; } -/* line 72, inputs/extends.scss */ -.gama { - color: blue; } -/* line 79, inputs/extends.scss */ -#admin .tabbar a, #admin .tabbar #demo .overview .fakelink, #demo .overview #admin .tabbar .fakelink { - font-weight: bold; } -/* line 80, inputs/extends.scss */ -/* line 82, inputs/extends.scss */ - -a1 b1 c1 d1, x1 y1 z1 w1 b1 c1 d1 { - color: red; } -/* line 83, inputs/extends.scss */ -/* line 85, inputs/extends.scss */ - -a2 b2 c2 d2, a2 x2 y2 z2 w2 c2 d2, x2 y2 z2 a2 w2 c2 d2 { - color: red; } -/* line 86, inputs/extends.scss */ -/* line 89, inputs/extends.scss */ - -a3 b3 c3 d3, a3 b3 x3 y3 z3 w3 d3, x3 y3 z3 a3 b3 w3 d3 { - color: red; } -/* line 90, inputs/extends.scss */ -/* line 93, inputs/extends.scss */ - -a4 b4 c4 d4, a4 b4 c4 x4 y4 z4 w4, x4 y4 z4 a4 b4 c4 w4 { - color: red; } -/* line 94, inputs/extends.scss */ -/* line 98, inputs/extends.scss */ - -#butt .yeah .okay, #butt .yeah .umm .sure, #butt .umm .yeah .sure { - font-weight: bold; } -/* line 99, inputs/extends.scss */ -/* line 101, inputs/extends.scss */ - -a9 b9 s9 t9 v9, a9 b9 s9 t9 x9 y9 z9, a9 b9 x9 y9 s9 t9 z9 { - color: red; } -/* line 103, inputs/extends.scss */ -@media print { -/* line 110, inputs/extends.scss */ -horse, man { - color: blue; } } -/* line 115, inputs/extends.scss */ -man { - color: red; } -/* line 123, inputs/extends.scss */ -wassup { - color: blue; } -/* line 128, inputs/extends.scss */ -/* line 129, inputs/extends.scss */ - -.foo .wassup { - color: blue; } -/* line 137, inputs/extends.scss */ -#something, .x, .y { - color: red; } -/* line 141, inputs/extends.scss */ -/* line 145, inputs/extends.scss */ - -/* line 151, inputs/extends.scss */ - -/* line 152, inputs/extends.scss */ - -/* line 156, inputs/extends.scss */ - -.nav-justified, .nav-tabs.nav-justified { - text-align: justify; } -/* line 162, inputs/extends.scss */ -.btn:hover, .edit .actions button:hover, .edit .new .actions button:hover, .btn:active, .edit .actions button:active, .edit .new .actions button:active, .btn.active, .edit .actions button.active, .edit .new .actions button.active, .btn.disabled, .edit .actions button.disabled, .edit .new .actions button.disabled, .btn[disabled], .edit .actions button[disabled], .edit .new .actions button[disabled] { - color: red; } -/* line 169, inputs/extends.scss */ -/* line 170, inputs/extends.scss */ - -.edit .actions button { - float: right; } -/* line 175, inputs/extends.scss */ -/* line 176, inputs/extends.scss */ - -/* line 177, inputs/extends.scss */ - .edit .new .actions { - padding: 0; } -/* line 180, inputs/extends.scss */ -/* line 186, inputs/extends.scss */ - -.z, .parent .self.z { - color: red; } -/* line 187, inputs/extends.scss */ -/* line 191, inputs/extends.scss */ - -/* line 193, inputs/extends.scss */ - -#content .social-login { - display: block; - float: right; - margin-right: 15px; - width: 250px; } -/* line 199, inputs/extends.scss */ -#content .social-login .facebook, #content .social-login .twitter { - display: block; - width: 255px; - height: 42px; - background: transparent url('images/login-btns.png') no-repeat; - background-position: 0 0; } -/* line 206, inputs/extends.scss */ -#content .social-login .facebook:hover, #content .social-login .twitter:hover { - background-position: 0 -43px; } -/* line 210, inputs/extends.scss */ -#content .social-login .facebook:focus, #content .social-login .twitter:focus, #content .social-login .facebook:active, #content .social-login .twitter:active { - background-position: 0 -86px; } -/* line 215, inputs/extends.scss */ -#content .social-login .twitter { - background-position: 0 -129px; } -/* line 220, inputs/extends.scss */ -#content .social-login .twitter:hover { - background-position: 0 -172px; } -/* line 224, inputs/extends.scss */ -#content .social-login .twitter:active, #content .social-login .twitter:focus { - background-position: 0 -215px; } -/* line 232, inputs/extends.scss */ -/* line 233, inputs/extends.scss */ - -body .to-extend, body .test { - color: red; } -/* line 236, inputs/extends.scss */ -/* line 241, inputs/extends.scss */ - -/* line 242, inputs/extends.scss */ - -.navbar .navbar-brand, .navbar .navbar-brand:hover { - font-weight: bold; - text-shadow: none; - color: #fff; } -/* line 247, inputs/extends.scss */ -/* line 253, inputs/extends.scss */ - -/* line 254, inputs/extends.scss */ - -.foo__bar#test, input { - background: red; } -/* line 256, inputs/extends.scss */ -/* line 258, inputs/extends.scss */ - -.selector1, .master-class { - color: blue; } -/* line 262, inputs/extends.scss */ -.selector2, .master-class { - background: #ccc; } -/* line 268, inputs/extends.scss */ -/* line 274, inputs/extends.scss */ - -/* line 275, inputs/extends.scss */ - -.main .block__element, .main .block__element--modifier { - font-size: 14px; } -/* line 278, inputs/extends.scss */ -.main .block__element--modifier { - font-weight: bold; } -/* line 285, inputs/extends.scss */ -/* line 291, inputs/extends.scss */ - -.pagination-bullet { - width: 6px; - height: 6px; - margin-left: 5px; } -/* line 295, inputs/extends.scss */ -.pagination-bullet:first-child { - margin-left: 0; } -/* line 298, inputs/extends.scss */ -.pagination-bullet.is-active { - background-color: white; } -/* line 303, inputs/extends.scss */ -/* line 304, inputs/extends.scss */ - -/* line 315, inputs/extends.scss */ - -/* line 310, inputs/extends.scss */ - -/* line 317, inputs/extends.scss */ - -.parent-nested-foo-include .in-nested-foo .child-nested-foo-include, .parent-nested-foo-include .in-nested-foo .beard + .mustache { - color: green; } -/* line 323, inputs/extends.scss */ -/* line 328, inputs/extends.scss */ - -/* line 331, inputs/extends.scss */ - -.btn-group > .btn-lg, .btn-group-lg.btn-group > .btn, .edit .actions .btn-group-lg.btn-group > button, .edit .new .actions .btn-group-lg.btn-group > button { - padding-right: 12px; - padding-left: 12px; } -/* line 337, inputs/extends.scss */ -.fp-content-center form + div { - padding-left: 0; } -/* line 341, inputs/extends.scss */ -/* line 342, inputs/extends.scss */ - -.form-inline + .a .form-group > b, .form-inline + .a .fp-content-center form + div > b, .fp-content-center .form-inline + .a form + div > b { - margin-bottom: 0; } -/* line 348, inputs/extends.scss */ -canvas, object, embed.bar { - color: yellow; } -/* line 351, inputs/extends.scss */ -.popup, input, img.bar, .prepend input.foo, .prepend div.foo { - color: red; } -/* line 354, inputs/extends.scss */ -div.popup, .prepend div.foo { - color: blue; } -/* line 357, inputs/extends.scss */ -.before span.popup .after { - color: green; } -/* line 360, inputs/extends.scss */ -/* line 363, inputs/extends.scss */ - -/* line 366, inputs/extends.scss */ - -/* line 369, inputs/extends.scss */ - -/* line 372, inputs/extends.scss */ - -/* line 373, inputs/extends.scss */ - -/* line 379, inputs/extends.scss */ - -.class1:not(:last-child), .class2:not(.foo):not(:last-child), .class3:not(:last-child) { - color: red; } -/* line 383, inputs/extends.scss */ -/* line 387, inputs/extends.scss */ - -/* line 391, inputs/extends.scss */ - -.inline-menu:hover > .sub-menu, .header-menu:hover > .sub-menu { - border-radius: 5px; } -/* line 394, inputs/extends.scss */ -/* line 395, inputs/extends.scss */ - -/* line 400, inputs/extends.scss */ - -/* line 405, inputs/extends.scss */ - -.myclass { - color: red; } -/* line 408, inputs/extends.scss */ diff --git a/tests/outputs_numbered/extends_nesting.css b/tests/outputs_numbered/extends_nesting.css deleted file mode 100644 index 54f503e6..00000000 --- a/tests/outputs_numbered/extends_nesting.css +++ /dev/null @@ -1,47 +0,0 @@ -/* line 1, inputs/extends_nesting.scss */ -.btn, .extend .the-button { - padding: 1px; } -/* line 4, inputs/extends_nesting.scss */ -.btn-lg, .btn-group-lg > .btn, .extend .btn-group-lg > .the-button { - font-size: 10px; } -/* line 7, inputs/extends_nesting.scss */ -.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret, .dropup .extend .btn-group-lg > .the-button .caret, .extend .dropup .btn-group-lg > .the-button .caret { - border-width: 100px; } -/* line 11, inputs/extends_nesting.scss */ -.dropup .btn, .dropup .extend .the-button, .extend .dropup .the-button { - content: "dropup btn"; } -/* line 13, inputs/extends_nesting.scss */ -.dropup .btn .caret, .dropup .extend .the-button .caret, .extend .dropup .the-button .caret { - content: "dropup btn caret"; } -/* line 17, inputs/extends_nesting.scss */ -.dropup > .btn, .extend .dropup > .the-button { - content: "dropup > btn"; } -/* line 19, inputs/extends_nesting.scss */ -.dropup > .btn > .caret, .extend .dropup > .the-button > .caret { - content: "dropup > btn > caret"; } -/* line 23, inputs/extends_nesting.scss */ -.dropup + .btn, .extend .dropup + .the-button { - content: "dropup + btn"; } -/* line 25, inputs/extends_nesting.scss */ -.dropup + .btn + .caret, .extend .dropup + .the-button + .caret { - content: "dropup + btn + caret"; } -/* line 29, inputs/extends_nesting.scss */ -.dropup.btn, .extend .the-button.dropup { - content: "dropupbtn"; } -/* line 31, inputs/extends_nesting.scss */ -.dropup.btn.caret, .extend .the-button.dropup.caret { - content: "dropupbtncaret"; } -/* line 36, inputs/extends_nesting.scss */ -/* line 40, inputs/extends_nesting.scss */ - -/* line 41, inputs/extends_nesting.scss */ - -/* line 47, inputs/extends_nesting.scss */ - -.nav-bar, header ul { - background: #eee; } -/* line 49, inputs/extends_nesting.scss */ -.nav-bar > .item, header ul > .item, header ul > li, header ul.nav-bar > li { - margin: 0 10px; } -/* line 54, inputs/extends_nesting.scss */ -/* line 56, inputs/extends_nesting.scss */ diff --git a/tests/outputs_numbered/filter_effects.css b/tests/outputs_numbered/filter_effects.css deleted file mode 100644 index d40dbcd5..00000000 --- a/tests/outputs_numbered/filter_effects.css +++ /dev/null @@ -1,21 +0,0 @@ -/* line 1, inputs/filter_effects.scss */ -#number { - -webkit-filter: grayscale(1) sepia(0.5) saturate(0.1) invert(1) opacity(0.5) brightness(0.5) contrast(0.5); } -/* line 11, inputs/filter_effects.scss */ -#percentage { - -webkit-filter: grayscale(100%) sepia(50%) saturate(10%) invert(100%) opacity(50%) brightness(50%) contrast(50%); } -/* line 21, inputs/filter_effects.scss */ -#misc { - -webkit-filter: hue-rotate(90deg) blur(10px) drop-shadow(10px -16px 30px purple); } -/* line 37, inputs/filter_effects.scss */ -#decimal { - opacity: 0.5; - filter: alpha(opacity=50, style=1); } -/* line 41, inputs/filter_effects.scss */ -#percent { - opacity: 0.5; - filter: alpha(opacity=50); } -/* line 45, inputs/filter_effects.scss */ -.row { - background-color: #071c23; - color: #2284a1; } diff --git a/tests/outputs_numbered/functions.css b/tests/outputs_numbered/functions.css deleted file mode 100644 index 6841fa05..00000000 --- a/tests/outputs_numbered/functions.css +++ /dev/null @@ -1,56 +0,0 @@ -/* line 10, inputs/functions.scss */ -div { - color: 14px; - sum: 23; } -/* line 33, inputs/functions.scss */ -div { - hello: 10 55; - hello: 1010 55; - hello: "hello 10 and 55"; } -/* line 44, inputs/functions.scss */ -del { - color: 1000; } -/* line 48, inputs/functions.scss */ -div { - hello: "hello foo and bar"; - hello: "hello bar and default"; - hello: "hello Alice, Bob, Tom"; } -/* line 61, inputs/functions.scss */ -.foo { - test2: -moz-art; } -/* line 77, inputs/functions.scss */ -/* line 67, inputs/functions.scss */ - div span { - height: 3px; } -/* line 87, inputs/functions.scss */ -div { - width: 2; } -/* line 95, inputs/functions.scss */ -p { - color: arglist; } -/* line 112, inputs/functions.scss */ -.test { - display: 'global'; - display: 'test-mixin'; - display: 'test-mixin'; - display: 'global'; } -/* line 118, inputs/functions.scss */ -.test-inspect { - n: null; - b1: true; - b2: false; - n1: 0; - s1: ''; - s2: 'hello'; - l1: 1 2; - l2: 3 4; - l3: 5, 6; - l4: (a: 1, b: 2); - l5: (a: 1, b: 2); } -/* line 165, inputs/functions.scss */ -div { - margin: 1px 1px 2px 2px; - padding: 1px 1px 2px 2px; } -/* line 173, inputs/functions.scss */ -.test { - color: rgba(159, 159, 159, 0.625); } diff --git a/tests/outputs_numbered/ie7.css b/tests/outputs_numbered/ie7.css deleted file mode 100644 index 3935c7d3..00000000 --- a/tests/outputs_numbered/ie7.css +++ /dev/null @@ -1,9 +0,0 @@ -/* line 2, inputs/ie7.scss */ -#foo:before { - content: counter(item,".") ": "; } -/* line 6, inputs/ie7.scss */ -#bar:before { - content: counter(item,"."); } -/* line 10, inputs/ie7.scss */ -#fu:before { - content: counter(item); } diff --git a/tests/outputs_numbered/if.css b/tests/outputs_numbered/if.css deleted file mode 100644 index 154326a2..00000000 --- a/tests/outputs_numbered/if.css +++ /dev/null @@ -1,22 +0,0 @@ -/* line 10, inputs/if.scss */ -div { - color: blue; } -/* line 16, inputs/if.scss */ -pre { - val-1: "red"; - val-2: "blue"; - val-3: "blue"; - val-4: "red"; - val-5: "red"; } -/* line 25, inputs/if.scss */ -span { - color: blue; - height: 10px; - width: 20px; } -/* line 47, inputs/if.scss */ -div { - color: blue; - border-color: green; } -/* line 67, inputs/if.scss */ -del { - thing: no; } diff --git a/tests/outputs_numbered/if_on_null.css b/tests/outputs_numbered/if_on_null.css deleted file mode 100644 index 268bcae6..00000000 --- a/tests/outputs_numbered/if_on_null.css +++ /dev/null @@ -1,3 +0,0 @@ -/* line 6, inputs/if_on_null.scss */ -body { - background-color: "red"; } diff --git a/tests/outputs_numbered/import.css b/tests/outputs_numbered/import.css deleted file mode 100644 index 8bfe1380..00000000 --- a/tests/outputs_numbered/import.css +++ /dev/null @@ -1,32 +0,0 @@ -@import "foo.css"; -@import "foo" screen; -@import "http://foo.com/bar"; -@import url(foo); -/* line 1, inputs/imports/simple.scss */ -div { - height: 200px; - color: red; } -/* line 9, inputs/import.scss */ -pre { - color: red; } -/* line 1, inputs/imports/simple.scss */ -pre div { - height: 200px; - color: red; } -/* line 14, inputs/import.scss */ -/* line 1, inputs/imports/simple.scss */ - -code div { - height: 200px; - color: red; } -/* line 1, inputs/imports/simple.scss */ -code div { - height: 200px; - color: red; } -/* line 2, inputs/imports/_partial.scss */ -#partial { - color: blue; } -/* line 20, inputs/import.scss */ -body { - color: #7c2; - background: gray; } diff --git a/tests/outputs_numbered/interpolation.css b/tests/outputs_numbered/interpolation.css deleted file mode 100644 index 256dde01..00000000 --- a/tests/outputs_numbered/interpolation.css +++ /dev/null @@ -1,103 +0,0 @@ -/* line 2, inputs/interpolation.scss */ -div { - color: redwhite blue; - color: red white blue; - color: red whiteblue; - color: redwhiteblue; - color: ummyeahwhat; - color: stacked; - font-size: 10px/something; - font-size: 10px / something; - test: "whatworldwrong"; - test: "whatworldwrong"; - test: "whatworldwrong"; - test: "what"world"wrong"; - hi: "what is 16 end"; } -/* line 24, inputs/interpolation.scss */ -/* line 27, inputs/interpolation.scss */ - pre var { - color: red; } -/* line 31, inputs/interpolation.scss */ -pre var dad { - color: red; } -/* line 35, inputs/interpolation.scss */ -pre bedvardad { - color: red; } -/* line 40, inputs/interpolation.scss */ -/* line 42, inputs/interpolation.scss */ - -cool .thing-1 { - color: red; } -/* line 42, inputs/interpolation.scss */ -cool .thing-2 { - color: red; } -/* line 42, inputs/interpolation.scss */ -cool .thing-3 { - color: red; } -/* line 42, inputs/interpolation.scss */ -cool .thing-4 { - color: red; } -/* line 42, inputs/interpolation.scss */ -cool .thing-5 { - color: red; } -/* line 48, inputs/interpolation.scss */ -abcde { - color: red; } -/* line 52, inputs/interpolation.scss */ -#hello, .world { - color: red; } -/* line 56, inputs/interpolation.scss */ -#abchelloyeah, .coolworldyes { - color: red; } -/* line 62, inputs/interpolation.scss */ -div.element:nth-child(2n) { - display: none; } -/* line 69, inputs/interpolation.scss */ -div { - hello: world; - coolhello: world; - helloone: world; - twohelloone: world; - oneabtwo: cool; - hello-world: red; - hello-mold: white; - hello-hello: blue; } -/* line 86, inputs/interpolation.scss */ -body { - color: 3; } -/* line 91, inputs/interpolation.scss */ -foo, x, y { - color: #abc; } -/* line 97, inputs/interpolation.scss */ -div { - prop: a, b; } -/* line 101, inputs/interpolation.scss */ -/* line 102, inputs/interpolation.scss */ - -a.badge { - text-decoration: none; } -/* line 119, inputs/interpolation.scss */ -.btn-primary { - background: yellow; } -/* line 110, inputs/interpolation.scss */ -.btn-primary:not(.disabled) { - border-color: red; } -/* line 113, inputs/interpolation.scss */ -.btn-primary:not(.disabled):focus { - border-width: 3px; } -/* line 133, inputs/interpolation.scss */ -/* line 124, inputs/interpolation.scss */ - -/* line 125, inputs/interpolation.scss */ - -/* line 126, inputs/interpolation.scss */ - .pagination .page-item:first-child .page-link { - border-radius: 5px; } -/* line 140, inputs/interpolation.scss */ -.element { - border: 2px solid #000; } -/* line 149, inputs/interpolation.scss */ -/* line 150, inputs/interpolation.scss */ - -div > p > strong, div > h1 > strong { - color: red; } diff --git a/tests/outputs_numbered/keyword_args.css b/tests/outputs_numbered/keyword_args.css deleted file mode 100644 index 5a6d7463..00000000 --- a/tests/outputs_numbered/keyword_args.css +++ /dev/null @@ -1,7 +0,0 @@ -/* line 8, inputs/keyword_args.scss */ -pre { - out: alpha fort three palace; } -/* line 19, inputs/keyword_args.scss */ -div { - hello: 5; - world: -5; } diff --git a/tests/outputs_numbered/list.css b/tests/outputs_numbered/list.css deleted file mode 100644 index 6fa2ea80..00000000 --- a/tests/outputs_numbered/list.css +++ /dev/null @@ -1,26 +0,0 @@ -/* line 4, inputs/list.scss */ -div { - padding: 10px 20px 30px 40px; - margin: 0 10px 10px 10px; - background: linear-gradient(black, white); } -/* line 13, inputs/list.scss */ -p { - background: linear-gradient(red, blue); } -/* line 20, inputs/list.scss */ -.bracket-list { - background: linear-gradient(red, blue); } -/* line 24, inputs/list.scss */ -div { - x: 2; - z: 2; } -/* line 31, inputs/list.scss */ -div { - a: 10px; - b: -20px; - c: 30px; - d: 30px; } -/* line 38, inputs/list.scss */ -div { - x: space; - y: comma; - z: space; } diff --git a/tests/outputs_numbered/looping.css b/tests/outputs_numbered/looping.css deleted file mode 100644 index 3ca7273c..00000000 --- a/tests/outputs_numbered/looping.css +++ /dev/null @@ -1,89 +0,0 @@ -/* line 2, inputs/looping.scss */ -div { - color: what; - color: is; - color: this; - font: what; - font: is; - font: this; - background: what; - background: is; - background: this; - border: what; - border: is; - border: this; - background: what what; - background: is is; - background: this this; - background: what what; - background: is is; - background: this this; - color: red; } -/* line 32, inputs/looping.scss */ -div h1 { - font-size: 2em; } -/* line 32, inputs/looping.scss */ -div h2 { - font-size: 1.5em; } -/* line 32, inputs/looping.scss */ -div h3 { - font-size: 1.2em; } -/* line 42, inputs/looping.scss */ -span { - color: 0; - color: 1; - color: 2; - color: 3; - color: 4; - color: 5; - color: 6; - color: 7; - color: 8; - color: 9; - color: 10; } -/* line 50, inputs/looping.scss */ -pre { - color: 1; - color: 2; - color: 3; - color: 4; - height: 1; - height: 2; - height: 3; - height: 4; - height: 5; - cool: 10; - cool: 9; - cool: 8; - cool: 7; - cool: 6; - cool: 5; - cool: 4; - cool: 3; } -/* line 85, inputs/looping.scss */ -div { - a: false; - b: true; - c: true; - c: true; } -/* line 92, inputs/looping.scss */ -body.each { - color: 1; - background-color: 2; - color: 3; - background-color: 4; - color: 5; } -/* line 112, inputs/looping.scss */ -body.for { - color: 1; - background-color: 2; - color: 3; - background-color: 4; - color: 5; } -/* line 132, inputs/looping.scss */ -body.while { - color: 1; - background-color: 2; - color: 3; - background-color: 4; - color: 5; } diff --git a/tests/outputs_numbered/map.css b/tests/outputs_numbered/map.css deleted file mode 100644 index 23c144fb..00000000 --- a/tests/outputs_numbered/map.css +++ /dev/null @@ -1,28 +0,0 @@ -/* line 11, inputs/map.scss */ -div { - color: black; - color: red; - foo: black, red, #0f0; - bar: color, length; - baz: (color: #fff, color2: red, 'color3': #0f0, length: 40em); - foo: (length: 40em); - bar: true; } -/* line 23, inputs/map.scss */ -div { - foo: color black; - bar: color; } -/* line 32, inputs/map.scss */ -.black { - background-color: #000 !important; } -/* line 32, inputs/map.scss */ -.grey { - background-color: #888 !important; } -/* line 32, inputs/map.scss */ -.white { - background-color: #fff !important; } -/* line 53, inputs/map.scss */ -div { - a: 1; - b: 2; - color: 1; - background-color: 2; } diff --git a/tests/outputs_numbered/media.css b/tests/outputs_numbered/media.css deleted file mode 100644 index 09a2b053..00000000 --- a/tests/outputs_numbered/media.css +++ /dev/null @@ -1,166 +0,0 @@ -@media { -/* line 4, inputs/media.scss */ -div { - color: blue; } } - -@media what { -/* line 7, inputs/media.scss */ -div { - color: blue; } } - -@media (cool) { -/* line 11, inputs/media.scss */ -div { - color: blue; } } - -@media (cool: blue) { -/* line 14, inputs/media.scss */ -div { - color: blue; } } - -@media hello and (world) and (butt: man) { -/* line 18, inputs/media.scss */ -div { - color: blue; } } - -@media (max-width: 940px) { -/* line 23, inputs/media.scss */ -color: red; } - -@media not hello and (world) { -/* line 28, inputs/media.scss */ -color: blue; -/* line 30, inputs/media.scss */ -pre { - color: blue; } } - @media not hello and (world) { - @media butt { -/* line 34, inputs/media.scss */ -color: red; -/* line 36, inputs/media.scss */ -div { -color: red; } } } - -@media c { -/* line 61, inputs/media.scss */ -color: blue; } -/* line 70, inputs/media.scss */ -div { - color: blue; } - @media screen and (-webkit-min-device-pixel-ratio: 1.5) { -/* line 73, inputs/media.scss */ -div .sidebar { -width: 500px; } } -/* line 87, inputs/media.scss */ -div { - position: absolute; } - @media screen { -/* line 90, inputs/media.scss */ -div { -top: 0; -bottom: 8em; -color: red; } -/* line 93, inputs/media.scss */ -div p { -margin: 5px; } -/* line 82, inputs/media.scss */ -div .success { -color: green; } } -/* line 101, inputs/media.scss */ -.button { - width: 300px; - height: 100px; - background: #eee; } -/* line 106, inputs/media.scss */ -.button :hover { - background: #aaa; } - -@media only screen and (max-width: 300px) { -/* line 110, inputs/media.scss */ -.button { - width: 100px; - height: 100px; } } -/* line 116, inputs/media.scss */ -code { - position: absolute; } - -@media screen { -/* line 118, inputs/media.scss */ -code { - height: 10px; } -/* line 119, inputs/media.scss */ -code pre { - height: 20px; } } -/* line 126, inputs/media.scss */ -@media screen and (color: blue) { -/* line 128, inputs/media.scss */ -dt { - height: 10px; } } - -@media screen { -/* line 136, inputs/media.scss */ -.screen { - width: 12px; } } - -@media only screen { -/* line 140, inputs/media.scss */ -.only-screen { - height: 11px; } } - -@media only screen { -/* line 147, inputs/media.scss */ -.only-screen { - width: 14px; } } - -@media only screen { -/* line 151, inputs/media.scss */ -.only-screen { - height: 16px; } } - -@media print { -/* line 167, inputs/media.scss */ -.only-print { - height: 12px; } } - -@media screen { -/* line 175, inputs/media.scss */ -.only-print { - height: 12px; } } - -@media not screen { -/* line 191, inputs/media.scss */ -.not-screen { - height: 15px; } } - -@media only screen and (color: blue) and (width: 13) { -/* line 208, inputs/media.scss */ -.only-screen { - height: 15px; } } - -@media screen and (max-width: 749px) and (max-width: 600px) and (min-width: 361px) { -/* line 217, inputs/media.scss */ -.item { - color: red; } } -/* line 223, inputs/media.scss */ - - @media not all and (max-width: 450px) { - @media not all and (max-width: 690px) and (orientation: portrait) { - @media (max-width: 1000px) { -/* line 226, inputs/media.scss */ -a { -color: red; } } } } -/* line 233, inputs/media.scss */ - - @media not all and (max-width: 450px) { - @media (max-width: 690px) and (orientation: portrait) and (max-width: 1000px) { -/* line 236, inputs/media.scss */ -a { -color: red; } } } -/* line 243, inputs/media.scss */ - - @media (max-width: 450px) { - @media not all and (max-width: 690px) and (orientation: portrait) { - @media not all and (max-width: 1000px) { -/* line 246, inputs/media.scss */ -a { -color: red; } } } } diff --git a/tests/outputs_numbered/mixins.css b/tests/outputs_numbered/mixins.css deleted file mode 100644 index b9f67f52..00000000 --- a/tests/outputs_numbered/mixins.css +++ /dev/null @@ -1,119 +0,0 @@ -/* line 9, inputs/mixins.scss */ -div { - color: blue; - color: red; } -/* line 4, inputs/mixins.scss */ -div pre { - height: 200px; } -/* line 26, inputs/mixins.scss */ -span { - color: blue; } -/* line 17, inputs/mixins.scss */ -span div { - height: 20px; } -/* line 30, inputs/mixins.scss */ -html { - height: 43px; } -/* line 39, inputs/mixins.scss */ -del { - height: 20px; } -/* line 52, inputs/mixins.scss */ -div { - color: white; - color: blue; - color: white; } -/* line 62, inputs/mixins.scss */ -div { - background-image: linear-gradient(left top, red, green); } -/* line 72, inputs/mixins.scss */ -div { - -moz-box-shadow: 10px 10px 5px #888; - -webkit-box-shadow: 10px 10px 5px #888; - box-shadow: 10px 10px 5px #888; - -moz-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; - -webkit-box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; - box-shadow: inset 10px 10px #888, -10px -10px #f4f4f4; } -/* line 81, inputs/mixins.scss */ -/* line 82, inputs/mixins.scss */ - -div p { - color: red; - color: blue; } -/* line 83, inputs/mixins.scss */ -div p .class { - color: red; } -/* line 17, inputs/mixins.scss */ -div p .class div { - height: 20px; } -/* line 17, inputs/mixins.scss */ -div p div { - height: 20px; } -/* line 89, inputs/mixins.scss */ -div p .top { - top: 0; } -/* line 92, inputs/mixins.scss */ -div p .top div { - color: red; } -/* line 103, inputs/mixins.scss */ -div.mixin-content-simple { - color: red; } -/* line 109, inputs/mixins.scss */ -div.mixin-content-with-arg { - background: blue; - color: red; } -/* line 109, inputs/mixins.scss */ -div.mixin-content-with-arg { - background: purple; - height: 20px; } -/* line 103, inputs/mixins.scss */ -div.mixin-content-simple { - height: 43px; } -/* line 103, inputs/mixins.scss */ -div.mixin-content-simple { - color: orange; } -/* line 17, inputs/mixins.scss */ -div.mixin-content-simple div { - height: 20px; } -/* line 109, inputs/mixins.scss */ -div.mixin-content-with-arg { - background: purple; - height: 43px; } -/* line 109, inputs/mixins.scss */ -div.mixin-content-with-arg { - background: purple; - color: orange; } -/* line 17, inputs/mixins.scss */ -div.mixin-content-with-arg div { - height: 20px; } -/* line 156, inputs/mixins.scss */ -#please-wait { - background: url(/images/logo.png); - position: absolute; - top: 1em; - right: 0; - bottom: 3em; - left: 4em; } -/* line 168, inputs/mixins.scss */ -div.parameter-name-scope { - -webkit-transform: translateX(50px); } - -@-webkit-keyframes change-color { -/* line 181, inputs/mixins.scss */ -0% { - color: green; } -/* line 182, inputs/mixins.scss */ -100% { - color: red; } } -/* line 190, inputs/mixins.scss */ -@media screen and (min-width:0\0) { -/* line 186, inputs/mixins.scss */ -.test { - color: #000; } } -/* line 197, inputs/mixins.scss */ -div { - content: "div"; - content: "div"; } -/* line 197, inputs/mixins.scss */ -div p { - content: "p"; - content: "p"; } diff --git a/tests/outputs_numbered/nested_mixins.css b/tests/outputs_numbered/nested_mixins.css deleted file mode 100644 index 880ee491..00000000 --- a/tests/outputs_numbered/nested_mixins.css +++ /dev/null @@ -1,26 +0,0 @@ -/* line 13, inputs/nested_mixins.scss */ -/* line 2, inputs/nested_mixins.scss */ - div .container { - width: 10px; } -/* line 2, inputs/nested_mixins.scss */ -div .container .container { - width: 10px; - max-width: 12px; } -/* line 21, inputs/nested_mixins.scss */ -div .container .foo { - width: 10px; } -/* line 24, inputs/nested_mixins.scss */ -div .container .bar { - width: 12px; } - -@media print, screen and (min-width:640px) { -/* line 33, inputs/nested_mixins.scss */ -/* line 43, inputs/nested_mixins.scss */ - .position-left { - color: red; - background: yellow; } } - -@media print, screen and (min-width:640px) { -/* line 45, inputs/nested_mixins.scss */ -.element { - float: left; } } diff --git a/tests/outputs_numbered/nesting.css b/tests/outputs_numbered/nesting.css deleted file mode 100644 index 4400af51..00000000 --- a/tests/outputs_numbered/nesting.css +++ /dev/null @@ -1,24 +0,0 @@ -div: blue; -/* line 3, inputs/nesting.scss */ -body { - color: red; } -/* line 8, inputs/nesting.scss */ -div { - color: red; - height: yes; } -/* line 12, inputs/nesting.scss */ -div pre { - color: blue; } -/* line 21, inputs/nesting.scss */ -div { - font: 10px hello world; - font-size: 10px; - font-color: blue; - border-left: 1px solid blue; - border-right: 2px dashed green; } -/* line 34, inputs/nesting.scss */ -#nested-nesting { - bar: baz; - bang-bop: bar; - bang-bip: 1px; - bang-blat-baf: bort; } diff --git a/tests/outputs_numbered/null.css b/tests/outputs_numbered/null.css deleted file mode 100644 index 90e4bf62..00000000 --- a/tests/outputs_numbered/null.css +++ /dev/null @@ -1,22 +0,0 @@ -/* line 2, inputs/null.scss */ -.div { - one: null; - one: world; - one: NULL world; - one: a, b; - two: a, b; } -/* line 12, inputs/null.scss */ -p:before { - content: "I ate pies!"; } -/* line 31, inputs/null.scss */ -.foo { - -webkit-border-radius: 10; - border-radius: 10; } -/* line 35, inputs/null.scss */ -.fu { - -webkit-border-radius: 20; - border-radius: 20; } -/* line 39, inputs/null.scss */ -.bar { - -webkit-border-top-left-radius: 30; - border-top-left-radius: 30; } diff --git a/tests/outputs_numbered/operators.css b/tests/outputs_numbered/operators.css deleted file mode 100644 index 9a956a2c..00000000 --- a/tests/outputs_numbered/operators.css +++ /dev/null @@ -1,186 +0,0 @@ -/* line 3, inputs/operators.scss */ -body { - color: 8; - color: 16; - height: 10px/10px; - color: 6px; - color: 5px; - top: 1.5em; - left: -1cm; - top: 6.2992125984; } -/* line 15, inputs/operators.scss */ -div { - color: false; - color: true; - color: true; - color: false; - color: what > 3; - color: 0; - color: -1; - color: 1; } -/* line 29, inputs/operators.scss */ -#units { - test: 2.5748031496in; - test: 13mm; - test: 4em; - test: 11mm; - test: 1.1cm; } -/* line 37, inputs/operators.scss */ -#modulo { - test: 1; - test: 1cm; } -/* line 42, inputs/operators.scss */ -#colors { - color: #ff0203; - color: #fe0000; - color: rgba(3, 8, 15, 0.5); - color: rgba(5, 7, 10, 0.5); - color: rgba(2, 4, 6, 0.5); - color: rgba(0, 1, 1, 0.5); - color: rgba(3, 4, 5, 0.5); - color: rgba(0, 0, 1, 0.5); - color: #22f; - color: false; - color: true; - color: true; - color: false; } -/* line 63, inputs/operators.scss */ -#preserve { - hello: what -going; - hello: what - going; } -/* line 68, inputs/operators.scss */ -#strings { - hello: what -going; - hello: whatgoing; - hello: whatgoing; - hello: whatgoing; - hello: whatgoing; - hello: "whatgoing"; - hello: goingwhat; - hello: "whatwhat"; } -/* line 81, inputs/operators.scss */ -#negation { - a: -60; - b: -90; - b: -90; } -/* line 88, inputs/operators.scss */ -#bools-fail { - and: false and two; - and: one and two; - and: one and false; - or: false or two; - or: one or two; - or: one or false; } -/* line 98, inputs/operators.scss */ -#bools { - and: false; - and: two; - and: false; - or: two; - or: one; - or: one; - or: two; } -/* line 111, inputs/operators.scss */ -#nots-fail { - not: false2; - not: not false; - not: not 0; - not: not 1; - not: not ""; - not: not hello; } -/* line 120, inputs/operators.scss */ -#nots { - not: false2; - not: true; - not: false; - not: false; - not: false; - not: false; - not: true; } -/* line 130, inputs/operators.scss */ -#string-test { - str: true; - str: false; - str: true; - str: true; - str: xhellohellofalse; - str: true; } -/* line 146, inputs/operators.scss */ -#special { - cancel-unit: 1; } -/* line 153, inputs/operators.scss */ -.row .a { - margin: -0.5em; } -/* line 154, inputs/operators.scss */ -.row .b { - margin: -0.5em; } -/* line 155, inputs/operators.scss */ -.row .c { - margin: -0.5em; } -/* line 156, inputs/operators.scss */ -.row .d { - margin: -0.5em; } -/* line 157, inputs/operators.scss */ -.row .e { - margin: 0 -0.5em; } -/* line 159, inputs/operators.scss */ -.alt .a { - margin: -0.5em; } -/* line 160, inputs/operators.scss */ -.alt .b { - margin: -0.5em; } -/* line 161, inputs/operators.scss */ -.alt .c { - margin: -0.5em; } -/* line 162, inputs/operators.scss */ -.alt .d { - margin: 0 -0.5em; } -/* line 163, inputs/operators.scss */ -.alt .e { - margin: 0 -0.5em; } -/* line 165, inputs/operators.scss */ -.row .f { - margin: -2em; } -/* line 166, inputs/operators.scss */ -.row .g { - margin: -2em; } -/* line 167, inputs/operators.scss */ -.row .h { - margin: -2em; } -/* line 168, inputs/operators.scss */ -.row .i { - margin: -2em; } -/* line 169, inputs/operators.scss */ -.row .j { - margin: 0 -2em; } -/* line 171, inputs/operators.scss */ -.alt .f { - margin: -2em; } -/* line 172, inputs/operators.scss */ -.alt .g { - margin: -2em; } -/* line 173, inputs/operators.scss */ -.alt .h { - margin: -2em; } -/* line 174, inputs/operators.scss */ -.alt .i { - margin: 0 -2em; } -/* line 175, inputs/operators.scss */ -.alt .j { - margin: 0 -2em; } -/* line 184, inputs/operators.scss */ -div { - *margin-left: 2.0744680851%; } -/* line 190, inputs/operators.scss */ -.foo { - width: 12.5%; } -/* line 212, inputs/operators.scss */ -#bools-test { - a: false; - b: true; - f: false; - n: true; - o: true; - p: false; - r: one; - s: one; } diff --git a/tests/outputs_numbered/parsing_comments.css b/tests/outputs_numbered/parsing_comments.css deleted file mode 100644 index 5e0ec76a..00000000 --- a/tests/outputs_numbered/parsing_comments.css +++ /dev/null @@ -1,55 +0,0 @@ -/* comment 1 */ -/* line 2, inputs/parsing_comments.scss */ -a { - /* comment 2 */ - color: red; - /* comment 3 */ - /* comment 4 */ } -/* comment 5 */ -/*! comment 1 */ -/* line 10, inputs/parsing_comments.scss */ -b { - /*! comment 2 */ - color: red; - /*! comment 3 */ - /*! comment 4 */ } -/*! comment 5 */ -/* - * multi-line comment 1 - */ -/* line 20, inputs/parsing_comments.scss */ -c { - /* - * multi-line comment 2 - */ - color: red; - /* - * multi-line comment 3 - */ - /* - * multi-line comment 4 - */ } -/* - * multi-line comment 5 - */ -/*! - * multi-line comment 1 - */ -/* line 38, inputs/parsing_comments.scss */ -d { - /*! - * multi-line comment 2 - */ - color: red; - /*! - * multi-line comment 3 - */ - /*! - * multi-line comment 4 - */ } -/*! - * multi-line comment 5 - */ -/* line 54, inputs/parsing_comments.scss */ -e { - color: red; } diff --git a/tests/outputs_numbered/placeholder_selector.css b/tests/outputs_numbered/placeholder_selector.css deleted file mode 100644 index 3eb4a6ea..00000000 --- a/tests/outputs_numbered/placeholder_selector.css +++ /dev/null @@ -1,16 +0,0 @@ -/* line 1, inputs/placeholder_selector.scss */ -p a.notice span, p a.error span, #context a.notice span, #context a.error span { - color: blue; - font-weight: bold; - font-size: 2em; } -/* line 7, inputs/placeholder_selector.scss */ -/* line 9, inputs/placeholder_selector.scss */ -/* line 13, inputs/placeholder_selector.scss */ -p { - padding: 2em; } -/* line 18, inputs/placeholder_selector.scss */ -/* line 22, inputs/placeholder_selector.scss */ - -.layout { - color: red; } -/* line 26, inputs/placeholder_selector.scss */ diff --git a/tests/outputs_numbered/scss_css.css b/tests/outputs_numbered/scss_css.css deleted file mode 100644 index dd19dda4..00000000 --- a/tests/outputs_numbered/scss_css.css +++ /dev/null @@ -1,797 +0,0 @@ -@charset "UTF-8"; -@import "foo.css"; -@import 'foo.css'; -@import url("foo.css"); -@import url('foo.css'); -@import url(foo.css); -@import "foo.css" screen; -@import "foo.css" screen, print; -@import "foo.css" screen, print and (foo: 0); -@import "foo.css" screen, only print, screen and (foo: 0); -/* line 1, inputs/scss_css.scss */ -[foo~=bar] { - a: b; } -/* line 5, inputs/scss_css.scss */ -[foo^=bar] { - a: b; } -/* line 9, inputs/scss_css.scss */ -[foo$=bar] { - a: b; } -/* line 13, inputs/scss_css.scss */ -[foo*=bar] { - a: b; } -/* line 17, inputs/scss_css.scss */ -[foo|=en] { - a: b; } -/* line 21, inputs/scss_css.scss */ -foo { - a: 2; - b: 2.3em; - c: 50%; - d: "fraz bran"; - e: flanny-blanny-blan; - f: url(http://sass-lang.com); - h: #abc; } -/* line 32, inputs/scss_css.scss */ -selector { - property: value; - property2: value; } -/* line 37, inputs/scss_css.scss */ -sel { - p: v; } -/* line 39, inputs/scss_css.scss */ -.foo { - /* Foo - Bar - Baz */ - a: b; } -/* line 46, inputs/scss_css.scss */ -.foo { - /* Foo - Bar - Baz */ - a: b; } -/* line 53, inputs/scss_css.scss */ -.foo { - /* Foo - Bar */ - a: b; } -/* line 58, inputs/scss_css.scss */ -.foo { - /* Foo - Bar - Baz */ - a: b; } - -@foo { - a: b; -/* line 65, inputs/scss_css.scss */ -rule { - a: b; } } - -@foo { - a: b; } - -@bar { - a: b; } - -@foo "bar" - -foo { - a: 12px calc(100%/3 - 2*1em - 2*1px); - b: 12px -moz-calc(100%/3 - 2*1em - 2*1px); - b: 12px -webkit-calc(100%/3 - 2*1em - 2*1px); - b: 12px -foobar-calc(100%/3 - 2*1em - 2*1px); } -/* line 84, inputs/scss_css.scss */ -foo { - bar: baz; } -/* line 86, inputs/scss_css.scss */ -bar { - bar: baz; } -/* line 88, inputs/scss_css.scss */ -baz { - bar: baz; } -/* - * foo - */ -/* line 94, inputs/scss_css.scss */ -bar { - baz: bang; } -/* line 97, inputs/scss_css.scss */ -E, F { - a: b; } -/* line 101, inputs/scss_css.scss */ -E F, G H { - a: b; } -/* line 105, inputs/scss_css.scss */ -E > F, G > H { - a: b; } -/* This is a CSS comment. */ -/* line 110, inputs/scss_css.scss */ -.one { - color: green; } -/* Another comment */ -/* The following should not be used: - .two {color: red;} */ -/* line 113, inputs/scss_css.scss */ -.three { - color: green; - /* color: red; */ } -/** - .four {color: red;} */ -/* line 116, inputs/scss_css.scss */ -.five { - color: green; } -/**/ -/* line 118, inputs/scss_css.scss */ -.six { - color: green; } -/*********/ -/* line 120, inputs/scss_css.scss */ -.seven { - color: green; } -/* a comment **/ -/* line 122, inputs/scss_css.scss */ -.eight { - color: green; } -/* line 125, inputs/scss_css.scss */ -foo { - a: \foo bar; - b: foo\ bar; - c: \2022 \0020; - d: foo\\bar; - e: foo\"\'bar; } -/* line 133, inputs/scss_css.scss */ -foo { - a: "\foo bar"; - b: "foo\ bar"; - c: "\2022 \0020"; - d: "foo\\bar"; - e: "foo\"'bar"; } -/* line 141, inputs/scss_css.scss */ -foo { - _name: val; - *name: val; - :name: val; - .name: val; - #name: val; - name/**/: val; - name/*\**/: val; - name: val; } - -@foo "bar" ; - -foo { - a: -moz-element(#foo); - b: -webkit-element(#foo); - b: -foobar-element(#foo); } - -@foo ; - -foo { - bar: baz; } - -/* line 179, inputs/scss_css.scss */ - -0% { - a: b; } -/* line 183, inputs/scss_css.scss */ -60% { - a: b; } -/* line 187, inputs/scss_css.scss */ -100% { - a: b; } -/* line 191, inputs/scss_css.scss */ -12px { - a: b; } -/* line 195, inputs/scss_css.scss */ -foo { - a: b; } -/* line 199, inputs/scss_css.scss */ -foo { - a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); } -/* line 203, inputs/scss_css.scss */ -:foo("bar") { - a: b; } -/* line 207, inputs/scss_css.scss */ -:foo(bar) { - a: b; } -/* line 211, inputs/scss_css.scss */ -:foo(12px) { - a: b; } -/* line 215, inputs/scss_css.scss */ -:foo(+) { - a: b; } -/* line 219, inputs/scss_css.scss */ -:foo(-) { - a: b; } -/* line 223, inputs/scss_css.scss */ -:foo(+"bar") { - a: b; } -/* line 227, inputs/scss_css.scss */ -:foo(-++--baz-"bar"12px) { - a: b; } -/* line 231, inputs/scss_css.scss */ -foo { - a: foo-bar(12); - b: -foo-bar-baz(13, 14 15); } -/* line 254, inputs/scss_css.scss */ -foo { - a: foo !important; - b: foo bar !important; - b: foo, bar !important; } -/* line 260, inputs/scss_css.scss */ -foo { - a: -moz-bar-baz; - b: foo -o-bar-baz; } -/* line 265, inputs/scss_css.scss */ -foo { - a: d; - /* b; c: */ } -/* line 268, inputs/scss_css.scss */ -foo { - a: d; - /*: b; c */ } -/* Foo - * Bar */ -/* line 275, inputs/scss_css.scss */ -.foo { - /* Foo - * Bar */ } -/* line 280, inputs/scss_css.scss */ -[foo] { - a: b; } -/* line 284, inputs/scss_css.scss */ -[foo="bar"] { - a: b; } -/* line 288, inputs/scss_css.scss */ -[foo~="bar"] { - a: b; } -/* line 292, inputs/scss_css.scss */ -[foo^="bar"] { - a: b; } -/* line 296, inputs/scss_css.scss */ -[foo$="bar"] { - a: b; } -/* line 300, inputs/scss_css.scss */ -[foo*="bar"] { - a: b; } -/* line 304, inputs/scss_css.scss */ -[foo|="en"] { - a: b; } -/* line 308, inputs/scss_css.scss */ -:root { - a: b; } -/* line 312, inputs/scss_css.scss */ -:nth-child(n) { - a: b; } -/* line 316, inputs/scss_css.scss */ -:nth-last-child(n) { - a: b; } -/* line 320, inputs/scss_css.scss */ -:nth-of-type(n) { - a: b; } -/* line 324, inputs/scss_css.scss */ -:nth-last-of-type(n) { - a: b; } -/* line 328, inputs/scss_css.scss */ -:first-child { - a: b; } -/* line 332, inputs/scss_css.scss */ -:last-child { - a: b; } -/* line 336, inputs/scss_css.scss */ -:first-of-type { - a: b; } -/* line 340, inputs/scss_css.scss */ -:last-of-type { - a: b; } -/* line 344, inputs/scss_css.scss */ -:only-child { - a: b; } -/* line 348, inputs/scss_css.scss */ -:only-of-type { - a: b; } -/* line 352, inputs/scss_css.scss */ -:empty { - a: b; } -/* line 356, inputs/scss_css.scss */ -:link { - a: b; } -/* line 360, inputs/scss_css.scss */ -:visited { - a: b; } -/* line 364, inputs/scss_css.scss */ -:active { - a: b; } -/* line 368, inputs/scss_css.scss */ -:hover { - a: b; } -/* line 372, inputs/scss_css.scss */ -:focus { - a: b; } -/* line 376, inputs/scss_css.scss */ -:target { - a: b; } -/* line 380, inputs/scss_css.scss */ -:lang(fr) { - a: b; } -/* line 384, inputs/scss_css.scss */ -:enabled { - a: b; } -/* line 388, inputs/scss_css.scss */ -:disabled { - a: b; } -/* line 392, inputs/scss_css.scss */ -:checked { - a: b; } -/* line 396, inputs/scss_css.scss */ -::first-line { - a: b; } -/* line 400, inputs/scss_css.scss */ -::first-letter { - a: b; } -/* line 404, inputs/scss_css.scss */ -::before { - a: b; } -/* line 408, inputs/scss_css.scss */ -::after { - a: b; } -/* line 412, inputs/scss_css.scss */ -.warning { - a: b; } -/* line 416, inputs/scss_css.scss */ -#myid { - a: b; } -/* line 420, inputs/scss_css.scss */ -:not(s) { - a: b; } - -@media all { -/* line 425, inputs/scss_css.scss */ -rule1 { - prop: val; } -/* line 428, inputs/scss_css.scss */ -rule2 { - prop: val; } } - -@media screen, print { -/* line 433, inputs/scss_css.scss */ -rule1 { - prop: val; } -/* line 436, inputs/scss_css.scss */ -rule2 { - prop: val; } } - -@media screen and (-webkit-min-device-pixel-ratio: 0) { -/* line 440, inputs/scss_css.scss */ -a: b; } - -@media only screen, print and (foo: 0px) and (bar: flam(12px solid)) { -/* line 444, inputs/scss_css.scss */ -a: b; } -/* line 448, inputs/scss_css.scss */ -:-moz-any(h1, h2, h3) { - a: b; } -/* line 452, inputs/scss_css.scss */ -:-moz-any(.foo) { - a: b; } -/* line 456, inputs/scss_css.scss */ -:-moz-any(foo bar, .baz > .bang) { - a: b; } - -@-moz-document url(http://www.w3.org/), - url-prefix(http://www.w3.org/Style/), - domain(mozilla.org), - regexp("^https:.*") { -/* line 464, inputs/scss_css.scss */ -.foo { - a: b; } } -/* line 468, inputs/scss_css.scss */ -foo { - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); - filter: progid:DXImageTransform.Microsoft.gradient(GradientType=1, startColorstr=#c0ff3300, endColorstr=#ff000000); } -/* line 473, inputs/scss_css.scss */ -foo { - filter: alpha(opacity=20); - filter: alpha(opacity=20, enabled=true); - filter: blaznicate(foo=bar, baz=bang bip, bart=#fa4600); } - -@foo bar { - a: b; } - -@bar baz { - c: d; } - -@foo bar; -@bar baz; - - -/* Foo - * Bar */ -/* Baz - * Bang */ - - -.foo { - /* Foo - * Bar */ - /* Baz - * Bang */ } -/* line 503, inputs/scss_css.scss */ -.foo { - /* Foo Bar */ - /* Baz Bang */ } - -@namespace "http://www.w3.org/Profiles/xhtml1-strict"; - -@namespace url(http://www.w3.org/Profiles/xhtml1-strict); - -@namespace html url("http://www.w3.org/Profiles/xhtml1-strict"); - -[foo|bar=baz] { - a: b; } -/* line 517, inputs/scss_css.scss */ -[*|bar=baz] { - a: b; } -/* line 521, inputs/scss_css.scss */ -[foo|bar|=baz] { - a: b; } -/* line 525, inputs/scss_css.scss */ -foo|E { - a: b; } -/* line 529, inputs/scss_css.scss */ -*|E { - a: b; } -/* line 533, inputs/scss_css.scss */ -foo|* { - a: b; } -/* line 537, inputs/scss_css.scss */ -*|* { - a: b; } -/* line 541, inputs/scss_css.scss */ -:not(foo|bar) { - a: b; } -/* line 545, inputs/scss_css.scss */ -:not(*|bar) { - a: b; } -/* line 549, inputs/scss_css.scss */ -:not(foo|*) { - a: b; } -/* line 553, inputs/scss_css.scss */ -:not(*|*) { - a: b; } -/* line 557, inputs/scss_css.scss */ -:not(#blah) { - a: b; } -/* line 561, inputs/scss_css.scss */ -:not(.blah) { - a: b; } -/* line 565, inputs/scss_css.scss */ -:not([foo]) { - a: b; } -/* line 569, inputs/scss_css.scss */ -:not([foo^="bar"]) { - a: b; } -/* line 573, inputs/scss_css.scss */ -:not([baz|foo~="bar"]) { - a: b; } -/* line 577, inputs/scss_css.scss */ -:not(:hover) { - a: b; } -/* line 581, inputs/scss_css.scss */ -:not(:nth-child(2n + 3)) { - a: b; } -/* line 585, inputs/scss_css.scss */ -:not(:not(#foo)) { - a: b; } -/* line 589, inputs/scss_css.scss */ -:not(a#foo.bar) { - a: b; } -/* line 593, inputs/scss_css.scss */ -:not(#foo .bar > baz) { - a: b; } -/* line 597, inputs/scss_css.scss */ -:not(h1, h2, h3) { - a: b; } -/* line 605, inputs/scss_css.scss */ -foo { - a: "bang 1 bar bip"; } -/* line 609, inputs/scss_css.scss */ -:nth-child(-n) { - a: b; } -/* line 613, inputs/scss_css.scss */ -:nth-child(+n) { - a: b; } -/* line 617, inputs/scss_css.scss */ -:nth-child(even) { - a: b; } -/* line 621, inputs/scss_css.scss */ -:nth-child(odd) { - a: b; } -/* line 625, inputs/scss_css.scss */ -:nth-child(50) { - a: b; } -/* line 629, inputs/scss_css.scss */ -:nth-child(-50) { - a: b; } -/* line 633, inputs/scss_css.scss */ -:nth-child(+50) { - a: b; } -/* line 637, inputs/scss_css.scss */ -:nth-child(2n+3) { - a: b; } -/* line 641, inputs/scss_css.scss */ -:nth-child(2n-3) { - a: b; } -/* line 645, inputs/scss_css.scss */ -:nth-child(+2n-3) { - a: b; } -/* line 649, inputs/scss_css.scss */ -:nth-child(-2n+3) { - a: b; } -/* line 653, inputs/scss_css.scss */ -:nth-child(-2n+ 3) { - a: b; } -/* line 657, inputs/scss_css.scss */ -:nth-child( 2n + 3) { - a: b; } -/* line 661, inputs/scss_css.scss */ -foo { - a: foo bar baz; - b: foo, #abc, -12; - c: 1px/2px/-3px; - d: foo bar, baz/bang; } - -@page { - prop1: val; - prop2: val; } - -@page flap { - prop1: val; - prop2: val; } - -@page :first { - prop1: val; - prop2: val; } - -@page flap:first { - prop1: val; - prop2: val; } -/* line 688, inputs/scss_css.scss */ -.foo { - /* Foo */ - a: b; } -/* line 693, inputs/scss_css.scss */ -.foo { - /* Foo - * Bar */ - a: b; } -/* Foo */ -/* line 699, inputs/scss_css.scss */ -.foo { - a: b; } -/* Foo - * Bar */ -/* line 704, inputs/scss_css.scss */ -.foo { - a: b; } -/* line 708, inputs/scss_css.scss */ -.foo #bar:baz(/* bang )*/ bip) { - /* .a #foo */ - a: b; } -/* line 712, inputs/scss_css.scss */ -> E { - a: b; } -/* line 716, inputs/scss_css.scss */ -+ E { - a: b; } -/* line 720, inputs/scss_css.scss */ -~ E { - a: b; } -/* line 724, inputs/scss_css.scss */ -> > E { - a: b; } -/* line 728, inputs/scss_css.scss */ ->> E { - a: b; } -/* line 732, inputs/scss_css.scss */ -E* { - a: b; } -/* line 736, inputs/scss_css.scss */ -E*.foo { - a: b; } -/* line 740, inputs/scss_css.scss */ -E*:hover { - a: b; } -/* line 744, inputs/scss_css.scss */ -E, F { - a: b; } -/* line 749, inputs/scss_css.scss */ -E F { - a: b; } -/* line 754, inputs/scss_css.scss */ -E, F G, H { - a: b; } -/* line 759, inputs/scss_css.scss */ -body { - /* - //comment here - */ } -/* line 766, inputs/scss_css.scss */ -E > F { - a: b; } -/* line 768, inputs/scss_css.scss */ -E ~ F { - a: b; } -/* line 770, inputs/scss_css.scss */ -E + F { - a: b; } -/* line 772, inputs/scss_css.scss */ -* { - a: b; } -/* line 776, inputs/scss_css.scss */ -E { - a: b; } -/* line 780, inputs/scss_css.scss */ -E[foo] { - a: b; } -/* line 784, inputs/scss_css.scss */ -E[foo="bar"] { - a: b; } -/* line 788, inputs/scss_css.scss */ -E[foo~="bar"] { - a: b; } -/* line 792, inputs/scss_css.scss */ -E[foo^="bar"] { - a: b; } -/* line 796, inputs/scss_css.scss */ -E[foo$="bar"] { - a: b; } -/* line 800, inputs/scss_css.scss */ -E[foo*="bar"] { - a: b; } -/* line 804, inputs/scss_css.scss */ -E[foo|="en"] { - a: b; } -/* line 808, inputs/scss_css.scss */ -E:root { - a: b; } -/* line 812, inputs/scss_css.scss */ -E:nth-child(n) { - a: b; } -/* line 816, inputs/scss_css.scss */ -E:nth-last-child(n) { - a: b; } -/* line 820, inputs/scss_css.scss */ -E:nth-of-type(n) { - a: b; } -/* line 824, inputs/scss_css.scss */ -E:nth-last-of-type(n) { - a: b; } -/* line 828, inputs/scss_css.scss */ -E:first-child { - a: b; } -/* line 832, inputs/scss_css.scss */ -E:last-child { - a: b; } -/* line 836, inputs/scss_css.scss */ -E:first-of-type { - a: b; } -/* line 840, inputs/scss_css.scss */ -E:last-of-type { - a: b; } -/* line 844, inputs/scss_css.scss */ -E:only-child { - a: b; } -/* line 848, inputs/scss_css.scss */ -E:only-of-type { - a: b; } -/* line 852, inputs/scss_css.scss */ -E:empty { - a: b; } -/* line 856, inputs/scss_css.scss */ -E:link { - a: b; } -/* line 860, inputs/scss_css.scss */ -E:visited { - a: b; } -/* line 864, inputs/scss_css.scss */ -E:active { - a: b; } -/* line 868, inputs/scss_css.scss */ -E:hover { - a: b; } -/* line 872, inputs/scss_css.scss */ -E:focus { - a: b; } -/* line 876, inputs/scss_css.scss */ -E:target { - a: b; } -/* line 880, inputs/scss_css.scss */ -E:lang(fr) { - a: b; } -/* line 884, inputs/scss_css.scss */ -E:enabled { - a: b; } -/* line 888, inputs/scss_css.scss */ -E:disabled { - a: b; } -/* line 892, inputs/scss_css.scss */ -E:checked { - a: b; } -/* line 896, inputs/scss_css.scss */ -E::first-line { - a: b; } -/* line 900, inputs/scss_css.scss */ -E::first-letter { - a: b; } -/* line 904, inputs/scss_css.scss */ -E::before { - a: b; } -/* line 908, inputs/scss_css.scss */ -E::after { - a: b; } -/* line 912, inputs/scss_css.scss */ -E.warning { - a: b; } -/* line 916, inputs/scss_css.scss */ -E#myid { - a: b; } -/* line 920, inputs/scss_css.scss */ -E:not(s) { - a: b; } -/* line 924, inputs/scss_css.scss */ -E F { - a: b; } -/* line 928, inputs/scss_css.scss */ -E > F { - a: b; } -/* line 932, inputs/scss_css.scss */ -E + F { - a: b; } -/* line 936, inputs/scss_css.scss */ -E ~ F { - a: b; } - -@supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) { -/* line 941, inputs/scss_css.scss */ -.foo { - a: b; } } - -@-prefix-supports (a: b) and (c: d) or (not (d: e)) and ((not (f: g)) or (not ((h: i) and (j: k)))) { -/* line 948, inputs/scss_css.scss */ -.foo { - a: b; } } -/* line 954, inputs/scss_css.scss */ -foo { - foo: bar; - #baz: bang; - #bip: bop; } -/* line 960, inputs/scss_css.scss */ -foo { - a: -2; - b: -2.3em; - c: -50%; - d: -foo(bar baz); } -/* line 967, inputs/scss_css.scss */ -foo { - a: -0.5em; - b: 0.5em; - c: -foo(12px); - d: +foo(12px); } -/* line 977, inputs/scss_css.scss */ -foo { - -moz-foo-bar: blat; - -o-flat-blang: wibble; } -/* line 981, inputs/scss_css.scss */ -foo { - a: foo(); - b: bar baz-bang() bip; } -/* line 985, inputs/scss_css.scss */ -.alpha { - color: rgba(31, 37, 38, 0.749); - background-color: #1f2526; } -/* line 991, inputs/scss_css.scss */ -.shortcode-4c29f540779d8549daf934275faea11 { - color: red; } diff --git a/tests/outputs_numbered/selector_functions.css b/tests/outputs_numbered/selector_functions.css deleted file mode 100644 index c036813c..00000000 --- a/tests/outputs_numbered/selector_functions.css +++ /dev/null @@ -1,129 +0,0 @@ -/* line 1, inputs/selector_functions.scss */ -.foo, .bar, .foo2 .bar2, .foo3 > .bar3 { - content: ".foo"; - content: ".bar"; - content: ".foo2 .bar2"; - content: ".foo3 > .bar3"; } -/* line 8, inputs/selector_functions.scss */ -.main aside:hover, .sidebar p { - content: ".main aside:hover"; - content: ".sidebar p"; } -/* line 15, inputs/selector_functions.scss */ -.is-superselector { - content: false; - /* false */ } -/* line 18, inputs/selector_functions.scss */ -.is-superselector1 { - content: true; - /*true*/ } -/* line 21, inputs/selector_functions.scss */ -.is-superselector2 { - content: true; - /*true*/ } -/* line 25, inputs/selector_functions.scss */ -.is-superselector3 { - content: true; - /*true*/ } -/* line 29, inputs/selector_functions.scss */ -.is-superselector4 { - content: false; - /*false*/ } -/* line 33, inputs/selector_functions.scss */ -.is-superselector5 { - content: true; - /* true*/ } -/* line 37, inputs/selector_functions.scss */ -.is-superselector6 { - content: false; - /* false*/ } -/* line 41, inputs/selector_functions.scss */ -.is-superselector7 { - content: true; - /* true*/ } -/* line 44, inputs/selector_functions.scss */ -.is-superselector8 { - content: false; - /* false*/ } -/* line 47, inputs/selector_functions.scss */ -.is-superselector9 { - content: true; - /* true*/ } -/* line 51, inputs/selector_functions.scss */ -a.disabled { - content: 'a.disabled'; } -/* line 55, inputs/selector_functions.scss */ -.accordion__copy { - content: '.accordion__copy'; } -/* line 59, inputs/selector_functions.scss */ -.accordion__copy, .accordion__image { - content: '.accordion__copy, .accordion__image'; } -/* line 63, inputs/selector_functions.scss */ -.accordion__copy, .slider__copy, .accordion__image, .slider__image { - content: '.accordion__copy, .slider__copy, .accordion__image, .slider__image'; } -/* line 67, inputs/selector_functions.scss */ -a.disabled, .link.disabled { - content: "a.disabled, .link.disabled"; } -/* line 70, inputs/selector_functions.scss */ -a.disabled { - content: "a.disabled"; } -/* line 74, inputs/selector_functions.scss */ -.guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar { - content: ".guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar"; } -/* line 78, inputs/selector_functions.scss */ -ul li { - content: "ul li"; } -/* line 82, inputs/selector_functions.scss */ -.alert p, .warning p { - content: ".alert p, .warning p"; } -/* line 86, inputs/selector_functions.scss */ -.alert:hover { - content: ".alert:hover"; } -/* line 90, inputs/selector_functions.scss */ -.accordion__copy { - content: ".accordion__copy"; } -/* line 95, inputs/selector_functions.scss */ -.main aside:hover { - content: ".main"; - content: "aside:hover"; } -/* line 95, inputs/selector_functions.scss */ -.sidebar p { - content: ".sidebar"; - content: "p"; } -/* line 102, inputs/selector_functions.scss */ -.link.disabled { - content: ".link.disabled"; } -/* line 105, inputs/selector_functions.scss */ -a.disabled { - content: "a.disabled"; } -/* line 109, inputs/selector_functions.scss */ -.guide .content nav.sidebar, .content .guide nav.sidebar { - content: ".guide .content nav.sidebar, .content .guide nav.sidebar"; } -/* line 113, inputs/selector_functions.scss */ -a, .disabled { - /* a, .disabled */ - content: "a"; - content: ".disabled"; } -/* line 119, inputs/selector_functions.scss */ -main, .blog, :after { - /* main, .blog, :after */ - content: "main"; - content: ".blog"; - content: ":after"; } -/* line 126, inputs/selector_functions.scss */ -a.disabled { - content: "a.disabled"; } -/* line 130, inputs/selector_functions.scss */ -a.disabled.outgoing { - content: "a.disabled.outgoing"; } -/* line 134, inputs/selector_functions.scss */ - { - content: "null"; } -/* line 138, inputs/selector_functions.scss */ -.warning main a, main .warning a { - content: ".warning main a, main .warning a"; } -/* line 142, inputs/selector_functions.scss */ -main.warning a.disabled { - content: "main.warning a.disabled"; } -/* line 146, inputs/selector_functions.scss */ -main .warning a { - content: "main .warning a"; } diff --git a/tests/outputs_numbered/selectors.css b/tests/outputs_numbered/selectors.css deleted file mode 100644 index 7b6a8571..00000000 --- a/tests/outputs_numbered/selectors.css +++ /dev/null @@ -1,416 +0,0 @@ -/* line 1, inputs/selectors.scss */ -* { - color: blue; } -/* line 2, inputs/selectors.scss */ -E { - color: blue; } -/* line 4, inputs/selectors.scss */ -E:not(:link) { - color: blue; } -/* line 5, inputs/selectors.scss */ -E:not(:link):not(:visited) { - color: blue; } -/* line 6, inputs/selectors.scss */ -E:not(:link, :visited) { - color: blue; } -/* line 7, inputs/selectors.scss */ -E:matches(:hover, :focus) { - color: blue; } -/* line 9, inputs/selectors.scss */ -E.warning { - color: blue; } -/* line 10, inputs/selectors.scss */ -E#id { - color: blue; } -/* line 11, inputs/selectors.scss */ -E[foo] { - color: blue; } -/* line 12, inputs/selectors.scss */ -E[foo="barbar"] { - color: blue; } -/* line 13, inputs/selectors.scss */ -E[foo="barbar" i] { - color: blue; } -/* line 14, inputs/selectors.scss */ -E[foo~="hello#$@%@$#^"] { - color: blue; } -/* line 15, inputs/selectors.scss */ -E[foo^="color: green;"] { - color: blue; } -/* line 16, inputs/selectors.scss */ -E[foo$="239023"] { - color: blue; } -/* line 17, inputs/selectors.scss */ -E[foo*="29302"] { - color: blue; } -/* line 18, inputs/selectors.scss */ -E[foo|="239032"] { - color: blue; } -/* line 20, inputs/selectors.scss */ -[foo] { - color: blue; } -/* line 21, inputs/selectors.scss */ -[foo] .helloWorld { - color: blue; } -/* line 22, inputs/selectors.scss */ -[foo].helloWorld { - color: blue; } -/* line 23, inputs/selectors.scss */ -[foo="barbar"] { - color: blue; } -/* line 24, inputs/selectors.scss */ -[foo~="hello#$@%@$#^"] { - color: blue; } -/* line 25, inputs/selectors.scss */ -[foo^="color: green;"] { - color: blue; } -/* line 26, inputs/selectors.scss */ -[foo$="239023"] { - color: blue; } -/* line 27, inputs/selectors.scss */ -[foo*="29302"] { - color: blue; } -/* line 28, inputs/selectors.scss */ -[foo|="239032"] { - color: blue; } -/* line 30, inputs/selectors.scss */ -E:dir(ltr) { - color: blue; } -/* line 31, inputs/selectors.scss */ -E:lang(en) { - color: blue; } -/* line 32, inputs/selectors.scss */ -E:lang(en, fr) { - color: blue; } -/* line 34, inputs/selectors.scss */ -E:any-link { - color: blue; } -/* line 35, inputs/selectors.scss */ -E:link { - color: blue; } -/* line 36, inputs/selectors.scss */ -E:visited { - color: blue; } -/* line 37, inputs/selectors.scss */ -E:local-link { - color: blue; } -/* line 38, inputs/selectors.scss */ -E:local-link(0) { - color: red; } -/* line 39, inputs/selectors.scss */ -E:local-link(1) { - color: white; } -/* line 40, inputs/selectors.scss */ -E:local-link(2) { - color: red; } -/* line 41, inputs/selectors.scss */ -E:target { - color: blue; } -/* line 42, inputs/selectors.scss */ -E:scope { - color: blue; } -/* line 44, inputs/selectors.scss */ -E:current { - color: blue; } -/* line 45, inputs/selectors.scss */ -E:current(:link) { - color: blue; } -/* line 46, inputs/selectors.scss */ -E:past { - color: blue; } -/* line 47, inputs/selectors.scss */ -E:future { - color: blue; } -/* line 49, inputs/selectors.scss */ -E:active { - color: blue; } -/* line 50, inputs/selectors.scss */ -E:hover { - color: blue; } -/* line 51, inputs/selectors.scss */ -E:focus { - color: blue; } -/* line 52, inputs/selectors.scss */ -E:enabled { - color: blue; } -/* line 53, inputs/selectors.scss */ -E:disabled { - color: blue; } -/* line 54, inputs/selectors.scss */ -E:indeterminate { - color: blue; } -/* line 55, inputs/selectors.scss */ -E:default { - color: blue; } -/* line 56, inputs/selectors.scss */ -E:in-range { - color: blue; } -/* line 57, inputs/selectors.scss */ -E:out-of-range { - color: blue; } -/* line 58, inputs/selectors.scss */ -E:required { - color: blue; } -/* line 59, inputs/selectors.scss */ -E:optional { - color: blue; } -/* line 60, inputs/selectors.scss */ -E:read-only { - color: blue; } -/* line 61, inputs/selectors.scss */ -E:read-write { - color: blue; } -/* line 63, inputs/selectors.scss */ -E:root { - color: blue; } -/* line 64, inputs/selectors.scss */ -E:empty { - color: blue; } -/* line 65, inputs/selectors.scss */ -E:first-child { - color: blue; } -/* line 66, inputs/selectors.scss */ -E:nth-child(odd) { - color: blue; } -/* line 67, inputs/selectors.scss */ -E:nth-child(2n+1) { - color: blue; } -/* line 68, inputs/selectors.scss */ -E:nth-child(5) { - color: blue; } -/* line 69, inputs/selectors.scss */ -E:last-child { - color: blue; } -/* line 70, inputs/selectors.scss */ -E:nth-last-child(-n+2) { - color: blue; } -/* line 71, inputs/selectors.scss */ -E:only-child { - color: blue; } -/* line 72, inputs/selectors.scss */ -E:first-of-type { - color: blue; } -/* line 73, inputs/selectors.scss */ -E:nth-of-type(2n) { - color: blue; } -/* line 74, inputs/selectors.scss */ -E:last-of-type { - color: blue; } -/* line 75, inputs/selectors.scss */ -E:nth-last-of-type(n) { - color: blue; } -/* line 76, inputs/selectors.scss */ -E:only-of-type { - color: blue; } -/* line 77, inputs/selectors.scss */ -E:nth-match(odd) { - color: blue; } -/* line 78, inputs/selectors.scss */ -E:nth-last-match(odd) { - color: blue; } -/* line 80, inputs/selectors.scss */ -E:column(n) { - color: blue; } -/* line 81, inputs/selectors.scss */ -E:nth-column(n) { - color: blue; } -/* line 82, inputs/selectors.scss */ -E:nth-last-column(n) { - color: blue; } -/* line 84, inputs/selectors.scss */ -E F { - color: blue; } -/* line 85, inputs/selectors.scss */ -E > F { - color: blue; } -/* line 86, inputs/selectors.scss */ -E + F { - color: blue; } -/* line 87, inputs/selectors.scss */ -E ~ F { - color: blue; } -/* line 88, inputs/selectors.scss */ -E /foo/ F { - color: blue; } -/* line 89, inputs/selectors.scss */ -E! > F { - color: blue; } -/* line 92, inputs/selectors.scss */ -[foo|att=val] { - color: blue; } -/* line 93, inputs/selectors.scss */ -[*|att] { - color: yellow; } -/* line 94, inputs/selectors.scss */ -[|att] { - color: green; } -/* line 95, inputs/selectors.scss */ -[att] { - color: green; } -/* line 98, inputs/selectors.scss */ -E::first-line { - color: blue; } -/* line 99, inputs/selectors.scss */ -E::first-letter { - color: blue; } -/* line 100, inputs/selectors.scss */ -E::before { - color: blue; } -/* line 101, inputs/selectors.scss */ -E::after { - color: blue; } -/* line 104, inputs/selectors.scss */ -E::choices { - color: blue; } -/* line 105, inputs/selectors.scss */ -E::value { - color: blue; } -/* line 106, inputs/selectors.scss */ -E::repeat-index { - color: blue; } -/* line 107, inputs/selectors.scss */ -E::repeat-item { - color: blue; } -/* line 109, inputs/selectors.scss */ -E:first { - color: blue; } -/* line 110, inputs/selectors.scss */ -E:first-line { - color: blue; } -/* line 111, inputs/selectors.scss */ -E:first-letter { - color: blue; } -/* line 112, inputs/selectors.scss */ -E:before { - color: blue; } -/* line 113, inputs/selectors.scss */ -E:after { - color: blue; } -/* line 114, inputs/selectors.scss */ -E:checked { - color: blue; } -/* line 115, inputs/selectors.scss */ -E:invalid { - color: blue; } -/* line 116, inputs/selectors.scss */ -E:valid { - color: blue; } -/* line 117, inputs/selectors.scss */ -E:left { - color: blue; } -/* line 118, inputs/selectors.scss */ -E:right { - color: blue; } -/* line 121, inputs/selectors.scss */ -E:any(ol) { - color: blue; } -/* line 122, inputs/selectors.scss */ -E::selection { - color: blue; } -/* line 126, inputs/selectors.scss */ -div { - font: something; - font-size: 30em; } -/* line 127, inputs/selectors.scss */ -div font:something { - size: 30em; } -/* line 139, inputs/selectors.scss */ -/* line 140, inputs/selectors.scss */ - -.something.world { - color: blue; } -/* line 144, inputs/selectors.scss */ -.something .mold { - height: 200px; } -/* line 148, inputs/selectors.scss */ -.dog .something { - color: blue; } -/* line 153, inputs/selectors.scss */ -/* line 154, inputs/selectors.scss */ - -.dad .simple .wolf { - color: blue; } -/* line 158, inputs/selectors.scss */ -.rad.simple.bad { - color: blue; } -/* line 164, inputs/selectors.scss */ -/* line 165, inputs/selectors.scss */ - -/* line 166, inputs/selectors.scss */ - .something div .what.world { - color: blue; } -/* line 172, inputs/selectors.scss */ -/* line 173, inputs/selectors.scss */ - -div.foo div { - color: blue; } -/* line 176, inputs/selectors.scss */ -div + div { - color: green; } -/* line 181, inputs/selectors.scss */ -/* line 182, inputs/selectors.scss */ - -/* line 183, inputs/selectors.scss */ - /* line 184, inputs/selectors.scss */ - .nice-fonts .main .message div .title, .nice-fonts div .message div .title { - font-size: 24px; } -/* line 192, inputs/selectors.scss */ -.escape\% { - color: red; } -/* line 196, inputs/selectors.scss */ -.escape-plan\% { - color: green; } -/* line 200, inputs/selectors.scss */ -/* line 201, inputs/selectors.scss */ - -.element .one, .element .two { - property: value; } -/* line 228, inputs/selectors.scss */ -/* line 223, inputs/selectors.scss */ - -#secondary h1, #secondary h2, #secondary h3, #secondary h4, #secondary h5, #secondary h6 { - color: #e6e6e6; } -/* line 235, inputs/selectors.scss */ -/* line 236, inputs/selectors.scss */ - -.test foo, .test bar { - border: 1px dashed red; } -/* line 247, inputs/selectors.scss */ -/* line 248, inputs/selectors.scss */ - -span a, p a, div a { - color: red; } -/* line 253, inputs/selectors.scss */ -/* line 256, inputs/selectors.scss */ - -.parent.self { - content: "should match .parent.self"; } -/* line 259, inputs/selectors.scss */ -.parent .child { - content: "should match .parent .child"; } -/* line 262, inputs/selectors.scss */ -.parent.self2 { - content: "should match .parent.self2"; } -/* line 267, inputs/selectors.scss */ -/* line 269, inputs/selectors.scss */ - -.parent.self1, .parent.self2 { - content: "should match .parent.self1, .parent.self2"; } -/* line 274, inputs/selectors.scss */ -.self1 .parent { - content: "should match .self1 .parent"; } -/* line 279, inputs/selectors.scss */ -.parent + .parent { - content: "should match .parent + .parent"; } -/* line 285, inputs/selectors.scss */ -/* line 286, inputs/selectors.scss */ - -ul ul, ul ol, ol ul, ol ol { - display: block; } -/* line 292, inputs/selectors.scss */ -.👤 { - display: inline-block; } -/* line 296, inputs/selectors.scss */ -.❮ { - display: inline; - content: '↦'; } diff --git a/tests/outputs_numbered/short_circuit.css b/tests/outputs_numbered/short_circuit.css deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/outputs_numbered/shorthand.css b/tests/outputs_numbered/shorthand.css deleted file mode 100644 index 581aebe2..00000000 --- a/tests/outputs_numbered/shorthand.css +++ /dev/null @@ -1,39 +0,0 @@ -/* short-hand properties */ -/* line 2, inputs/shorthand.scss */ -div { - background: 0px 0px / 12px; - background: 25% 75% / cover; - background: center / 50%; - background: left / 3em; - background: right / auto; - background: top / contain; - background: 0px 0px, center / 50% auto; - background: 0px 0px, center / 3em 25%; - font: 0.8em / normal; - font: 12px / normal; - font: 80% / normal; - font: large / 34%; - font: large / 3.5; - font: large / 3em; - font: larger / normal; - font: 0.8em / 3.5; - font: 12px / 3em; - font: 80% / 34%; - /* size | family */ - font: 2em "Open Sans", sans-serif; - /* style | size | family */ - font: italic 2em "Open Sans", sans-serif; - /* style | variant | weight | size/line-height | family */ - font: italic small-caps bolder 16px/3 cursive; - /* The font used in system dialogs */ - font: message-box; - grid-column: 1 / 3; - grid-column: 2 / -1; - grid-column: auto / auto; - grid-column: span 3 / 6; - grid-column: 5 somegridarea span / 2 span; - grid-row: 1 / 3; - grid-row: 2 / -1; - grid-row: auto / auto; - grid-row: span 3 / 6; - grid-row: 5 somegridarea span / 2 span; } diff --git a/tests/outputs_numbered/values.css b/tests/outputs_numbered/values.css deleted file mode 100644 index e218a64e..00000000 --- a/tests/outputs_numbered/values.css +++ /dev/null @@ -1,44 +0,0 @@ -/* line 2, inputs/values.scss */ -#values { - color: #eee; - color: #eee; - height: 20px; - width: 80%; - color: "hello world"; - height: url("http://google.com"); - background-image: url(//host/image.png); - dads: url(http://leafo.net); - padding: 10px 10px 10px 10px, 3px 3px 3px; - textblock: "This is a multiline block #not { color: #eee;}"; - margin: 4, 3, 1; - content: "This is a multiline string."; - border-radius: -1px -1px -1px black; - grid-template-columns: [avatar] 2fr [body] 6fr; } -/* line 23, inputs/values.scss */ -#subtraction { - lit: 10 -11; - lit: -1; - lit: -1; - lit: -1; - var: -90; - var: -90; - var: -90; - var: -90; } -/* line 37, inputs/values.scss */ -#special { - a: 12px expression(1 + (3 / Foo.bar("baz" + "bang") + function() {return 12;}) % 12); } -/* line 41, inputs/values.scss */ -#unary { - b: 0.5em; - c: -foo(12px); - d: +foo(12px); } -/* line 47, inputs/values.scss */ -#self { - content: "#self"; } - -@font-face { - unicode-range: U+26; - unicode-range: U+0-7F; - unicode-range: U+0025-00FF; - unicode-range: U+4??; - unicode-range: U+0025-00FF, U+4??; } diff --git a/tests/outputs_numbered/variables.css b/tests/outputs_numbered/variables.css deleted file mode 100644 index 4d33c91c..00000000 --- a/tests/outputs_numbered/variables.css +++ /dev/null @@ -1,42 +0,0 @@ -cool: 100px; -/* line 4, inputs/variables.scss */ -div { - height: red, two, three; } -/* line 10, inputs/variables.scss */ -div { - num: 1000; } -/* line 15, inputs/variables.scss */ -div { - num: 2000; } -/* line 23, inputs/variables.scss */ -pre { - color: blue; } -/* line 31, inputs/variables.scss */ -del { - color: blue; } -/* line 34, inputs/variables.scss */ -/* line 36, inputs/variables.scss */ - del div pre { - color: red; } -/* line 50, inputs/variables.scss */ -body { - font-family: Arial; - font-family: Helvetica Neue; - font-family: "Helvetica Neue"; - font-family: Helvetica, Arial, sans-serif; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } -/* line 58, inputs/variables.scss */ -#main { - width: 5em; } -/* line 63, inputs/variables.scss */ -#sidebar { - width: 5em; } -/* line 71, inputs/variables.scss */ -A { - color: green; } -/* line 79, inputs/variables.scss */ -body { - color: #000; } -/* line 86, inputs/variables.scss */ -* { - data: 12; } diff --git a/tests/scss_test.rb b/tests/scss_test.rb deleted file mode 100644 index 41fa8e75..00000000 --- a/tests/scss_test.rb +++ /dev/null @@ -1,4238 +0,0 @@ -# -*- coding: utf-8 -*- -require File.dirname(__FILE__) + '/test_helper' - -class ScssTest < MiniTest::Test - include ScssTestHelper - - ## One-Line Comments - - def test_one_line_comments - assert_equal < :nested)) -@fblthp { - .foo .bar { - a: b; } } -CSS -.foo { - @fblthp { - .bar {a: b} - } -} -SCSS - end - - def test_keyframe_bubbling - assert_equal(< :nested)) -@keyframes spin { - 0% { - transform: rotate(0deg); } } -@-webkit-keyframes spin { - 0% { - transform: rotate(0deg); } } -CSS -.foo { - @keyframes spin { - 0% {transform: rotate(0deg)} - } - @-webkit-keyframes spin { - 0% {transform: rotate(0deg)} - } -} -SCSS - end - - ## Namespace Properties - - def test_namespace_properties - assert_equal < e - assert_equal 'Invalid CSS after "bar:baz calc": expected selector, was "(1 + 2)"', e.message - assert_equal 2, e.sass_line - end - - def test_namespace_properties_without_space_allowed_for_non_identifier - assert_equal < e - assert_equal "Extend directives may only be used within rules.", e.message - assert_equal 3, e.sass_line - end - - def test_at_root_doesnt_always_break_blocks - assert_equal < e - assert_equal 'Invalid CSS after "": expected selector, was "0%"', e.message - assert_equal 1, e.sass_line - end - - def test_selector_rule_in_keyframes - render < e - assert_equal 'Invalid CSS after "": expected keyframes selector (e.g. 10%), was ".foo"', e.message - assert_equal 2, e.sass_line - end - - def test_nested_mixin_def_is_scoped - render < e - assert_equal "Undefined mixin 'bar'.", e.message - assert_equal 3, e.sass_line - end - - def test_rules_beneath_properties - render < e - assert_equal 'Illegal nesting: Only properties may be nested beneath properties.', e.message - assert_equal 3, e.sass_line - end - - def test_uses_property_exception_with_star_hack - render <; } -SCSS - assert(false, "Expected syntax error") - rescue Sass::SyntaxError => e - assert_equal 'Invalid CSS after " *bar:baz ": expected expression (e.g. 1px, bold), was "; }"', e.message - assert_equal 2, e.sass_line - end - - def test_uses_property_exception_with_colon_hack - render <; } -SCSS - assert(false, "Expected syntax error") - rescue Sass::SyntaxError => e - assert_equal 'Invalid CSS after " :bar:baz ": expected expression (e.g. 1px, bold), was "; }"', e.message - assert_equal 2, e.sass_line - end - - def test_uses_rule_exception_with_dot_hack - render <; } -SCSS - assert(false, "Expected syntax error") - rescue Sass::SyntaxError => e - assert_equal 'Invalid CSS after " .bar:baz ": expected expression (e.g. 1px, bold), was "; }"', e.message - assert_equal 2, e.sass_line - end - - def test_uses_property_exception_with_space_after_name - render <; } -SCSS - assert(false, "Expected syntax error") - rescue Sass::SyntaxError => e - assert_equal 'Invalid CSS after " bar: baz ": expected expression (e.g. 1px, bold), was "; }"', e.message - assert_equal 2, e.sass_line - end - - def test_uses_property_exception_with_non_identifier_after_name - render <; } -SCSS - assert(false, "Expected syntax error") - rescue Sass::SyntaxError => e - assert_equal 'Invalid CSS after " bar:1px ": expected expression (e.g. 1px, bold), was "; }"', e.message - assert_equal 2, e.sass_line - end - - def test_uses_property_exception_when_followed_by_open_bracket - render < e - assert_equal 'Invalid CSS after " bar:{baz: ": expected expression (e.g. 1px, bold), was ".fail} }"', e.message - assert_equal 2, e.sass_line - end - - def test_script_error - render < e - assert_equal 'Invalid CSS after " bar: "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message - assert_equal 2, e.sass_line - end - - def test_multiline_script_syntax_error - render < e - assert_equal 'Invalid CSS after " "baz" * ": expected expression (e.g. 1px, bold), was "* }"', e.message - assert_equal 3, e.sass_line - end - - def test_multiline_script_runtime_error - render < e - assert_equal "Undefined variable: \"$bang\".", e.message - assert_equal 4, e.sass_line - end - - def test_post_multiline_script_runtime_error - render < e - assert_equal "Undefined variable: \"$bop\".", e.message - assert_equal 5, e.sass_line - end - - def test_multiline_property_runtime_error - render < e - assert_equal "Undefined variable: \"$bang\".", e.message - assert_equal 4, e.sass_line - end - - def test_post_resolution_selector_error - render "\n\nfoo \#{\") bar\"} {a: b}" - assert(false, "Expected syntax error") - rescue Sass::SyntaxError => e - assert_equal 'Invalid CSS after "foo ": expected selector, was ") bar"', e.message - assert_equal 3, e.sass_line - end - - def test_parent_in_mid_selector_error - assert_raise_message(Sass::SyntaxError, < :compressed) -z a,z b{display:block} -CSS -a -, b { - z & { - display: block; - } -} -SCSS - end - - def test_if_error_line - assert_raise_line(2) {render(< :compressed) -foo{color:#000} -CSS -foo {color: darken(black, 10%)} -SCSS - end - - # ref: https://github.com/nex3/sass/issues/104 - def test_no_buffer_overflow - template = render < :compressed)) -@import url("fallback-layout.css") supports(not (display: flex)) -CSS -$display-type: flex; -@import url("fallback-layout.css") supports(not (display: #{$display-type})); -SASS - end - - def test_import_with_supports_clause - assert_equal(< :compressed)) -@import url("fallback-layout.css") supports(not (display: flex));.foo{bar:baz} -CSS -@import url("fallback-layout.css") supports(not (display: flex)); -.foo { bar: baz; } -SASS - end - - def test_crlf - # Attempt to reproduce https://github.com/sass/sass/issues/1985 - assert_equal(<