less 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Changelog.md +4 -0
- data/Gemfile +1 -1
- data/less.gemspec +1 -1
- data/lib/less/defaults.rb +3 -3
- data/lib/less/java_script/v8_context.rb +1 -1
- data/lib/less/js/.gitattributes +3 -2
- data/lib/less/js/.gitignore +18 -2
- data/lib/less/js/.jshintrc +11 -0
- data/lib/less/js/CHANGELOG.md +87 -2
- data/lib/less/js/CONTRIBUTING.md +4 -3
- data/lib/less/js/Gruntfile.js +290 -0
- data/lib/less/js/README.md +342 -12
- data/lib/less/js/benchmark/benchmark.less +194 -194
- data/lib/less/js/benchmark/less-benchmark.js +9 -10
- data/lib/less/js/bin/lessc +154 -12
- data/lib/less/js/bower.json +18 -0
- data/lib/less/js/build.gradle +347 -0
- data/lib/less/js/build/README.md +350 -0
- data/lib/less/js/build/browser-header.js +4 -0
- data/lib/less/js/build/build.yml +160 -0
- data/lib/less/js/build/require-rhino.js +7 -2
- data/lib/less/js/build/rhino-header.js +4 -0
- data/lib/less/js/build/rhino-modules.js +131 -0
- data/lib/less/js/build/tasks/.gitkeep +1 -0
- data/lib/less/js/dist/less-1.5.0.js +6914 -0
- data/lib/less/js/dist/less-1.5.0.min.js +13 -0
- data/lib/less/js/dist/less-1.5.1.js +6941 -0
- data/lib/less/js/dist/less-1.5.1.min.js +13 -0
- data/lib/less/js/dist/less-1.6.0.js +7485 -0
- data/lib/less/js/dist/less-1.6.0.min.js +16 -0
- data/lib/less/js/dist/less-1.6.1.js +7513 -0
- data/lib/less/js/dist/less-1.6.1.min.js +16 -0
- data/lib/less/js/dist/less-1.6.2.js +7624 -0
- data/lib/less/js/dist/less-1.6.2.min.js +16 -0
- data/lib/less/js/dist/less-rhino-1.5.1.js +6831 -0
- data/lib/less/js/dist/less-rhino-1.6.2.js +9017 -0
- data/lib/less/js/dist/lessc-rhino-1.6.2.js +449 -0
- data/lib/less/js/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/lib/less/js/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/lib/less/js/gradlew +164 -0
- data/lib/less/js/gradlew.bat +90 -0
- data/lib/less/js/lib/less/browser.js +482 -367
- data/lib/less/js/lib/less/colors.js +0 -1
- data/lib/less/js/lib/less/encoder.js +4 -0
- data/lib/less/js/lib/less/env.js +50 -19
- data/lib/less/js/lib/less/extend-visitor.js +66 -41
- data/lib/less/js/lib/less/functions.js +309 -104
- data/lib/less/js/lib/less/import-visitor.js +21 -10
- data/lib/less/js/lib/less/index.js +90 -68
- data/lib/less/js/lib/less/join-selector-visitor.js +11 -4
- data/lib/less/js/lib/less/lessc_helper.js +56 -45
- data/lib/less/js/lib/less/parser.js +830 -460
- data/lib/less/js/lib/less/rhino.js +380 -58
- data/lib/less/js/lib/less/source-map-output.js +141 -0
- data/lib/less/js/lib/less/to-css-visitor.js +215 -0
- data/lib/less/js/lib/less/tree.js +57 -5
- data/lib/less/js/lib/less/tree/alpha.js +13 -5
- data/lib/less/js/lib/less/tree/anonymous.js +11 -5
- data/lib/less/js/lib/less/tree/assignment.js +11 -5
- data/lib/less/js/lib/less/tree/call.js +19 -8
- data/lib/less/js/lib/less/tree/color.js +59 -36
- data/lib/less/js/lib/less/tree/comment.js +17 -4
- data/lib/less/js/lib/less/tree/condition.js +3 -3
- data/lib/less/js/lib/less/tree/dimension.js +161 -153
- data/lib/less/js/lib/less/tree/directive.js +39 -18
- data/lib/less/js/lib/less/tree/element.js +41 -18
- data/lib/less/js/lib/less/tree/expression.js +11 -5
- data/lib/less/js/lib/less/tree/extend.js +11 -1
- data/lib/less/js/lib/less/tree/import.js +34 -20
- data/lib/less/js/lib/less/tree/javascript.js +16 -10
- data/lib/less/js/lib/less/tree/keyword.js +5 -2
- data/lib/less/js/lib/less/tree/media.js +39 -22
- data/lib/less/js/lib/less/tree/mixin.js +135 -56
- data/lib/less/js/lib/less/tree/negative.js +4 -2
- data/lib/less/js/lib/less/tree/operation.js +17 -12
- data/lib/less/js/lib/less/tree/paren.js +5 -2
- data/lib/less/js/lib/less/tree/quoted.js +9 -6
- data/lib/less/js/lib/less/tree/rule.js +39 -21
- data/lib/less/js/lib/less/tree/ruleset.js +229 -145
- data/lib/less/js/lib/less/tree/selector.js +101 -34
- data/lib/less/js/lib/less/tree/unicode-descriptor.js +4 -3
- data/lib/less/js/lib/less/tree/url.js +33 -11
- data/lib/less/js/lib/less/tree/value.js +13 -6
- data/lib/less/js/lib/less/tree/variable.js +13 -8
- data/lib/less/js/lib/less/visitor.js +117 -25
- data/lib/less/js/lib/source-map/source-map-0.1.31.js +1933 -0
- data/lib/less/js/lib/source-map/source-map-footer.js +4 -0
- data/lib/less/js/lib/source-map/source-map-header.js +3 -0
- data/lib/less/js/package.json +30 -15
- data/lib/less/js/test/browser/common.js +131 -56
- data/lib/less/js/test/browser/css/global-vars/simple.css +3 -0
- data/lib/less/js/test/browser/css/modify-vars/simple.css +8 -0
- data/lib/less/js/test/browser/css/relative-urls/urls.css +8 -9
- data/lib/less/js/test/browser/css/rootpath-relative/urls.css +0 -1
- data/lib/less/js/test/browser/css/rootpath/urls.css +0 -1
- data/lib/less/js/test/browser/css/urls.css +18 -14
- data/lib/less/js/test/browser/es5.js +27 -0
- data/lib/less/js/test/{less/errors/color-operation-error.less → browser/less/console-errors/test-error.less} +0 -0
- data/lib/less/js/test/browser/less/console-errors/test-error.txt +2 -0
- data/lib/less/js/test/browser/less/global-vars/simple.less +3 -0
- data/lib/less/js/test/browser/less/modify-vars/imports/simple2.less +4 -0
- data/lib/less/js/test/browser/less/modify-vars/simple.less +8 -0
- data/lib/less/js/test/browser/less/relative-urls/urls.less +1 -1
- data/lib/less/js/test/browser/less/rootpath-relative/urls.less +1 -1
- data/lib/less/js/test/browser/less/rootpath/urls.less +1 -1
- data/lib/less/js/test/browser/less/urls.less +9 -1
- data/lib/less/js/test/browser/phantom-runner.js +112 -103
- data/lib/less/js/test/browser/runner-browser-options.js +42 -0
- data/lib/less/js/test/browser/{runner-browser.js → runner-browser-spec.js} +7 -2
- data/lib/less/js/test/browser/runner-console-errors.js +5 -0
- data/lib/less/js/test/browser/runner-errors-options.js +5 -0
- data/lib/less/js/test/browser/runner-errors-spec.js +4 -0
- data/lib/less/js/test/browser/runner-global-vars-options.js +4 -0
- data/lib/less/js/test/browser/runner-global-vars-spec.js +3 -0
- data/lib/less/js/test/browser/runner-legacy-options.js +4 -0
- data/lib/less/js/test/browser/{runner-legacy.js → runner-legacy-spec.js} +1 -4
- data/lib/less/js/test/browser/runner-main-options.js +15 -0
- data/lib/less/js/test/browser/runner-main-spec.js +3 -0
- data/lib/less/js/test/browser/runner-modify-vars-options.js +2 -0
- data/lib/less/js/test/browser/runner-modify-vars-spec.js +43 -0
- data/lib/less/js/test/browser/runner-no-js-errors-options.js +4 -0
- data/lib/less/js/test/browser/runner-no-js-errors-spec.js +4 -0
- data/lib/less/js/test/browser/runner-production-options.js +3 -0
- data/lib/less/js/test/browser/{runner-production.js → runner-production-spec.js} +1 -3
- data/lib/less/js/test/browser/runner-relative-urls-options.js +3 -0
- data/lib/less/js/test/browser/{runner-relative-urls.js → runner-relative-urls-spec.js} +1 -2
- data/lib/less/js/test/browser/runner-rootpath-options.js +3 -0
- data/lib/less/js/test/browser/runner-rootpath-relative-options.js +4 -0
- data/lib/less/js/test/browser/{runner-rootpath-relative.js → runner-rootpath-relative-spec.js} +1 -3
- data/lib/less/js/test/browser/{runner-rootpath.js → runner-rootpath-spec.js} +1 -2
- data/lib/less/js/test/browser/test-runner-template.tmpl +47 -0
- data/lib/less/js/test/css/colors.css +7 -0
- data/lib/less/js/test/css/comments.css +9 -4
- data/lib/less/js/test/css/compression/compression.css +3 -2
- data/lib/less/js/test/css/css-3.css +17 -5
- data/lib/less/js/test/css/css-guards.css +37 -0
- data/lib/less/js/test/css/debug/linenumbers-all.css +6 -0
- data/lib/less/js/test/css/debug/linenumbers-comments.css +5 -0
- data/lib/less/js/test/css/debug/linenumbers-mediaquery.css +5 -0
- data/lib/less/js/test/css/empty.css +0 -0
- data/lib/less/js/test/css/extend-chaining.css +9 -0
- data/lib/less/js/test/css/extend-selector.css +10 -2
- data/lib/less/js/test/css/extract-and-length.css +133 -0
- data/lib/less/js/test/css/functions.css +23 -10
- data/lib/less/js/test/css/globalVars/extended.css +12 -0
- data/lib/less/js/test/css/globalVars/simple.css +6 -0
- data/lib/less/js/test/css/import-inline.css +5 -0
- data/lib/less/js/test/css/import-once.css +12 -0
- data/lib/less/js/test/css/import-reference.css +49 -0
- data/lib/less/js/test/css/import.css +0 -2
- data/lib/less/js/test/css/media.css +21 -5
- data/lib/less/js/test/css/merge.css +26 -0
- data/lib/less/js/test/css/mixins-guards-default-func.css +129 -0
- data/lib/less/js/test/css/mixins-guards.css +6 -0
- data/lib/less/js/test/css/mixins-important.css +7 -0
- data/lib/less/js/test/css/mixins-interpolated.css +39 -0
- data/lib/less/js/test/css/mixins.css +20 -0
- data/lib/less/js/test/css/modifyVars/extended.css +9 -0
- data/lib/less/js/test/css/no-output.css +0 -0
- data/lib/less/js/test/css/parens.css +3 -0
- data/lib/less/js/test/css/property-name-interp.css +20 -0
- data/lib/less/js/test/css/selectors.css +12 -0
- data/lib/less/js/test/css/static-urls/urls.css +7 -4
- data/lib/less/js/test/css/strings.css +3 -0
- data/lib/less/js/test/css/url-args/urls.css +56 -0
- data/lib/less/js/test/css/urls.css +21 -9
- data/lib/less/js/test/index.js +45 -0
- data/lib/less/js/test/less-test.js +234 -191
- data/lib/less/js/test/less/colors.less +6 -0
- data/lib/less/js/test/less/comments.less +7 -1
- data/lib/less/js/test/less/compression/compression.less +21 -1
- data/lib/less/js/test/less/css-3.less +12 -0
- data/lib/less/js/test/less/css-guards.less +99 -0
- data/lib/less/js/test/less/debug/linenumbers.less +11 -1
- data/lib/less/js/test/less/empty.less +0 -0
- data/lib/less/js/test/less/errors/add-mixed-units.txt +4 -2
- data/lib/less/js/test/less/errors/add-mixed-units2.txt +4 -2
- data/lib/less/js/test/less/errors/color-func-invalid-color.less +3 -0
- data/lib/less/js/test/less/errors/color-func-invalid-color.txt +4 -0
- data/lib/less/js/test/less/errors/css-guard-default-func.less +4 -0
- data/lib/less/js/test/less/errors/css-guard-default-func.txt +4 -0
- data/lib/less/js/test/less/errors/import-subfolder2.txt +4 -2
- data/lib/less/js/test/less/errors/javascript-undefined-var.less +3 -0
- data/lib/less/js/test/less/errors/javascript-undefined-var.txt +4 -0
- data/lib/less/js/test/less/errors/mixins-guards-default-func-1.less +9 -0
- data/lib/less/js/test/less/errors/mixins-guards-default-func-1.txt +4 -0
- data/lib/less/js/test/less/errors/mixins-guards-default-func-2.less +9 -0
- data/lib/less/js/test/less/errors/mixins-guards-default-func-2.txt +4 -0
- data/lib/less/js/test/less/errors/mixins-guards-default-func-3.less +9 -0
- data/lib/less/js/test/less/errors/mixins-guards-default-func-3.txt +4 -0
- data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors.less +4 -0
- data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors.txt +4 -0
- data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors2.less +4 -0
- data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors2.txt +4 -0
- data/lib/less/js/test/less/errors/parse-error-curly-bracket.less +4 -1
- data/lib/less/js/test/less/errors/parse-error-curly-bracket.txt +4 -2
- data/lib/less/js/test/less/errors/parse-error-extra-parens.less +5 -0
- data/lib/less/js/test/less/errors/parse-error-extra-parens.txt +3 -0
- data/lib/less/js/test/less/errors/parse-error-missing-bracket.txt +2 -2
- data/lib/less/js/test/less/errors/parse-error-missing-parens.less +5 -0
- data/lib/less/js/test/less/errors/parse-error-missing-parens.txt +3 -0
- data/lib/less/js/test/less/errors/property-asterisk-only-name.less +3 -0
- data/lib/less/js/test/less/errors/property-asterisk-only-name.txt +4 -0
- data/lib/less/js/test/less/errors/property-interp-not-defined.less +1 -0
- data/lib/less/js/test/less/errors/property-interp-not-defined.txt +2 -0
- data/lib/less/js/test/less/errors/svg-gradient1.less +3 -0
- data/lib/less/js/test/less/errors/svg-gradient1.txt +4 -0
- data/lib/less/js/test/less/errors/svg-gradient2.less +3 -0
- data/lib/less/js/test/less/errors/svg-gradient2.txt +4 -0
- data/lib/less/js/test/less/errors/svg-gradient3.less +3 -0
- data/lib/less/js/test/less/errors/svg-gradient3.txt +4 -0
- data/lib/less/js/test/less/errors/unit-function.less +3 -0
- data/lib/less/js/test/less/errors/unit-function.txt +4 -0
- data/lib/less/js/test/less/extend-chaining.less +12 -0
- data/lib/less/js/test/less/extend-selector.less +15 -0
- data/lib/less/js/test/less/extract-and-length.less +133 -0
- data/lib/less/js/test/less/functions.less +15 -2
- data/lib/less/js/test/less/globalVars/extended.json +5 -0
- data/lib/less/js/test/less/globalVars/extended.less +10 -0
- data/lib/less/js/test/less/globalVars/simple.json +3 -0
- data/lib/less/js/test/less/globalVars/simple.less +3 -0
- data/lib/less/js/test/less/import-inline.less +2 -0
- data/lib/less/js/test/less/import-once.less +2 -0
- data/lib/less/js/test/less/import-reference.less +18 -0
- data/lib/less/js/test/less/import/import-and-relative-paths-test.less +11 -0
- data/lib/less/js/test/less/import/import-reference.less +43 -0
- data/lib/less/js/test/less/import/import-test-f.less +5 -0
- data/lib/less/js/test/less/import/invalid-css.less +1 -0
- data/lib/less/js/test/less/media.less +25 -1
- data/lib/less/js/test/less/merge.less +59 -0
- data/lib/less/js/test/less/mixins-args.less +10 -0
- data/lib/less/js/test/less/mixins-guards-default-func.less +195 -0
- data/lib/less/js/test/less/mixins-guards.less +16 -0
- data/lib/less/js/test/less/mixins-important.less +4 -1
- data/lib/less/js/test/less/mixins-interpolated.less +69 -0
- data/lib/less/js/test/less/mixins.less +27 -0
- data/lib/less/js/test/less/modifyVars/extended.json +5 -0
- data/lib/less/js/test/less/modifyVars/extended.less +11 -0
- data/lib/less/js/test/less/no-js-errors/no-js-errors.less +3 -0
- data/lib/less/js/test/less/no-js-errors/no-js-errors.txt +4 -0
- data/lib/less/js/test/less/no-output.less +2 -0
- data/lib/less/js/test/less/parens.less +4 -0
- data/lib/less/js/test/less/property-name-interp.less +53 -0
- data/lib/less/js/test/less/selectors.less +13 -0
- data/lib/less/js/test/less/sourcemaps/basic.json +3 -0
- data/lib/less/js/test/less/sourcemaps/basic.less +27 -0
- data/lib/less/js/test/less/sourcemaps/imported.css +7 -0
- data/lib/less/js/test/less/strings.less +6 -0
- data/lib/less/js/test/less/url-args/urls.less +63 -0
- data/lib/less/js/test/less/urls.less +15 -0
- data/lib/less/js/test/rhino/test-header.js +15 -0
- data/lib/less/js/test/sourcemaps/basic.json +1 -0
- data/lib/less/js/test/sourcemaps/index.html +17 -0
- data/lib/less/loader.rb +48 -40
- data/lib/less/version.rb +1 -1
- data/spec/less/parser_spec.rb +15 -15
- metadata +146 -40
- data/lib/less/js/Makefile +0 -102
- data/lib/less/js/build/header.js +0 -9
- data/lib/less/js/test/browser-test-prepare.js +0 -46
- data/lib/less/js/test/browser/runner-errors.js +0 -5
- data/lib/less/js/test/browser/runner-main.js +0 -15
- data/lib/less/js/test/browser/template.htm +0 -10
- data/lib/less/js/test/less/errors/color-operation-error.txt +0 -2
data/lib/less/js/lib/less/env.js
CHANGED
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
'paths', // option - unmodified - paths to search for imports on
|
|
5
5
|
'optimization', // option - optimization level (for the chunker)
|
|
6
6
|
'files', // list of files that have been imported, used for import-once
|
|
7
|
-
'contents', //
|
|
7
|
+
'contents', // map - filename to contents of all the files
|
|
8
|
+
'contentsIgnoredChars', // map - filename to lines at the begining of each file to ignore
|
|
8
9
|
'relativeUrls', // option - whether to adjust URL's to be relative
|
|
10
|
+
'rootpath', // option - rootpath to append to URL's
|
|
9
11
|
'strictImports', // option -
|
|
12
|
+
'insecure', // option - whether to allow imports from insecure ssl hosts
|
|
10
13
|
'dumpLineNumbers', // option - whether to dump line numbers
|
|
11
14
|
'compress', // option - whether to compress
|
|
12
15
|
'processImports', // option - whether to process imports. if false then imports will not be imported
|
|
13
16
|
'syncImport', // option - whether to import synchronously
|
|
17
|
+
'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
|
|
14
18
|
'mime', // browser only - mime type for sheet import
|
|
19
|
+
'useFileCache', // browser only - whether to use the per file session cache
|
|
15
20
|
'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc.
|
|
16
21
|
];
|
|
17
22
|
|
|
@@ -21,12 +26,14 @@
|
|
|
21
26
|
// 'rootpath' - path to append to normal URLs for this node
|
|
22
27
|
// 'currentDirectory' - path to the current file, absolute
|
|
23
28
|
// 'rootFilename' - filename of the base file
|
|
24
|
-
// 'entryPath'
|
|
29
|
+
// 'entryPath' - absolute path to the entry file
|
|
30
|
+
// 'reference' - whether the file should not be output and only output parts that are referenced
|
|
25
31
|
|
|
26
32
|
tree.parseEnv = function(options) {
|
|
27
33
|
copyFromOriginal(options, this, parseCopyProperties);
|
|
28
34
|
|
|
29
35
|
if (!this.contents) { this.contents = {}; }
|
|
36
|
+
if (!this.contentsIgnoredChars) { this.contentsIgnoredChars = {}; }
|
|
30
37
|
if (!this.files) { this.files = {}; }
|
|
31
38
|
|
|
32
39
|
if (!this.currentFileInfo) {
|
|
@@ -46,22 +53,18 @@
|
|
|
46
53
|
}
|
|
47
54
|
};
|
|
48
55
|
|
|
49
|
-
tree.parseEnv.prototype.toSheet = function (path) {
|
|
50
|
-
var env = new tree.parseEnv(this);
|
|
51
|
-
env.href = path;
|
|
52
|
-
//env.title = path;
|
|
53
|
-
env.type = this.mime;
|
|
54
|
-
return env;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
56
|
var evalCopyProperties = [
|
|
58
|
-
'silent',
|
|
59
|
-
'verbose',
|
|
60
|
-
'compress',
|
|
61
|
-
'yuicompress',
|
|
62
|
-
'ieCompat',
|
|
63
|
-
'strictMath',
|
|
64
|
-
'strictUnits'
|
|
57
|
+
'silent', // whether to swallow errors and warnings
|
|
58
|
+
'verbose', // whether to log more activity
|
|
59
|
+
'compress', // whether to compress
|
|
60
|
+
'yuicompress', // whether to compress with the outside tool yui compressor
|
|
61
|
+
'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
|
|
62
|
+
'strictMath', // whether math has to be within parenthesis
|
|
63
|
+
'strictUnits', // whether units need to evaluate correctly
|
|
64
|
+
'cleancss', // whether to compress with clean-css
|
|
65
|
+
'sourceMap', // whether to output a source map
|
|
66
|
+
'importMultiple', // whether we are currently importing multiple copies
|
|
67
|
+
'urlArgs' // whether to add args into url tokens
|
|
65
68
|
];
|
|
66
69
|
|
|
67
70
|
tree.evalEnv = function(options, frames) {
|
|
@@ -89,6 +92,33 @@
|
|
|
89
92
|
return !/^(?:[a-z-]+:|\/)/.test(path);
|
|
90
93
|
};
|
|
91
94
|
|
|
95
|
+
tree.evalEnv.prototype.normalizePath = function( path ) {
|
|
96
|
+
var
|
|
97
|
+
segments = path.split("/").reverse(),
|
|
98
|
+
segment;
|
|
99
|
+
|
|
100
|
+
path = [];
|
|
101
|
+
while (segments.length !== 0 ) {
|
|
102
|
+
segment = segments.pop();
|
|
103
|
+
switch( segment ) {
|
|
104
|
+
case ".":
|
|
105
|
+
break;
|
|
106
|
+
case "..":
|
|
107
|
+
if ((path.length === 0) || (path[path.length - 1] === "..")) {
|
|
108
|
+
path.push( segment );
|
|
109
|
+
} else {
|
|
110
|
+
path.pop();
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
path.push( segment );
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return path.join("/");
|
|
120
|
+
};
|
|
121
|
+
|
|
92
122
|
//todo - do the same for the toCSS env
|
|
93
123
|
//tree.toCSSEnv = function (options) {
|
|
94
124
|
//};
|
|
@@ -101,5 +131,6 @@
|
|
|
101
131
|
destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
|
|
102
132
|
}
|
|
103
133
|
}
|
|
104
|
-
}
|
|
105
|
-
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
})(require('./tree'));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
(function (tree) {
|
|
2
|
+
/*jshint loopfunc:true */
|
|
3
|
+
|
|
2
4
|
tree.extendFinderVisitor = function() {
|
|
3
5
|
this._visitor = new tree.visitor(this);
|
|
4
6
|
this.contexts = [];
|
|
@@ -18,7 +20,6 @@
|
|
|
18
20
|
visitArgs.visitDeeper = false;
|
|
19
21
|
},
|
|
20
22
|
visitRuleset: function (rulesetNode, visitArgs) {
|
|
21
|
-
|
|
22
23
|
if (rulesetNode.root) {
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
@@ -26,20 +27,31 @@
|
|
|
26
27
|
var i, j, extend, allSelectorsExtendList = [], extendList;
|
|
27
28
|
|
|
28
29
|
// get &:extend(.a); rules which apply to all selectors in this ruleset
|
|
29
|
-
|
|
30
|
+
var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
|
|
31
|
+
for(i = 0; i < ruleCnt; i++) {
|
|
30
32
|
if (rulesetNode.rules[i] instanceof tree.Extend) {
|
|
31
|
-
allSelectorsExtendList.push(
|
|
33
|
+
allSelectorsExtendList.push(rules[i]);
|
|
34
|
+
rulesetNode.extendOnEveryPath = true;
|
|
32
35
|
}
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
// now find every selector and apply the extends that apply to all extends
|
|
36
39
|
// and the ones which apply to an individual extend
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
var paths = rulesetNode.paths;
|
|
41
|
+
for(i = 0; i < paths.length; i++) {
|
|
42
|
+
var selectorPath = paths[i],
|
|
43
|
+
selector = selectorPath[selectorPath.length - 1],
|
|
44
|
+
selExtendList = selector.extendList;
|
|
45
|
+
|
|
46
|
+
extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
|
|
47
|
+
: allSelectorsExtendList;
|
|
48
|
+
|
|
49
|
+
if (extendList) {
|
|
50
|
+
extendList = extendList.map(function(allSelectorsExtend) {
|
|
51
|
+
return allSelectorsExtend.clone();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
43
55
|
for(j = 0; j < extendList.length; j++) {
|
|
44
56
|
this.foundExtends = true;
|
|
45
57
|
extend = extendList[j];
|
|
@@ -113,7 +125,7 @@
|
|
|
113
125
|
targetExtend = extendsListTarget[targetExtendIndex];
|
|
114
126
|
|
|
115
127
|
// look for circular references
|
|
116
|
-
if
|
|
128
|
+
if( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ){ continue; }
|
|
117
129
|
|
|
118
130
|
// find a match in the target extends self selector (the bit before :extend)
|
|
119
131
|
selectorPath = [targetExtend.selfSelectors[0]];
|
|
@@ -139,7 +151,7 @@
|
|
|
139
151
|
newExtend.ruleset = targetExtend.ruleset;
|
|
140
152
|
|
|
141
153
|
//remember its parents for circular references
|
|
142
|
-
newExtend.
|
|
154
|
+
newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
|
|
143
155
|
|
|
144
156
|
// only process the selector once.. if we have :extend(.a,.b) then multiple
|
|
145
157
|
// extends will look at the same selector path, so when extending
|
|
@@ -175,20 +187,6 @@
|
|
|
175
187
|
return extendsToAdd;
|
|
176
188
|
}
|
|
177
189
|
},
|
|
178
|
-
inInheritanceChain: function (possibleParent, possibleChild) {
|
|
179
|
-
if (possibleParent === possibleChild) {
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
if (possibleChild.parents) {
|
|
183
|
-
if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) {
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) {
|
|
187
|
-
return true;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return false;
|
|
191
|
-
},
|
|
192
190
|
visitRule: function (ruleNode, visitArgs) {
|
|
193
191
|
visitArgs.visitDeeper = false;
|
|
194
192
|
},
|
|
@@ -208,11 +206,12 @@
|
|
|
208
206
|
|
|
209
207
|
for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
|
|
210
208
|
for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
|
|
211
|
-
|
|
212
209
|
selectorPath = rulesetNode.paths[pathIndex];
|
|
213
210
|
|
|
214
211
|
// extending extends happens initially, before the main pass
|
|
215
|
-
if (
|
|
212
|
+
if (rulesetNode.extendOnEveryPath) { continue; }
|
|
213
|
+
var extendList = selectorPath[selectorPath.length-1].extendList;
|
|
214
|
+
if (extendList && extendList.length) { continue; }
|
|
216
215
|
|
|
217
216
|
matches = this.findMatch(allExtends[extendIndex], selectorPath);
|
|
218
217
|
|
|
@@ -246,7 +245,7 @@
|
|
|
246
245
|
haystackElement = hackstackSelector.elements[hackstackElementIndex];
|
|
247
246
|
|
|
248
247
|
// if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
|
|
249
|
-
if (extend.allowBefore || (haystackSelectorIndex
|
|
248
|
+
if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
|
|
250
249
|
potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
|
|
251
250
|
}
|
|
252
251
|
|
|
@@ -257,7 +256,7 @@
|
|
|
257
256
|
// then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
|
|
258
257
|
// what the resulting combinator will be
|
|
259
258
|
targetCombinator = haystackElement.combinator.value;
|
|
260
|
-
if (targetCombinator
|
|
259
|
+
if (targetCombinator === '' && hackstackElementIndex === 0) {
|
|
261
260
|
targetCombinator = ' ';
|
|
262
261
|
}
|
|
263
262
|
|
|
@@ -313,6 +312,24 @@
|
|
|
313
312
|
elementValue2 = elementValue2.value.value || elementValue2.value;
|
|
314
313
|
return elementValue1 === elementValue2;
|
|
315
314
|
}
|
|
315
|
+
elementValue1 = elementValue1.value;
|
|
316
|
+
elementValue2 = elementValue2.value;
|
|
317
|
+
if (elementValue1 instanceof tree.Selector) {
|
|
318
|
+
if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
for(var i = 0; i <elementValue1.elements.length; i++) {
|
|
322
|
+
if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
|
|
323
|
+
if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
316
333
|
return false;
|
|
317
334
|
},
|
|
318
335
|
extendSelector:function (matches, selectorPath, replacementSelector) {
|
|
@@ -325,7 +342,8 @@
|
|
|
325
342
|
matchIndex,
|
|
326
343
|
selector,
|
|
327
344
|
firstElement,
|
|
328
|
-
match
|
|
345
|
+
match,
|
|
346
|
+
newElements;
|
|
329
347
|
|
|
330
348
|
for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
|
|
331
349
|
match = matches[matchIndex];
|
|
@@ -333,7 +351,8 @@
|
|
|
333
351
|
firstElement = new tree.Element(
|
|
334
352
|
match.initialCombinator,
|
|
335
353
|
replacementSelector.elements[0].value,
|
|
336
|
-
replacementSelector.elements[0].index
|
|
354
|
+
replacementSelector.elements[0].index,
|
|
355
|
+
replacementSelector.elements[0].currentFileInfo
|
|
337
356
|
);
|
|
338
357
|
|
|
339
358
|
if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
|
|
@@ -342,17 +361,24 @@
|
|
|
342
361
|
currentSelectorPathIndex++;
|
|
343
362
|
}
|
|
344
363
|
|
|
345
|
-
|
|
364
|
+
newElements = selector.elements
|
|
365
|
+
.slice(currentSelectorPathElementIndex, match.index)
|
|
366
|
+
.concat([firstElement])
|
|
367
|
+
.concat(replacementSelector.elements.slice(1));
|
|
368
|
+
|
|
369
|
+
if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
|
|
370
|
+
path[path.length - 1].elements =
|
|
371
|
+
path[path.length - 1].elements.concat(newElements);
|
|
372
|
+
} else {
|
|
373
|
+
path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
|
|
346
374
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
.concat(replacementSelector.elements.slice(1))
|
|
352
|
-
));
|
|
375
|
+
path.push(new tree.Selector(
|
|
376
|
+
newElements
|
|
377
|
+
));
|
|
378
|
+
}
|
|
353
379
|
currentSelectorPathIndex = match.endPathIndex;
|
|
354
380
|
currentSelectorPathElementIndex = match.endPathElementIndex;
|
|
355
|
-
if (currentSelectorPathElementIndex >=
|
|
381
|
+
if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
|
|
356
382
|
currentSelectorPathElementIndex = 0;
|
|
357
383
|
currentSelectorPathIndex++;
|
|
358
384
|
}
|
|
@@ -360,7 +386,6 @@
|
|
|
360
386
|
|
|
361
387
|
if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
|
|
362
388
|
path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
|
|
363
|
-
currentSelectorPathElementIndex = 0;
|
|
364
389
|
currentSelectorPathIndex++;
|
|
365
390
|
}
|
|
366
391
|
|
|
@@ -388,4 +413,4 @@
|
|
|
388
413
|
}
|
|
389
414
|
};
|
|
390
415
|
|
|
391
|
-
})(require('./tree'));
|
|
416
|
+
})(require('./tree'));
|
|
@@ -5,7 +5,7 @@ tree.functions = {
|
|
|
5
5
|
return this.rgba(r, g, b, 1.0);
|
|
6
6
|
},
|
|
7
7
|
rgba: function (r, g, b, a) {
|
|
8
|
-
var rgb = [r, g, b].map(function (c) { return scaled(c,
|
|
8
|
+
var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
|
|
9
9
|
a = number(a);
|
|
10
10
|
return new(tree.Color)(rgb, a);
|
|
11
11
|
},
|
|
@@ -13,6 +13,14 @@ tree.functions = {
|
|
|
13
13
|
return this.hsla(h, s, l, 1.0);
|
|
14
14
|
},
|
|
15
15
|
hsla: function (h, s, l, a) {
|
|
16
|
+
function hue(h) {
|
|
17
|
+
h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
|
|
18
|
+
if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
|
|
19
|
+
else if (h * 2 < 1) { return m2; }
|
|
20
|
+
else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
|
|
21
|
+
else { return m1; }
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
h = (number(h) % 360) / 360;
|
|
17
25
|
s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
|
|
18
26
|
|
|
@@ -23,14 +31,6 @@ tree.functions = {
|
|
|
23
31
|
hue(h) * 255,
|
|
24
32
|
hue(h - 1/3) * 255,
|
|
25
33
|
a);
|
|
26
|
-
|
|
27
|
-
function hue(h) {
|
|
28
|
-
h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
|
|
29
|
-
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
|
|
30
|
-
else if (h * 2 < 1) return m2;
|
|
31
|
-
else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
|
|
32
|
-
else return m1;
|
|
33
|
-
}
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
hsv: function(h, s, v) {
|
|
@@ -96,6 +96,11 @@ tree.functions = {
|
|
|
96
96
|
return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%');
|
|
97
97
|
},
|
|
98
98
|
saturate: function (color, amount) {
|
|
99
|
+
// filter: saturate(3.2);
|
|
100
|
+
// should be kept as is, so check for color
|
|
101
|
+
if (!color.rgb) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
99
104
|
var hsl = color.toHSL();
|
|
100
105
|
|
|
101
106
|
hsl.s += amount.value / 100;
|
|
@@ -201,7 +206,7 @@ tree.functions = {
|
|
|
201
206
|
} else {
|
|
202
207
|
threshold = number(threshold);
|
|
203
208
|
}
|
|
204
|
-
if (
|
|
209
|
+
if (color.luma() < threshold) {
|
|
205
210
|
return light;
|
|
206
211
|
} else {
|
|
207
212
|
return dark;
|
|
@@ -218,6 +223,7 @@ tree.functions = {
|
|
|
218
223
|
str = quoted.value;
|
|
219
224
|
|
|
220
225
|
for (var i = 0; i < args.length; i++) {
|
|
226
|
+
/*jshint loopfunc:true */
|
|
221
227
|
str = str.replace(/%[sda]/i, function(token) {
|
|
222
228
|
var value = token.match(/s/i) ? args[i].value : args[i].toCSS();
|
|
223
229
|
return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value;
|
|
@@ -227,6 +233,9 @@ tree.functions = {
|
|
|
227
233
|
return new(tree.Quoted)('"' + str + '"', str);
|
|
228
234
|
},
|
|
229
235
|
unit: function (val, unit) {
|
|
236
|
+
if(!(val instanceof tree.Dimension)) {
|
|
237
|
+
throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") };
|
|
238
|
+
}
|
|
230
239
|
return new(tree.Dimension)(val.value, unit ? unit.toCSS() : "");
|
|
231
240
|
},
|
|
232
241
|
convert: function (val, unit) {
|
|
@@ -234,7 +243,7 @@ tree.functions = {
|
|
|
234
243
|
},
|
|
235
244
|
round: function (n, f) {
|
|
236
245
|
var fraction = typeof(f) === "undefined" ? 0 : f.value;
|
|
237
|
-
return
|
|
246
|
+
return _math(function(num) { return num.toFixed(fraction); }, null, n);
|
|
238
247
|
},
|
|
239
248
|
pi: function () {
|
|
240
249
|
return new(tree.Dimension)(Math.PI);
|
|
@@ -252,25 +261,67 @@ tree.functions = {
|
|
|
252
261
|
|
|
253
262
|
return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit);
|
|
254
263
|
},
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
|
|
264
|
+
_minmax: function (isMin, args) {
|
|
265
|
+
args = Array.prototype.slice.call(args);
|
|
266
|
+
switch(args.length) {
|
|
267
|
+
case 0: throw { type: "Argument", message: "one or more arguments required" };
|
|
268
|
+
case 1: return args[0];
|
|
269
|
+
}
|
|
270
|
+
var i, j, current, currentUnified, referenceUnified, unit,
|
|
271
|
+
order = [], // elems only contains original argument values.
|
|
272
|
+
values = {}; // key is the unit.toString() for unified tree.Dimension values,
|
|
273
|
+
// value is the index into the order array.
|
|
274
|
+
for (i = 0; i < args.length; i++) {
|
|
275
|
+
current = args[i];
|
|
276
|
+
if (!(current instanceof tree.Dimension)) {
|
|
277
|
+
order.push(current);
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
currentUnified = current.unify();
|
|
281
|
+
unit = currentUnified.unit.toString();
|
|
282
|
+
j = values[unit];
|
|
283
|
+
if (j === undefined) {
|
|
284
|
+
values[unit] = order.length;
|
|
285
|
+
order.push(current);
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
referenceUnified = order[j].unify();
|
|
289
|
+
if ( isMin && currentUnified.value < referenceUnified.value ||
|
|
290
|
+
!isMin && currentUnified.value > referenceUnified.value) {
|
|
291
|
+
order[j] = current;
|
|
292
|
+
}
|
|
262
293
|
}
|
|
294
|
+
if (order.length == 1) {
|
|
295
|
+
return order[0];
|
|
296
|
+
}
|
|
297
|
+
args = order.map(function (a) { return a.toCSS(this.env); })
|
|
298
|
+
.join(this.env.compress ? "," : ", ");
|
|
299
|
+
return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")");
|
|
300
|
+
},
|
|
301
|
+
min: function () {
|
|
302
|
+
return this._minmax(true, arguments);
|
|
303
|
+
},
|
|
304
|
+
max: function () {
|
|
305
|
+
return this._minmax(false, arguments);
|
|
263
306
|
},
|
|
264
307
|
argb: function (color) {
|
|
265
308
|
return new(tree.Anonymous)(color.toARGB());
|
|
266
|
-
|
|
267
309
|
},
|
|
268
310
|
percentage: function (n) {
|
|
269
311
|
return new(tree.Dimension)(n.value * 100, '%');
|
|
270
312
|
},
|
|
271
313
|
color: function (n) {
|
|
272
314
|
if (n instanceof tree.Quoted) {
|
|
273
|
-
|
|
315
|
+
var colorCandidate = n.value,
|
|
316
|
+
returnColor;
|
|
317
|
+
returnColor = tree.Color.fromKeyword(colorCandidate);
|
|
318
|
+
if (returnColor) {
|
|
319
|
+
return returnColor;
|
|
320
|
+
}
|
|
321
|
+
if (/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/.test(colorCandidate)) {
|
|
322
|
+
return new(tree.Color)(colorCandidate.slice(1));
|
|
323
|
+
}
|
|
324
|
+
throw { type: "Argument", message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF" };
|
|
274
325
|
} else {
|
|
275
326
|
throw { type: "Argument", message: "argument must be a string" };
|
|
276
327
|
}
|
|
@@ -305,75 +356,22 @@ tree.functions = {
|
|
|
305
356
|
_isa: function (n, Type) {
|
|
306
357
|
return (n instanceof Type) ? tree.True : tree.False;
|
|
307
358
|
},
|
|
308
|
-
|
|
309
|
-
/* Blending modes */
|
|
310
|
-
|
|
311
|
-
multiply: function(color1, color2) {
|
|
312
|
-
var r = color1.rgb[0] * color2.rgb[0] / 255;
|
|
313
|
-
var g = color1.rgb[1] * color2.rgb[1] / 255;
|
|
314
|
-
var b = color1.rgb[2] * color2.rgb[2] / 255;
|
|
315
|
-
return this.rgb(r, g, b);
|
|
316
|
-
},
|
|
317
|
-
screen: function(color1, color2) {
|
|
318
|
-
var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255;
|
|
319
|
-
var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255;
|
|
320
|
-
var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255;
|
|
321
|
-
return this.rgb(r, g, b);
|
|
322
|
-
},
|
|
323
|
-
overlay: function(color1, color2) {
|
|
324
|
-
var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255;
|
|
325
|
-
var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255;
|
|
326
|
-
var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255;
|
|
327
|
-
return this.rgb(r, g, b);
|
|
328
|
-
},
|
|
329
|
-
softlight: function(color1, color2) {
|
|
330
|
-
var t = color2.rgb[0] * color1.rgb[0] / 255;
|
|
331
|
-
var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255;
|
|
332
|
-
t = color2.rgb[1] * color1.rgb[1] / 255;
|
|
333
|
-
var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255;
|
|
334
|
-
t = color2.rgb[2] * color1.rgb[2] / 255;
|
|
335
|
-
var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255;
|
|
336
|
-
return this.rgb(r, g, b);
|
|
337
|
-
},
|
|
338
|
-
hardlight: function(color1, color2) {
|
|
339
|
-
var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255;
|
|
340
|
-
var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255;
|
|
341
|
-
var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255;
|
|
342
|
-
return this.rgb(r, g, b);
|
|
343
|
-
},
|
|
344
|
-
difference: function(color1, color2) {
|
|
345
|
-
var r = Math.abs(color1.rgb[0] - color2.rgb[0]);
|
|
346
|
-
var g = Math.abs(color1.rgb[1] - color2.rgb[1]);
|
|
347
|
-
var b = Math.abs(color1.rgb[2] - color2.rgb[2]);
|
|
348
|
-
return this.rgb(r, g, b);
|
|
349
|
-
},
|
|
350
|
-
exclusion: function(color1, color2) {
|
|
351
|
-
var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255;
|
|
352
|
-
var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255;
|
|
353
|
-
var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255;
|
|
354
|
-
return this.rgb(r, g, b);
|
|
355
|
-
},
|
|
356
|
-
average: function(color1, color2) {
|
|
357
|
-
var r = (color1.rgb[0] + color2.rgb[0]) / 2;
|
|
358
|
-
var g = (color1.rgb[1] + color2.rgb[1]) / 2;
|
|
359
|
-
var b = (color1.rgb[2] + color2.rgb[2]) / 2;
|
|
360
|
-
return this.rgb(r, g, b);
|
|
361
|
-
},
|
|
362
|
-
negation: function(color1, color2) {
|
|
363
|
-
var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]);
|
|
364
|
-
var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]);
|
|
365
|
-
var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]);
|
|
366
|
-
return this.rgb(r, g, b);
|
|
367
|
-
},
|
|
368
359
|
tint: function(color, amount) {
|
|
369
360
|
return this.mix(this.rgb(255,255,255), color, amount);
|
|
370
361
|
},
|
|
371
362
|
shade: function(color, amount) {
|
|
372
363
|
return this.mix(this.rgb(0, 0, 0), color, amount);
|
|
373
|
-
},
|
|
364
|
+
},
|
|
374
365
|
extract: function(values, index) {
|
|
375
|
-
index = index.value - 1; // (1-based index)
|
|
376
|
-
|
|
366
|
+
index = index.value - 1; // (1-based index)
|
|
367
|
+
// handle non-array values as an array of length 1
|
|
368
|
+
// return 'undefined' if index is invalid
|
|
369
|
+
return Array.isArray(values.value)
|
|
370
|
+
? values.value[index] : Array(values)[index];
|
|
371
|
+
},
|
|
372
|
+
length: function(values) {
|
|
373
|
+
var n = Array.isArray(values.value) ? values.value.length : 1;
|
|
374
|
+
return new tree.Dimension(n);
|
|
377
375
|
},
|
|
378
376
|
|
|
379
377
|
"data-uri": function(mimetypeNode, filePathNode) {
|
|
@@ -385,8 +383,8 @@ tree.functions = {
|
|
|
385
383
|
var mimetype = mimetypeNode.value;
|
|
386
384
|
var filePath = (filePathNode && filePathNode.value);
|
|
387
385
|
|
|
388
|
-
var fs = require(
|
|
389
|
-
path = require(
|
|
386
|
+
var fs = require('fs'),
|
|
387
|
+
path = require('path'),
|
|
390
388
|
useBase64 = false;
|
|
391
389
|
|
|
392
390
|
if (arguments.length < 2) {
|
|
@@ -415,10 +413,10 @@ tree.functions = {
|
|
|
415
413
|
// use base 64 unless it's an ASCII or UTF-8 format
|
|
416
414
|
var charset = mime.charsets.lookup(mimetype);
|
|
417
415
|
useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
|
|
418
|
-
if (useBase64) mimetype += ';base64';
|
|
416
|
+
if (useBase64) { mimetype += ';base64'; }
|
|
419
417
|
}
|
|
420
418
|
else {
|
|
421
|
-
useBase64 = /;base64$/.test(mimetype)
|
|
419
|
+
useBase64 = /;base64$/.test(mimetype);
|
|
422
420
|
}
|
|
423
421
|
|
|
424
422
|
var buf = fs.readFileSync(filePath);
|
|
@@ -435,17 +433,90 @@ tree.functions = {
|
|
|
435
433
|
}
|
|
436
434
|
|
|
437
435
|
return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env);
|
|
438
|
-
} else if (!this.env.silent) {
|
|
439
|
-
// if explicitly disabled (via --no-ie-compat on CLI, or env.ieCompat === false), merely warn
|
|
440
|
-
console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB);
|
|
441
436
|
}
|
|
442
437
|
}
|
|
443
438
|
|
|
444
439
|
buf = useBase64 ? buf.toString('base64')
|
|
445
440
|
: encodeURIComponent(buf);
|
|
446
441
|
|
|
447
|
-
var uri = "
|
|
442
|
+
var uri = "\"data:" + mimetype + ',' + buf + "\"";
|
|
448
443
|
return new(tree.URL)(new(tree.Anonymous)(uri));
|
|
444
|
+
},
|
|
445
|
+
|
|
446
|
+
"svg-gradient": function(direction) {
|
|
447
|
+
|
|
448
|
+
function throwArgumentDescriptor() {
|
|
449
|
+
throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" };
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (arguments.length < 3) {
|
|
453
|
+
throwArgumentDescriptor();
|
|
454
|
+
}
|
|
455
|
+
var stops = Array.prototype.slice.call(arguments, 1),
|
|
456
|
+
gradientDirectionSvg,
|
|
457
|
+
gradientType = "linear",
|
|
458
|
+
rectangleDimension = 'x="0" y="0" width="1" height="1"',
|
|
459
|
+
useBase64 = true,
|
|
460
|
+
renderEnv = {compress: false},
|
|
461
|
+
returner,
|
|
462
|
+
directionValue = direction.toCSS(renderEnv),
|
|
463
|
+
i, color, position, positionValue, alpha;
|
|
464
|
+
|
|
465
|
+
switch (directionValue) {
|
|
466
|
+
case "to bottom":
|
|
467
|
+
gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"';
|
|
468
|
+
break;
|
|
469
|
+
case "to right":
|
|
470
|
+
gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"';
|
|
471
|
+
break;
|
|
472
|
+
case "to bottom right":
|
|
473
|
+
gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"';
|
|
474
|
+
break;
|
|
475
|
+
case "to top right":
|
|
476
|
+
gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"';
|
|
477
|
+
break;
|
|
478
|
+
case "ellipse":
|
|
479
|
+
case "ellipse at center":
|
|
480
|
+
gradientType = "radial";
|
|
481
|
+
gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"';
|
|
482
|
+
rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
|
|
483
|
+
break;
|
|
484
|
+
default:
|
|
485
|
+
throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" };
|
|
486
|
+
}
|
|
487
|
+
returner = '<?xml version="1.0" ?>' +
|
|
488
|
+
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
|
|
489
|
+
'<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
|
|
490
|
+
|
|
491
|
+
for (i = 0; i < stops.length; i+= 1) {
|
|
492
|
+
if (stops[i].value) {
|
|
493
|
+
color = stops[i].value[0];
|
|
494
|
+
position = stops[i].value[1];
|
|
495
|
+
} else {
|
|
496
|
+
color = stops[i];
|
|
497
|
+
position = undefined;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (!(color instanceof tree.Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof tree.Dimension))) {
|
|
501
|
+
throwArgumentDescriptor();
|
|
502
|
+
}
|
|
503
|
+
positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
|
|
504
|
+
alpha = color.alpha;
|
|
505
|
+
returner += '<stop offset="' + positionValue + '" stop-color="' + color.toRGB() + '"' + (alpha < 1 ? ' stop-opacity="' + alpha + '"' : '') + '/>';
|
|
506
|
+
}
|
|
507
|
+
returner += '</' + gradientType + 'Gradient>' +
|
|
508
|
+
'<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
|
|
509
|
+
|
|
510
|
+
if (useBase64) {
|
|
511
|
+
try {
|
|
512
|
+
returner = require('./encoder').encodeBase64(returner); // TODO browser implementation
|
|
513
|
+
} catch(e) {
|
|
514
|
+
useBase64 = false;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'";
|
|
519
|
+
return new(tree.URL)(new(tree.Anonymous)(returner));
|
|
449
520
|
}
|
|
450
521
|
};
|
|
451
522
|
|
|
@@ -477,22 +548,146 @@ tree._mime = {
|
|
|
477
548
|
}
|
|
478
549
|
};
|
|
479
550
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
551
|
+
// Math
|
|
552
|
+
|
|
553
|
+
var mathFunctions = {
|
|
554
|
+
// name, unit
|
|
555
|
+
ceil: null,
|
|
556
|
+
floor: null,
|
|
557
|
+
sqrt: null,
|
|
558
|
+
abs: null,
|
|
559
|
+
tan: "",
|
|
560
|
+
sin: "",
|
|
561
|
+
cos: "",
|
|
562
|
+
atan: "rad",
|
|
563
|
+
asin: "rad",
|
|
564
|
+
acos: "rad"
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
function _math(fn, unit, n) {
|
|
568
|
+
if (!(n instanceof tree.Dimension)) {
|
|
569
|
+
throw { type: "Argument", message: "argument must be a number" };
|
|
570
|
+
}
|
|
571
|
+
if (unit == null) {
|
|
572
|
+
unit = n.unit;
|
|
573
|
+
} else {
|
|
574
|
+
n = n.unify();
|
|
575
|
+
}
|
|
576
|
+
return new(tree.Dimension)(fn(parseFloat(n.value)), unit);
|
|
577
|
+
}
|
|
491
578
|
|
|
492
|
-
|
|
493
|
-
|
|
579
|
+
// ~ End of Math
|
|
580
|
+
|
|
581
|
+
// Color Blending
|
|
582
|
+
// ref: http://www.w3.org/TR/compositing-1
|
|
583
|
+
|
|
584
|
+
function colorBlend(mode, color1, color2) {
|
|
585
|
+
var ab = color1.alpha, cb, // backdrop
|
|
586
|
+
as = color2.alpha, cs, // source
|
|
587
|
+
ar, cr, r = []; // result
|
|
588
|
+
|
|
589
|
+
ar = as + ab * (1 - as);
|
|
590
|
+
for (var i = 0; i < 3; i++) {
|
|
591
|
+
cb = color1.rgb[i] / 255;
|
|
592
|
+
cs = color2.rgb[i] / 255;
|
|
593
|
+
cr = mode(cb, cs);
|
|
594
|
+
if (ar) {
|
|
595
|
+
cr = (as * cs + ab * (cb
|
|
596
|
+
- as * (cb + cs - cr))) / ar;
|
|
597
|
+
}
|
|
598
|
+
r[i] = cr * 255;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
return new(tree.Color)(r, ar);
|
|
494
602
|
}
|
|
495
603
|
|
|
604
|
+
var colorBlendMode = {
|
|
605
|
+
multiply: function(cb, cs) {
|
|
606
|
+
return cb * cs;
|
|
607
|
+
},
|
|
608
|
+
screen: function(cb, cs) {
|
|
609
|
+
return cb + cs - cb * cs;
|
|
610
|
+
},
|
|
611
|
+
overlay: function(cb, cs) {
|
|
612
|
+
cb *= 2;
|
|
613
|
+
return (cb <= 1)
|
|
614
|
+
? colorBlendMode.multiply(cb, cs)
|
|
615
|
+
: colorBlendMode.screen(cb - 1, cs);
|
|
616
|
+
},
|
|
617
|
+
softlight: function(cb, cs) {
|
|
618
|
+
var d = 1, e = cb;
|
|
619
|
+
if (cs > 0.5) {
|
|
620
|
+
e = 1;
|
|
621
|
+
d = (cb > 0.25) ? Math.sqrt(cb)
|
|
622
|
+
: ((16 * cb - 12) * cb + 4) * cb;
|
|
623
|
+
}
|
|
624
|
+
return cb - (1 - 2 * cs) * e * (d - cb);
|
|
625
|
+
},
|
|
626
|
+
hardlight: function(cb, cs) {
|
|
627
|
+
return colorBlendMode.overlay(cs, cb);
|
|
628
|
+
},
|
|
629
|
+
difference: function(cb, cs) {
|
|
630
|
+
return Math.abs(cb - cs);
|
|
631
|
+
},
|
|
632
|
+
exclusion: function(cb, cs) {
|
|
633
|
+
return cb + cs - 2 * cb * cs;
|
|
634
|
+
},
|
|
635
|
+
|
|
636
|
+
// non-w3c functions:
|
|
637
|
+
average: function(cb, cs) {
|
|
638
|
+
return (cb + cs) / 2;
|
|
639
|
+
},
|
|
640
|
+
negation: function(cb, cs) {
|
|
641
|
+
return 1 - Math.abs(cb + cs - 1);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
// ~ End of Color Blending
|
|
646
|
+
|
|
647
|
+
tree.defaultFunc = {
|
|
648
|
+
eval: function () {
|
|
649
|
+
var v = this.value_, e = this.error_;
|
|
650
|
+
if (e) {
|
|
651
|
+
throw e;
|
|
652
|
+
}
|
|
653
|
+
if (v != null) {
|
|
654
|
+
return v ? tree.True : tree.False;
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
value: function (v) {
|
|
658
|
+
this.value_ = v;
|
|
659
|
+
},
|
|
660
|
+
error: function (e) {
|
|
661
|
+
this.error_ = e;
|
|
662
|
+
},
|
|
663
|
+
reset: function () {
|
|
664
|
+
this.value_ = this.error_ = null;
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
function initFunctions() {
|
|
669
|
+
var f, tf = tree.functions;
|
|
670
|
+
|
|
671
|
+
// math
|
|
672
|
+
for (f in mathFunctions) {
|
|
673
|
+
if (mathFunctions.hasOwnProperty(f)) {
|
|
674
|
+
tf[f] = _math.bind(null, Math[f], mathFunctions[f]);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// color blending
|
|
679
|
+
for (f in colorBlendMode) {
|
|
680
|
+
if (colorBlendMode.hasOwnProperty(f)) {
|
|
681
|
+
tf[f] = colorBlend.bind(null, colorBlendMode[f]);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// default
|
|
686
|
+
f = tree.defaultFunc;
|
|
687
|
+
tf["default"] = f.eval.bind(f);
|
|
688
|
+
|
|
689
|
+
} initFunctions();
|
|
690
|
+
|
|
496
691
|
function hsla(color) {
|
|
497
692
|
return tree.functions.hsla(color.h, color.s, color.l, color.a);
|
|
498
693
|
}
|
|
@@ -522,6 +717,16 @@ function clamp(val) {
|
|
|
522
717
|
return Math.min(1, Math.max(0, val));
|
|
523
718
|
}
|
|
524
719
|
|
|
720
|
+
tree.fround = function(env, value) {
|
|
721
|
+
var p;
|
|
722
|
+
if (env && (env.numPrecision != null)) {
|
|
723
|
+
p = Math.pow(10, env.numPrecision);
|
|
724
|
+
return Math.round(value * p) / p;
|
|
725
|
+
} else {
|
|
726
|
+
return value;
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
|
|
525
730
|
tree.functionCall = function(env, currentFileInfo) {
|
|
526
731
|
this.env = env;
|
|
527
732
|
this.currentFileInfo = currentFileInfo;
|