less 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|