flint-gs 2.1.1 → 2.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/lib/flint/version.rb +1 -1
  3. data/stylesheets/flint/functions/_functions.scss +1 -1
  4. metadata +2 -158
  5. data/tests/bootcamp/CHANGELOG.md +0 -70
  6. data/tests/bootcamp/CONTRIBUTING.md +0 -72
  7. data/tests/bootcamp/Gruntfile.coffee +0 -34
  8. data/tests/bootcamp/LICENSE.md +0 -7
  9. data/tests/bootcamp/README.md +0 -52
  10. data/tests/bootcamp/bower.json +0 -15
  11. data/tests/bootcamp/dist/_bootcamp.scss +0 -46
  12. data/tests/bootcamp/dist/bootcamp.coffee +0 -101
  13. data/tests/bootcamp/dist/core/functions/_actual.scss +0 -3
  14. data/tests/bootcamp/dist/core/functions/_error.scss +0 -29
  15. data/tests/bootcamp/dist/core/functions/_expect.scss +0 -6
  16. data/tests/bootcamp/dist/core/functions/_not-to.scss +0 -5
  17. data/tests/bootcamp/dist/core/functions/_should.scss +0 -6
  18. data/tests/bootcamp/dist/core/functions/_to.scss +0 -5
  19. data/tests/bootcamp/dist/core/mixins/_describe.scss +0 -31
  20. data/tests/bootcamp/dist/core/mixins/_it.scss +0 -31
  21. data/tests/bootcamp/dist/core/mixins/_runner.scss +0 -28
  22. data/tests/bootcamp/dist/core/mixins/_should.scss +0 -46
  23. data/tests/bootcamp/dist/core/mixins/_xdescribe.scss +0 -9
  24. data/tests/bootcamp/dist/core/mixins/_xit.scss +0 -9
  25. data/tests/bootcamp/dist/core/variables/_helpers.scss +0 -5
  26. data/tests/bootcamp/dist/core/variables/_settings.scss +0 -2
  27. data/tests/bootcamp/dist/core/variables/_should.scss +0 -6
  28. data/tests/bootcamp/dist/core/variables/_trackers.scss +0 -6
  29. data/tests/bootcamp/dist/lib/_sassyjson.scss +0 -1075
  30. data/tests/bootcamp/dist/matchers/_be.scss +0 -3
  31. data/tests/bootcamp/dist/matchers/_equal.scss +0 -3
  32. data/tests/bootcamp/dist/matchers/lists/_be-empty.scss +0 -3
  33. data/tests/bootcamp/dist/matchers/lists/_be-longer-than.scss +0 -3
  34. data/tests/bootcamp/dist/matchers/lists/_be-shorter-than.scss +0 -3
  35. data/tests/bootcamp/dist/matchers/lists/_contain.scss +0 -3
  36. data/tests/bootcamp/dist/matchers/lists/_deep-contain.scss +0 -3
  37. data/tests/bootcamp/dist/matchers/lists/_deep-equal.scss +0 -47
  38. data/tests/bootcamp/dist/matchers/lists/_have-length-of.scss +0 -3
  39. data/tests/bootcamp/dist/matchers/numbers/_be-close-to.scss +0 -12
  40. data/tests/bootcamp/dist/matchers/numbers/_be-greater-than.scss +0 -12
  41. data/tests/bootcamp/dist/matchers/numbers/_be-less-than.scss +0 -12
  42. data/tests/bootcamp/dist/matchers/types/_be-falsy.scss +0 -3
  43. data/tests/bootcamp/dist/matchers/types/_be-null.scss +0 -3
  44. data/tests/bootcamp/dist/matchers/types/_be-truthy.scss +0 -3
  45. data/tests/bootcamp/dist/matchers/types/_have-type-of.scss +0 -3
  46. data/tests/bootcamp/dist/utils/_contain.scss +0 -15
  47. data/tests/bootcamp/dist/utils/_equal.scss +0 -23
  48. data/tests/bootcamp/dist/utils/_list-join.scss +0 -35
  49. data/tests/bootcamp/dist/utils/_power.scss +0 -15
  50. data/tests/bootcamp/package.json +0 -63
  51. data/tests/bootcamp/tasks/bootcamp.coffee +0 -83
  52. data/tests/bootcamp/test/core/functions/_actual.scss +0 -10
  53. data/tests/bootcamp/test/core/functions/_expect.scss +0 -6
  54. data/tests/bootcamp/test/core/functions/_not-to.scss +0 -5
  55. data/tests/bootcamp/test/core/functions/_should.scss +0 -10
  56. data/tests/bootcamp/test/core/functions/_to.scss +0 -5
  57. data/tests/bootcamp/test/core/mixins/_describe.scss +0 -11
  58. data/tests/bootcamp/test/core/mixins/_it.scss +0 -5
  59. data/tests/bootcamp/test/core/mixins/_should.scss +0 -5
  60. data/tests/bootcamp/test/core/mixins/_xdescribe.scss +0 -28
  61. data/tests/bootcamp/test/core/mixins/_xit.scss +0 -12
  62. data/tests/bootcamp/test/matchers/_be.scss +0 -90
  63. data/tests/bootcamp/test/matchers/_equal.scss +0 -33
  64. data/tests/bootcamp/test/matchers/lists/_be-empty.scss +0 -12
  65. data/tests/bootcamp/test/matchers/lists/_be-longer-than.scss +0 -29
  66. data/tests/bootcamp/test/matchers/lists/_be-shorter-than.scss +0 -29
  67. data/tests/bootcamp/test/matchers/lists/_contain.scss +0 -39
  68. data/tests/bootcamp/test/matchers/lists/_deep-contain.scss +0 -51
  69. data/tests/bootcamp/test/matchers/lists/_deep-equal.scss +0 -151
  70. data/tests/bootcamp/test/matchers/lists/_have-length-of.scss +0 -31
  71. data/tests/bootcamp/test/matchers/numbers/_be-close-to.scss +0 -24
  72. data/tests/bootcamp/test/matchers/numbers/_be-greater-than.scss +0 -16
  73. data/tests/bootcamp/test/matchers/numbers/_be-less-than.scss +0 -16
  74. data/tests/bootcamp/test/matchers/types/_be-falsy.scss +0 -14
  75. data/tests/bootcamp/test/matchers/types/_be-null.scss +0 -13
  76. data/tests/bootcamp/test/matchers/types/_be-truthy.scss +0 -13
  77. data/tests/bootcamp/test/matchers/types/_have-type-of.scss +0 -17
  78. data/tests/bootcamp/test/specs.scss +0 -45
  79. data/tests/bootcamp/test/utils/_contain.scss +0 -41
  80. data/tests/bootcamp/test/utils/_equal.scss +0 -79
  81. data/tests/bootcamp/test/utils/_list-join.scss +0 -39
  82. data/tests/bootcamp/test/utils/_power.scss +0 -13
@@ -1,15 +0,0 @@
1
- {
2
- "name": "bootcamp",
3
- "version": "1.1.7",
4
- "homepage": "http://github.com/thejameskyle/bootcamp",
5
- "main": "dist/bootcamp.scss",
6
- "ignore": [
7
- "test",
8
- ".editorconfig",
9
- ".gitattributes",
10
- ".gitignore",
11
- ".jshintrc",
12
- ".travis.yml",
13
- "Gruntfile.coffee"
14
- ]
15
- }
@@ -1,46 +0,0 @@
1
- @import "lib/sassyjson";
2
-
3
- @import "core/variables/settings";
4
-
5
- @import "core/variables/helpers";
6
- @import "core/variables/should";
7
- @import "core/variables/trackers";
8
-
9
- @import "core/mixins/describe";
10
- @import "core/mixins/it";
11
- @import "core/mixins/runner";
12
- @import "core/mixins/should";
13
- @import "core/mixins/xdescribe";
14
- @import "core/mixins/xit";
15
-
16
- @import "core/functions/actual";
17
- @import "core/functions/error";
18
- @import "core/functions/expect";
19
- @import "core/functions/not-to";
20
- @import "core/functions/should";
21
- @import "core/functions/to";
22
-
23
- @import "utils/contain";
24
- @import "utils/equal";
25
- @import "utils/list-join";
26
- @import "utils/power";
27
-
28
- @import "matchers/be";
29
- @import "matchers/equal";
30
-
31
- @import "matchers/lists/be-empty";
32
- @import "matchers/lists/be-longer-than";
33
- @import "matchers/lists/be-shorter-than";
34
- @import "matchers/lists/contain";
35
- @import "matchers/lists/deep-contain";
36
- @import "matchers/lists/deep-equal";
37
- @import "matchers/lists/have-length-of";
38
-
39
- @import "matchers/numbers/be-close-to";
40
- @import "matchers/numbers/be-greater-than";
41
- @import "matchers/numbers/be-less-than";
42
-
43
- @import "matchers/types/be-falsy";
44
- @import "matchers/types/be-null";
45
- @import "matchers/types/be-truthy";
46
- @import "matchers/types/have-type-of";
@@ -1,101 +0,0 @@
1
- 'use strict'
2
-
3
- fs = require 'fs'
4
-
5
- module.exports =
6
- test: (filepath) ->
7
- error = null
8
-
9
- file = fs.readFileSync filepath, 'utf8'
10
-
11
- ###
12
- # Get Camp
13
- ###
14
-
15
- camp = file.match /\/\* >> Bootcamp >> \*\/((.|\n|\r)*)\/\* << Bootcamp << \*\//
16
-
17
- unless camp?
18
- return incomplete: true, error: 'No Test Suite Found'
19
- else
20
- camp = camp[1]
21
-
22
- ###
23
- # Get Results
24
- ###
25
-
26
- results = camp.match /Test Results \{((.|\n|\r)*)\}/
27
-
28
- unless results?
29
- return incomplete: true, error: 'No Test Results Found'
30
- else
31
- results = results[1]
32
-
33
- ###
34
- # Get Specs
35
- ###
36
-
37
- specs = camp.replace( results, '' ).replace( /Test Results \{\}|\{|\}|;|:/g, '' )
38
-
39
- ###
40
- # method: getProperty
41
- ###
42
-
43
- getProperty = (property, force) ->
44
- values = results.match new RegExp property + ': ((.|\n|\r)*?);', 'g'
45
- property = []
46
-
47
- if force and !values? then return property
48
-
49
- unless values?
50
- error = incomplete: true, error: "No #{property} Found"
51
- return false
52
- else
53
- for value in values
54
- value = value.replace(/;/, '')
55
- value = value.replace(/(.*:)/, '')
56
- value = value.trim()
57
- value = parseInt value unless isNaN value
58
- property.push value
59
-
60
- return property
61
-
62
- ###
63
- # Get Properties
64
- ###
65
-
66
- success = getProperty('Success').indexOf('true') > -1
67
- stats = getProperty 'Stats'
68
- tests = getProperty 'Tests'
69
- asserts = getProperty 'Asserts'
70
- passed = getProperty 'Passed'
71
- failed = getProperty 'Failed'
72
- skipped = getProperty 'Skipped'
73
- errors = getProperty 'Error', true
74
-
75
- ###
76
- # Return Any Errors
77
- ###
78
-
79
- return error if error
80
-
81
- ###
82
- # Return Final Values
83
- ###
84
-
85
- return {
86
- camp: camp
87
- results: results
88
- specs: specs
89
-
90
- success: success
91
- stats: stats
92
- details: "#{tests} Tests, #{asserts} assertions, #{failed} failures, #{skipped} skipped"
93
-
94
- tests: tests
95
- asserts: asserts
96
- passed: passed
97
- failed: failed
98
- skipped: skipped
99
-
100
- errors: errors
101
- }
@@ -1,3 +0,0 @@
1
- @function actual() {
2
- @return $bc-actual;
3
- }
@@ -1,29 +0,0 @@
1
- @function error($type, $message) {
2
- $title: null;
3
-
4
- @if $type == "type" {
5
- $title: "TYPE ERROR";
6
- }
7
-
8
- @else if $type == "warn" {
9
- $title: "WARNING"
10
- }
11
-
12
- @else if $type == "dep" {
13
- $title: "DEPRECATED"
14
- }
15
-
16
- @else if $type == "fatal" {
17
- $bc-error: true !global;
18
- $title: "FATAL ERROR";
19
- }
20
-
21
- @else {
22
- $bc-error: true !global;
23
- $title: "ERROR";
24
- }
25
-
26
- $bc-error-text: "!#{$title}! #{$message}." !global;
27
-
28
- @return false;
29
- }
@@ -1,6 +0,0 @@
1
- @function expect($this) {
2
- $bc-actual: $this !global;
3
- $bc-actual-text: "Expected" !global;
4
-
5
- @return null;
6
- }
@@ -1,5 +0,0 @@
1
- @function not-to($this) {
2
- $bc-expect-text: "not to " + $bc-expect-text !global;
3
-
4
- @return not $this;
5
- }
@@ -1,6 +0,0 @@
1
- @function should($be, $something, $when) {
2
- $bc-expect: $something !global;
3
- $bc-expect-text: $be !global;
4
-
5
- @return $when;
6
- }
@@ -1,5 +0,0 @@
1
- @function to($this) {
2
- $bc-expect-text: "to " + $bc-expect-text !global;
3
-
4
- @return $this;
5
- }
@@ -1,31 +0,0 @@
1
- @mixin describe($bc-describe-new) {
2
- @if not $bc-skipping {
3
- $bc-describe-old: $bc-describe !global !default;
4
- $bc-describe-old: append($bc-describe-old, $bc-describe-new) !global;
5
-
6
- @if $bc-describe-depth > 0 {
7
- $bc-describe: bc-util-list-join($bc-describe-old, " ", 2) !global;
8
- } @else {
9
- $bc-describe: "#{$bc-describe-new}" !global;
10
- }
11
-
12
- $bc-describe-depth: $bc-describe-depth + 1 !global;
13
-
14
- @content;
15
-
16
- $bc-describe: "" !global;
17
-
18
- $_tmp: ();
19
-
20
- @for $i from 1 through $bc-describe-depth {
21
- $_tmp: append($_tmp, nth($bc-describe-old, $i));
22
- }
23
-
24
- $bc-describe-old: $_tmp !global;
25
- $bc-describe: nth($bc-describe-old, 1) !global;
26
- $bc-describe-depth: $bc-describe-depth - 1 !global;
27
-
28
- } @else {
29
- @content;
30
- }
31
- }
@@ -1,31 +0,0 @@
1
- @mixin it($statement) {
2
- $bc-total: $bc-total + 1 !global;
3
-
4
- @if not $bc-skipping {
5
- $bc-passing: true !global;
6
-
7
- #{$bc-describe} #{$statement} {
8
- @content;
9
-
10
- @if $bc-passing {
11
- @if $bc-setting-verbose {
12
- Test: Passed;
13
- }
14
-
15
- $bc-stats: "#{$bc-stats} ✔" !global;
16
- $bc-passed: $bc-passed + 1 !global;
17
- }
18
-
19
- @else {
20
- Test: Failed;
21
-
22
- $bc-stats: "#{$bc-stats} ✗" !global;
23
- $bc-failed: $bc-failed + 1 !global;
24
- }
25
- }
26
-
27
- $bc-passing: null !global;
28
- } @else {
29
- $bc-skipped: $bc-skipped + 1 !global;
30
- }
31
- }
@@ -1,28 +0,0 @@
1
- @mixin runner-start {
2
- /* >> Bootcamp >> */
3
- }
4
-
5
- @mixin runner-end {
6
-
7
- @if $bc-total == 0 {
8
- $bc-stats: "No tests were found" !global;
9
- }
10
-
11
- Test Results {
12
- Success: $bc-failed == 0;
13
- Stats: #{ $bc-stats };
14
- Tests: #{ $bc-total };
15
- Asserts: #{ $bc-asserts };
16
- Passed: #{ $bc-passed };
17
- Failed: #{ $bc-failed };
18
- Skipped: #{ $bc-skipped };
19
-
20
- @if $bc-errors != () and $bc-setting-warnings {
21
- @each $error in $bc-errors {
22
- Error: #{$error};
23
- }
24
- }
25
- }
26
-
27
- /* << Bootcamp << */
28
- }
@@ -1,46 +0,0 @@
1
- @mixin should($actual, $expect) {
2
- @if $bc-error {
3
- $expect: false !global;
4
- }
5
-
6
- $bc-asserts: $bc-asserts + 1 !global;
7
-
8
- $bc-actual: json-encode($bc-actual) !global;
9
- $bc-expect: json-encode($bc-expect) !global;
10
-
11
- @if not $expect {
12
- $bc-passing: false !global;
13
- }
14
-
15
- @if not $expect or $bc-setting-verbose {
16
- $status: " ✗";
17
-
18
- @if $bc-passing {
19
- $status: " ✔";
20
- }
21
-
22
- @if $bc-error-text {
23
- #{$status}:
24
- #{$bc-error-text}
25
- #{$bc-actual-text} #{$bc-actual}
26
- #{$bc-expect-text} #{$bc-expect};
27
- } @else {
28
- #{$status}:
29
- #{$bc-actual-text} #{$bc-actual}
30
- #{$bc-expect-text} #{$bc-expect};
31
- }
32
- }
33
-
34
- @if $bc-error-text {
35
- @if not index($bc-errors, $bc-error-text) {
36
- $bc-errors: append($bc-errors, $bc-error-text) !global;
37
- }
38
- }
39
-
40
- $bc-actual-text: null !global;
41
- $bc-expect-text: null !global;
42
- $bc-actual: null !global;
43
- $bc-expect: null !global;
44
- $bc-error-text: null !global;
45
- $bc-error: false !global;
46
- }
@@ -1,9 +0,0 @@
1
- @mixin xdescribe($statement) {
2
- $bc-skipping: true !global;
3
-
4
- @include describe($statement) {
5
- @content;
6
- }
7
-
8
- $bc-skipping: false !global;
9
- }
@@ -1,9 +0,0 @@
1
- @mixin xit($statement) {
2
- $bc-skipping: true !global;
3
-
4
- @include it($statement) {
5
- @content;
6
- }
7
-
8
- $bc-skipping: false !global;
9
- }
@@ -1,5 +0,0 @@
1
- $bc-describe: "It";
2
- $bc-describe-depth: 0;
3
- $bc-passing: null;
4
- $bc-skipping: false;
5
- $bc-errors: ();
@@ -1,2 +0,0 @@
1
- $bc-setting-verbose: false !default;
2
- $bc-setting-warnings: false !default;
@@ -1,6 +0,0 @@
1
- $bc-actual: null;
2
- $bc-actual-text: null;
3
- $bc-expect-text: null;
4
- $bc-expect: null;
5
- $bc-error-text: null;
6
- $bc-error: false;
@@ -1,6 +0,0 @@
1
- $bc-total: 0;
2
- $bc-asserts: 0;
3
- $bc-passed: 0;
4
- $bc-failed: 0;
5
- $bc-skipped: 0;
6
- $bc-stats: "";
@@ -1,1075 +0,0 @@
1
- /*! sassyjson - v1.1.8 - 2014-06-01 */
2
- // Logs an error at `$pointer` with `$string` message
3
- // --------------------------------------------------------------------------------
4
- // @param [string] $string: error message
5
- // @param [number] $pointer: pointer position
6
- // --------------------------------------------------------------------------------
7
- // @return [list] (pointer, false)
8
-
9
- @function _throw($string, $pointer) {
10
- @warn "ERROR::#{$pointer}::#{$string}";
11
- @return $pointer, false;
12
- }
13
-
14
- // Delay parsing to type-specific function
15
- // according to found character
16
- // --------------------------------------------------------------------------------
17
- // @param [string] $source: JSON complete source
18
- // @param [number] $pointer: current pointer
19
- // --------------------------------------------------------------------------------
20
- // @throw "Unexpected token $token."
21
- // @throw "Empty JSON string."
22
- // --------------------------------------------------------------------------------
23
- // @return [list|false] (new pointer, parsed value)
24
-
25
- @function _json-decode--value($source, $pointer) {
26
- $length: str-length($source);
27
-
28
- @while $pointer <= $length {
29
- $token: str-slice($source, $pointer, $pointer);
30
- $pointer: $pointer + 1;
31
-
32
- @if $token == '{' {
33
- @return _json-decode--map($source, $pointer);
34
- }
35
- @else if $token == '[' {
36
- @return _json-decode--list($source, $pointer);
37
- }
38
- @else if $token == 't' {
39
- @return _json-decode--true($source, $pointer);
40
- }
41
- @else if $token == 'f' {
42
- @return _json-decode--false($source, $pointer);
43
- }
44
- @else if $token == '"' {
45
- @return _json-decode--string($source, $pointer);
46
- }
47
- @else if $token == 'n' {
48
- @return _json-decode--null($source, $pointer);
49
- }
50
- @else if index('1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '-' '.', $token) {
51
- @return _json-decode--number($source, $pointer);
52
- }
53
- @else if $token == ' ' or $token == " " {
54
- // @continue;
55
- }
56
- @else {
57
- @return _throw("Unexpected token `" + $token + "`.", $pointer);
58
- }
59
- }
60
-
61
- @return _throw("Empty JSON string.", $pointer);
62
- }
63
-
64
- // Move pointer to position of token
65
- // --------------------------------------------------------------------------------
66
- // @param [string] $source: JSON complete source
67
- // @param [number] $pointer: current pointer
68
- // @param [string] $token: token to reach
69
- // --------------------------------------------------------------------------------
70
- // @throw "Expected $token; found {x}."
71
- // @throw "Expected $token but reached end of stream."
72
- // --------------------------------------------------------------------------------
73
- // @return [number|false] new pointer
74
-
75
- @function _consume($source, $pointer, $token) {
76
- $length: str-length($source);
77
-
78
- @while $pointer <= $length {
79
- $char: str-slice($source, $pointer, $pointer);
80
- $pointer: $pointer + 1;
81
-
82
- @if $char == $token {
83
- @return $pointer;
84
- }
85
-
86
- @else if $char == " " or $char == " " {
87
- // @continue;
88
- }
89
-
90
- @else {
91
- @return _throw("Expected `" + $token + "; ` found `" + $char + "`.", $pointer);
92
- }
93
- }
94
-
95
- @return _throw("Expected `" + $token + "` but reached end of stream.", $pointer);
96
- }
97
-
98
- // Will find the first non escaped quote in a JSON String
99
- // --------------------------------------------------------------------------------
100
- // @param [string] $string: to search in
101
- // --------------------------------------------------------------------------------
102
- // @return [number] position of the first non escaped quote
103
-
104
- @function _find-ending-quote($string) {
105
- $backslash: str-slice('\\', 1, 1); // Dirty hack to have a single backslash
106
- $escaped-chars: '"\/bfnrtu'; // Characters that can be escaped in JSON
107
- $hexadecimal-chars: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' 'a' 'b' 'c' 'd' 'e' 'f';
108
-
109
- $pos: 1;
110
- $length: str-length($string);
111
- $backslash-found: false;
112
-
113
- @while $pos <= $length {
114
- $char: to-lower-case(str-slice($string, $pos, $pos));
115
-
116
- // Previous char was a backslash
117
- @if $backslash-found {
118
-
119
- // Special case, the 'u' character
120
- @if $char == 'u' {
121
- // Next 4 characters must be hexadecimal
122
- @if not index($hexadecimal-chars, str-slice($string, $pos + 1, $pos + 1)) or
123
- not index($hexadecimal-chars, str-slice($string, $pos + 2, $pos + 2)) or
124
- not index($hexadecimal-chars, str-slice($string, $pos + 3, $pos + 3)) or
125
- not index($hexadecimal-chars, str-slice($string, $pos + 4, $pos + 4)) {
126
- @return 0;
127
- }
128
-
129
- $pos: $pos + 4;
130
- }
131
-
132
- // Invalid character escaped
133
- @else if not str-index($escaped-chars, $char) {
134
- @return 0;
135
- }
136
-
137
- $backslash-found: false;
138
- }
139
-
140
- @else if $char == $backslash {
141
- $backslash-found: true;
142
- }
143
-
144
- // Unescaped quote found
145
- @else if $char == '"' {
146
- @return $pos;
147
- }
148
-
149
- $pos: $pos + 1;
150
- }
151
-
152
- // No end of string found
153
- @return 0;
154
- }
155
-
156
- // Strip special carriage return characters
157
- // --------------------------------------------------------------------------------
158
- // @param [string] $string: string to parse
159
- // @param [string] $char: char to strip
160
- // --------------------------------------------------------------------------------
161
- // @return [string] new string
162
-
163
- @function _strip-token($string, $token, $replace) {
164
-
165
- @while str-index($string, $token) and str-index($string, $token) > 0 {
166
- $index: str-index($string, $token);
167
- $string: str-slice($string, 1, $index - 1) + $replace + str-slice($string, $index + str-length($token));
168
- }
169
-
170
- @return $string;
171
- }
172
-
173
- // Parses a JSON encoded string to see if it's a CSS length
174
- // --------------------------------------------------------------------------------
175
- // @param [string] $string: JSON string
176
- // --------------------------------------------------------------------------------
177
- // @return [number|string] string or number, depending on the match
178
-
179
- @function _length($string) {
180
- @if type-of($string) == number {
181
- @return $string;
182
- }
183
-
184
- $strings: 'px' 'cm' 'mm' '%' 'ch' 'pica' 'in' 'em' 'rem' 'pt' 'pc' 'ex' 'vw' 'vh' 'vmin' 'vmax';
185
- $units: 1px 1cm 1mm 1% 1ch 1pica 1in 1em 1rem 1pt 1pc 1ex 1vw 1vh 1vmin 1vmax;
186
- $number: "";
187
- $unit: "";
188
-
189
- @for $i from 1 through str-length($string) {
190
- $c: str-slice($string, $i, $i);
191
- @if $c == ' ' or $c == " " {
192
- @if $number != "" {
193
- @return $string;
194
- }
195
- }
196
- @else if index('0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '-' '.', $c) {
197
- $number: $number + $c;
198
- }
199
- @else {
200
- @if $number == "" {
201
- @return $string;
202
- }
203
- $unit: $unit + $c;
204
- }
205
- }
206
-
207
- $number: nth(_json-decode--number($number, 2), 2);
208
- $index: index($strings, to-lower-case($unit));
209
-
210
- @if $index and $index > 0 {
211
- @return $number * nth($units, $index);
212
- }
213
-
214
- @return $string;
215
- }
216
-
217
- // Parses a JSON encoded string to see if it's a CSS color
218
- // --------------------------------------------------------------------------------
219
- // @param [string] $string: JSON string
220
- // --------------------------------------------------------------------------------
221
- // @return [color|string] string or number, depending on the match
222
-
223
- @function _color($string) {
224
- @if type-of($string) == color {
225
- @return $string;
226
- }
227
-
228
- $string-lower: to-lower-case($string);
229
- $colors: transparent black silver gray white maroon red purple fuchsia green lime olive yellow navy blue teal aqua aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white whitesmoke yellow yellowgreen;
230
- $keywords: ();
231
-
232
- // Filling $keywords with stringified color keywords
233
- @each $color in $colors {
234
- $keywords: append($keywords, $color + "");
235
- }
236
-
237
- // Deal with inherit keyword
238
- @if $string-lower == "inherit" {
239
- @return unquote($string);
240
- }
241
-
242
- // Deal with color keywords
243
- @if index($keywords, $string-lower) {
244
- @return nth($colors, index($keywords, $string-lower));
245
- }
246
-
247
- // Deal with hexadecimal triplets
248
- @else if str-slice($string-lower, 1, 1) == '#' {
249
- @return _from-hex($string);
250
- }
251
-
252
- // Deal with rgb(a) colors
253
- @else if str-slice($string-lower, 1, 3) == 'rgb' {
254
- @return _from-rgb($string);
255
- }
256
-
257
- // Deal with hsl(a) colors
258
- @else if str-slice($string-lower, 1, 3) == 'hsl' {
259
- @return _from-hsl($string);
260
- }
261
-
262
- // Return string
263
- @else {
264
- @return $string;
265
- }
266
- }
267
-
268
- // Cast a stringified number / stringified percentage into number type
269
- // --------------------------------------------------------------------------------
270
- // @param [string] $string: JSON string
271
- // --------------------------------------------------------------------------------
272
- // @return [number] unitless number or percentage
273
-
274
- @function _get-color-value($string) {
275
- $first: str-slice($string, 1, 1);
276
-
277
- // Pad <1 values with a leading 0
278
- @if $first == '.' {
279
- $string: '0' + $string;
280
- }
281
-
282
- $last: str-slice($string, -1, -1);
283
-
284
- @return if(
285
- $last == '%',
286
- nth(_json-decode--number(str-slice($string, 1, -2), 2), 2) * 1%,
287
- nth(_json-decode--number($string, 2), 2)
288
- );
289
- }
290
-
291
- // Cast a JSON encoded string into a hsl(a) color
292
- // --------------------------------------------------------------------------------
293
- // @param [string] $string: JSON string
294
- // --------------------------------------------------------------------------------
295
- // @return [color|string] string or hsl(a) color, depending on the match
296
-
297
- @function _from-hsl($string) {
298
- $frags: ();
299
- $string-lower: to-lower-case($string);
300
- $is-alpha: str-slice($string-lower, 4, 4) == 'a';
301
- $length: str-length($string);
302
- $start: str-index($string, "(");
303
-
304
- @for $i from $start through $length {
305
- $token: str-slice($string-lower, $i, $i);
306
- @if $token == ' ' or $token == " " {
307
- // @continue;
308
- }
309
- @else if $token == '(' or $token == ',' {
310
- $frags: append($frags, "");
311
- }
312
- @else if $token == ')' {
313
- @if length($frags) != if($is-alpha, 4, 3) { @return $string; } // Parsing error
314
- $hue: _get-color-value(nth($frags, 1));
315
- $saturation: _get-color-value(nth($frags, 2));
316
- $lightness: _get-color-value(nth($frags, 3));
317
-
318
- @if not $hue or not $saturation or not $lightness {
319
- @return $string;
320
- }
321
-
322
- @if $is-alpha {
323
- @if length($frags) != 4 { @return $string; } // No alpha channel found
324
- $alpha: _get-color-value(nth($frags, 4));
325
- @if not $alpha { @return $string; } // Error parsing alpha channel
326
- @return hsla($hue, $saturation, $lightness, $alpha);
327
- }
328
-
329
- @return hsl($hue, $saturation, $lightness);
330
- }
331
- @else {
332
- $frags: set-nth($frags, length($frags), nth($frags, length($frags)) + $token);
333
- }
334
- }
335
-
336
- @return $string;
337
- }
338
-
339
- // Cast a JSON encoded string into a rgb(a) color
340
- // --------------------------------------------------------------------------------
341
- // @param [string] $string: JSON string
342
- // --------------------------------------------------------------------------------
343
- // @return [color|string] string or rgb(a) color depending on the match
344
-
345
- @function _from-rgb($string) {
346
- $string-lower: to-lower-case($string);
347
- $frags: ();
348
- $is-alpha: str-slice($string-lower, 4, 4) == 'a';
349
- $start: str-index($string, "(");
350
- $length: str-length($string);
351
-
352
- @for $i from $start through $length {
353
- $token: str-slice($string-lower, $i, $i);
354
- @if $token == ' ' or $token == " " {
355
- // @continue;
356
- }
357
- @else if $token == '(' or $token == ',' {
358
- $frags: append($frags, "");
359
- }
360
- @else if $token == ')' {
361
- @if length($frags) != if($is-alpha, 4, 3) { @return $string; } // Parsing error
362
- $red: _get-color-value(nth($frags, 1));
363
- $green: _get-color-value(nth($frags, 2));
364
- $blue: _get-color-value(nth($frags, 3));
365
-
366
- @if not $red or not $green or not $blue {
367
- @return $string;
368
- }
369
-
370
- @if $is-alpha {
371
- @if length($frags) != 4 { @return $string; } // No alpha channel found
372
- $alpha: _get-color-value(nth($frags, 4));
373
- @if not $alpha { @return $string; } // Error parsing alpha channel
374
- @return rgba($red, $green, $blue, $alpha);
375
- }
376
-
377
- @return rgb($red, $green, $blue);
378
- }
379
- @else {
380
- $frags: set-nth($frags, length($frags), nth($frags, length($frags)) + $token);
381
- }
382
- }
383
-
384
- @return $string;
385
- }
386
-
387
- // Cast a JSON encoded string into a hexadecimal color
388
- // --------------------------------------------------------------------------------
389
- // @param [string] $string: JSON string
390
- // --------------------------------------------------------------------------------
391
- // @return [color|string] string or hex color depending on the match
392
-
393
- @function _from-hex($string) {
394
- $string-lower: to-lower-case($string);
395
- $r: ""; $g: ""; $b: "";
396
- $hex: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f";
397
- $length: str-length($string);
398
- $max: if($length == 4, 1, 2);
399
-
400
- // Check for length accuracy
401
- @if $length != 4 and $length != 7 {
402
- @return $string;
403
- }
404
-
405
- // Loop from the second character (omitting #)
406
- @for $i from 2 through $length {
407
- $c: str-slice($string-lower, $i, $i);
408
-
409
- // If wrong character, return
410
- @if not index($hex, $c) {
411
- @return $string;
412
- }
413
-
414
- @if str-length($r) < $max { $r: $r + $c }
415
- @else if str-length($g) < $max { $g: $g + $c }
416
- @else if str-length($b) < $max { $b: $b + $c }
417
- }
418
-
419
- @if $length == 4 {
420
- $r: $r + $r;
421
- $g: $g + $g;
422
- $b: $b + $b;
423
- }
424
-
425
- @return rgb(_hex-to-dec($r), _hex-to-dec($g), _hex-to-dec($b));
426
- }
427
-
428
- // Convert an hexadecimal number to a decimal number
429
- // --------------------------------------------------------------------------------
430
- // @param [string] $string: hexadecimal value
431
- // --------------------------------------------------------------------------------
432
- // @return [number] decimal number
433
-
434
- @function _hex-to-dec($string) {
435
- $hex: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "d" "e" "f";
436
- $string: to-lower-case($string);
437
- $length: str-length($string);
438
-
439
- $dec: 0;
440
- @for $i from 1 through $length {
441
- $factor: 1 + (15 * ($length - $i));
442
- $index: index($hex, str-slice($string, $i, $i));
443
- $dec: $dec + $factor * ($index - 1);
444
- }
445
-
446
- @return $dec;
447
- }
448
-
449
- // Power function
450
- // --------------------------------------------------------------------------------
451
- // @param [number] $x: number
452
- // @param [number] $n: power
453
- // --------------------------------------------------------------------------------
454
- // @return [number] $x ^ $n
455
-
456
- @function _pow($x, $n) {
457
- @if $n == 0 { @return 1; }
458
- $ret: 1;
459
- @if $n >= 0 {
460
- @for $i from 1 through $n {
461
- $ret: $ret * $x;
462
- }
463
- } @else {
464
- @for $i from $n to 0 {
465
- $ret: $ret / $x;
466
- }
467
- }
468
-
469
- @return $ret;
470
- }
471
-
472
- // Parses a JSON encoded number to find the integer part
473
- // --------------------------------------------------------------------------------
474
- // @param [string] $source: JSON complete source
475
- // @param [number] $pointer: current pointer
476
- // --------------------------------------------------------------------------------
477
- // @throw "Unexpected token $token."
478
- // --------------------------------------------------------------------------------
479
- // @return [list|false] (new pointer, parsed number)
480
-
481
- @function _find-integer($source, $pointer) {
482
- $source: to-lower-case($source);
483
- $length: str-length($source);
484
- $numbers: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
485
- $result: 0;
486
-
487
- @while $pointer <= $length {
488
- $token: str-slice($source, $pointer, $pointer);
489
- $index: index($numbers, $token);
490
-
491
- @if $token == '-' {
492
- // do nothing
493
- }
494
- @else if $index {
495
- $result: $result * 10 + ($index - 1);
496
- }
497
- @else {
498
- @if index('e' '.' ' ' ',' ']' '}', $token) {
499
- @return $pointer, $result;
500
- }
501
- @return _throw("Unexpected token `" + $token + "`.", $pointer);
502
- }
503
-
504
- $pointer: $pointer + 1;
505
- }
506
-
507
- @return $pointer, $result;
508
- }
509
-
510
- // Parses a JSON encoded number to find the digits
511
- // --------------------------------------------------------------------------------
512
- // @param [string] $source: JSON complete source
513
- // @param [number] $pointer: current pointer
514
- // --------------------------------------------------------------------------------
515
- // @throw "Unexpected token $token."
516
- // --------------------------------------------------------------------------------
517
- // @return [list|false] (new pointer, parsed number)
518
-
519
- @function _find-digits($source, $pointer) {
520
- $source: to-lower-case($source);
521
- $length: str-length($source);
522
- $numbers: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
523
- $result: null;
524
- $runs: 1;
525
-
526
- @while $pointer <= $length {
527
- $token: str-slice($source, $pointer, $pointer);
528
- $index: index($numbers, $token);
529
-
530
- @if $token == '.' {
531
- // @continue;
532
- }
533
- @else if $index and $index > 0 {
534
- $runs: $runs * 10;
535
- $result: if($result == null, ($index - 1), $result * 10 + ($index - 1));
536
- }
537
- @else {
538
- @if index('e' '.' ' ' ',' ']' '}', $token) {
539
- @return $pointer, if($result != null, $result / $runs, $result);
540
- }
541
- @return _throw("Unexpected token `" + $token + "`.", $pointer);
542
- }
543
-
544
- $pointer: $pointer + 1;
545
- }
546
-
547
- @return $pointer, if($result != null, $result / $runs, $result);
548
- }
549
-
550
- // Parses a JSON encoded number to find the exponent part
551
- // --------------------------------------------------------------------------------
552
- // @param [string] $source: JSON complete source
553
- // @param [number] $pointer: current pointer
554
- // --------------------------------------------------------------------------------
555
- // @throw "Unexpected token $token."
556
- // --------------------------------------------------------------------------------
557
- // @return [list|false] (new pointer, parsed number)
558
-
559
- @function _find-exponent($source, $pointer) {
560
- $source: to-lower-case($source);
561
- $length: str-length($source);
562
- $numbers: '0' '1' '2' '3' '4' '5' '6' '7' '8' '9';
563
- $result: null;
564
- $minus: null;
565
-
566
- @while $pointer <= $length {
567
- $token: str-slice($source, $pointer, $pointer);
568
- $index: index($numbers, $token);
569
-
570
- @if $token == 'e' {
571
- // @continue;
572
- }
573
- @else if $token == '-' {
574
- @if $minus != null {
575
- @return _throw("Unexpected token `-`.", $pointer);
576
- }
577
- $minus: true;
578
- }
579
- @else if $token == '+' {
580
- @if $minus != null {
581
- @return _throw("Unexpected token `+`.", $pointer);
582
- }
583
- $minus: false;
584
- }
585
- @else if $index and $index > 0 {
586
- $result: if($result == null, ($index - 1), $result * 10 + ($index - 1));
587
- }
588
- @else {
589
- @if not index(' ' ',' ']' '}', $token) {
590
- @return _throw("Unexpected token `" + $token + "`.", $pointer);
591
- }
592
-
593
- @return $pointer, if($minus and $result != null, $result * -1, $result);
594
- }
595
-
596
- $pointer: $pointer + 1;
597
- }
598
-
599
- @return $pointer, if($minus and $result != null, $result * -1, $result);
600
- }
601
-
602
- // Parses a JSON encoded string
603
- // --------------------------------------------------------------------------------
604
- // @param [string] $source: JSON complete source
605
- // @param [number] $pointer: current pointer
606
- // --------------------------------------------------------------------------------
607
- // @throw "Unterminated string."
608
- // --------------------------------------------------------------------------------
609
- // @return [list|false] (new pointer, parsed string / color / length)
610
-
611
- @function _json-decode--string($source, $pointer) {
612
- // Check for the end of the string
613
- $temp: str-slice($source, $pointer);
614
- $end: _find-ending-quote($temp);
615
- $string: "";
616
-
617
- // If no end is found
618
- @if not $end or $end == 0 {
619
- @return _throw("Unterminated string.", $pointer);
620
- }
621
-
622
- // If string is not empty
623
- @else if $end > 1 {
624
- $string: str-slice($temp, 1, $end - 1);
625
-
626
- $cr: "
627
- ";
628
- $string: _strip-token($string, "\r", $cr);
629
- $string: _strip-token($string, "\n", $cr);
630
- $string: _strip-token($string, '\\\"', '"');
631
-
632
- // Test whether the string could be a CSS length
633
- $string: _length($string);
634
-
635
- // Test whether the string could be a CSS color
636
- @if type-of($string) == string {
637
- $string: _color($string);
638
- }
639
- }
640
-
641
- @return ($pointer + $end, $string);
642
- }
643
-
644
- // Parses a JSON encoded `true`
645
- // --------------------------------------------------------------------------------
646
- // @param [string] $source: JSON complete source
647
- // @param [number] $pointer: current pointer
648
- // --------------------------------------------------------------------------------
649
- // @throw "Unexpected token `t`."
650
- // --------------------------------------------------------------------------------
651
- // @return [list|false] (new pointer, true)
652
-
653
- @function _json-decode--true($source, $pointer) {
654
- $length: str-length($source);
655
- @if $length - $pointer < 2
656
- or str-slice($source, $pointer, $pointer) != 'r'
657
- or str-slice($source, $pointer + 1, $pointer + 1) != 'u'
658
- or str-slice($source, $pointer + 2, $pointer + 2) != 'e' {
659
- @return _throw("Unexpected token: `t`.", $pointer);
660
- }
661
- @return ($pointer + 3, true);
662
- }
663
-
664
- // Parses a JSON encoded `false`
665
- // --------------------------------------------------------------------------------
666
- // @param $source: JSON complete source
667
- // @param $pointer: current pointer
668
- // --------------------------------------------------------------------------------
669
- // @throw "Unexpected token `f`."
670
- // --------------------------------------------------------------------------------
671
- // @return [list|false] (new pointer, false)
672
-
673
- @function _json-decode--false($source, $pointer) {
674
- $length: str-length($source);
675
- @if $length - $pointer < 3
676
- or str-slice($source, $pointer, $pointer) != 'a'
677
- or str-slice($source, $pointer + 1, $pointer + 1) != 'l'
678
- or str-slice($source, $pointer + 2, $pointer + 2) != 's'
679
- or str-slice($source, $pointer + 3, $pointer + 3) != 'e' {
680
- @return _throw("Unexpected token: `f`.", $pointer);
681
- }
682
- @return ($pointer + 4, false);
683
- }
684
-
685
- // Parses a JSON encoded `null`
686
- // --------------------------------------------------------------------------------
687
- // @param [string] $source: JSON complete source
688
- // @param [number] $pointer: current pointer
689
- // --------------------------------------------------------------------------------
690
- // @throw "Unexpected token `n`."
691
- // --------------------------------------------------------------------------------
692
- // @return [list|false] (new pointer, null)
693
-
694
- @function _json-decode--null($source, $pointer) {
695
- $length: str-length($source);
696
- @if $length - $pointer < 2
697
- or str-slice($source, $pointer, $pointer) != 'u'
698
- or str-slice($source, $pointer + 1, $pointer + 1) != 'l'
699
- or str-slice($source, $pointer + 2, $pointer + 2) != 'l' {
700
- @return _throw("Unexpected token: `n`.", $pointer);
701
- }
702
- @return ($pointer + 3, null);
703
- }
704
-
705
- // Parses a JSON encoded number
706
- // --------------------------------------------------------------------------------
707
- // @param [string] $source: JSON complete source
708
- // @param [number] $pointer: current pointer
709
- // --------------------------------------------------------------------------------
710
- // @throw "Unexpected token $token."
711
- // @throw "Unexpected end of stream."
712
- // --------------------------------------------------------------------------------
713
- // @return [list|false] (new pointer, parsed number)
714
-
715
- @function _json-decode--number($source, $pointer) {
716
- $pointer: $pointer - 1; // Move back pointer to begininng of number
717
- $allowed: '-' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9'; // Allowed characted to start with
718
- $first: str-slice($source, $pointer, $pointer); // First character of the number
719
- $minus: $first == '-'; // Is it negative?
720
-
721
- // Early check for errors
722
- @if not index($allowed, $first) {
723
- @return _throw("Unexpected token `" + $first + "`.", $pointer);
724
- }
725
-
726
- // Find the integer part
727
- $find-integer: _find-integer($source, $pointer);
728
- $pointer: nth($find-integer, 1);
729
- $result: nth($find-integer, 2);
730
- @if not $result { // Error occured
731
- @return $find-integer;
732
- }
733
-
734
- // Find digits
735
- @if str-slice($source, $pointer, $pointer) == '.' {
736
- $find-digits: _find-digits($source, $pointer);
737
- $pointer: nth($find-digits, 1);
738
- $digits: nth($find-digits, 2);
739
-
740
- @if $digits == null { // Empty digits, throw error
741
- @return _throw("Unexpected end of stream.", $pointer);
742
- }
743
- @else if $digits == false { // Error occured, return it
744
- @return $find-digits;
745
- }
746
-
747
- $result: $result + $digits;
748
- }
749
-
750
- // Find exponent
751
- @if to-lower-case(str-slice($source, $pointer, $pointer)) == 'e' {
752
- $find-exponent: _find-exponent($source, $pointer);
753
- $pointer: nth($find-exponent, 1);
754
- $exponent: nth($find-exponent, 2);
755
-
756
- @if $exponent == null { // Empty exponent, throw error
757
- @return _throw("Unexpected end of stream.", $pointer);
758
- }
759
- @else if $exponent == false { // Error occured, return it
760
- @return $find-exponent;
761
- }
762
-
763
- $result: $result * _pow(10, $exponent);
764
- }
765
-
766
- @return ($pointer, if($minus, $result * -1, $result));
767
- }
768
-
769
- // Parses a JSON encoded array
770
- // --------------------------------------------------------------------------------
771
- // @param [string] $source: JSON complete source
772
- // @param [number] $pointer: current pointer
773
- // --------------------------------------------------------------------------------
774
- // @throw "Unexpected comma in array literal."
775
- // @throw "Missing comma in array literal."
776
- // @throw "Unterminated array literal."
777
- // --------------------------------------------------------------------------------
778
- // @return [list|false] (new pointer, parsed list)
779
-
780
- @function _json-decode--list($source, $pointer) {
781
- $length: str-length($source);
782
- $list: ();
783
- $needs-comma: false;
784
-
785
- @if $pointer <= $length and str-slice($source, $pointer, $pointer) == "]" {
786
- @return ($pointer + 1, $list);
787
- }
788
-
789
- @while $pointer <= $length {
790
- $token: str-slice($source, $pointer, $pointer);
791
-
792
- @if $token == "]" {
793
- @if not $needs-comma and length($list) != 0 {
794
- @return _throw("Unexpected comma in array literal.", $pointer);
795
- }
796
-
797
- // Do it the Sass way and destruct a single item array to an element.
798
- @return ($pointer + 1, if(length($list) == 1, nth($list, 1), $list));
799
- }
800
- @else if $token == " " or $token == " " {
801
- $pointer: $pointer + 1;
802
- }
803
- @else if $token == "," {
804
- @if not $needs-comma {
805
- @return _throw("Unexpected comma in array literal.", $pointer);
806
- }
807
- $needs-comma: false;
808
- $pointer: $pointer + 1;
809
- }
810
- @else {
811
- @if $needs-comma {
812
- @return _throw("Missing comma in array literal.", $pointer);
813
- }
814
- $read: _json-decode--value($source, $pointer);
815
- $pointer: nth($read, 1);
816
- $list: append($list, nth($read, 2));
817
- $needs-comma: true;
818
- }
819
- }
820
-
821
- @return _throw("Unterminated array literal.", $pointer);
822
- }
823
-
824
- // Parses a JSON encoded object
825
- // --------------------------------------------------------------------------------
826
- // @param [string] $source: JSON complete source
827
- // @param [number] $pointer: current pointer
828
- // --------------------------------------------------------------------------------
829
- // @throw "Unexpected comma in object literal."
830
- // @throw "Unexpected token $token in object literal."
831
- // @throw "Missing comma in object literal."
832
- // @throw "Unterminated object literal."
833
- // @throw "Consuming token `:` failed."
834
- // --------------------------------------------------------------------------------
835
- // @return [list|false] (new pointer, map)
836
-
837
- @function _json-decode--map($source, $pointer) {
838
- $length: str-length($source);
839
- $map: ();
840
- $needs-comma: false;
841
-
842
- // Deal with empty map
843
- @if $pointer <= $length and str-slice($source, $pointer, $pointer) == "}" {
844
- @return ($pointer + 1, $map);
845
- }
846
-
847
- @while $pointer <= $length {
848
- $token: str-slice($source, $pointer, $pointer);
849
- $pointer: $pointer + 1;
850
-
851
- @if $token == "}" {
852
- @if not $needs-comma and length($map) != 0 {
853
- @return _throw("Unexpected comma in object literal.", $pointer);
854
- }
855
- @return ($pointer, $map);
856
- }
857
-
858
- @else if $token == " " or $token == " " {
859
- // @continue;
860
- }
861
-
862
- @else if $token == "," {
863
- @if not $needs-comma {
864
- @return _throw("Unexpected comma in object literal.", $pointer);
865
- }
866
- $needs-comma: false;
867
- }
868
-
869
- @else if $token == '"' {
870
- @if $needs-comma {
871
- @return _throw("Missing comma in object literal.", $pointer);
872
- }
873
-
874
- // Read key
875
- $read-key: _json-decode--string($source, $pointer);
876
- $pointer: nth($read-key, 1);
877
- $key: nth($read-key, 2);
878
-
879
- // Remove colon
880
- $pointer: _consume($source, $pointer, ":");
881
- @if length($pointer) > 1 { // If consume has failed
882
- @return _throw("Consuming token `:` failed.", 0);
883
- }
884
-
885
- // Read value
886
- $read-value: _json-decode--value($source, $pointer);
887
- $pointer: nth($read-value, 1);
888
- $value: nth($read-value, 2);
889
-
890
- // Add pair to map
891
- $map: map-merge($map, ($key: $value));
892
- $needs-comma: true;
893
- }
894
-
895
- @else {
896
- @return _throw("Unexpected token `" + $token + "` in object literal.", $pointer);
897
- }
898
- }
899
-
900
- @return _throw("Unterminated object literal.", $pointer);
901
- }
902
-
903
- // Parse a JSON string
904
- // --------------------------------------------------------------------------------
905
- // @param $json: JSON string to parse
906
- // --------------------------------------------------------------------------------
907
- // @throw "Input string may not be null"
908
- // --------------------------------------------------------------------------------
909
- // @return [literal|false]
910
-
911
- @function json-decode($json) {
912
- $length: str-length($json);
913
- $pointer: 1;
914
- $value: null;
915
-
916
- @if $json == null {
917
- @return _throw("Input string may not be null.", $pointer);
918
- }
919
-
920
- @while $value != false // Stop if error
921
- and $pointer <= $length {
922
- $read: _json-decode--value($json, $pointer);
923
- $pointer: nth($read, 1);
924
- $value: nth($read, 2);
925
- }
926
-
927
- @return $value;
928
- }
929
-
930
- // Proof quote a value
931
- // --------------------------------------------------------------------------------
932
- // @param $value: value to be quoted
933
- // --------------------------------------------------------------------------------
934
- // @return [string] quoted value
935
-
936
- @function _proof-quote($value) {
937
- @return '"' + $value + '"';
938
- }
939
-
940
- // Encode a bool to JSON
941
- // --------------------------------------------------------------------------------
942
- // @param $bool: bool to be encoded
943
- // --------------------------------------------------------------------------------
944
- // @return [bool] boolean
945
-
946
- @function _json-encode--bool($boolean) {
947
- @return $boolean;
948
- }
949
-
950
- // Encode a color to JSON
951
- // --------------------------------------------------------------------------------
952
- // @param $color: color to be encoded
953
- // --------------------------------------------------------------------------------
954
- // @return [string] encoded color
955
-
956
- @function _json-encode--color($color) {
957
- @return _proof-quote($color);
958
- }
959
-
960
- // Encode a list to JSON
961
- // --------------------------------------------------------------------------------
962
- // @param $list: list to be encoded
963
- // --------------------------------------------------------------------------------
964
- // @return [string] encoded list
965
-
966
- @function _json-encode--list($list) {
967
- $str: "";
968
- @each $item in $list {
969
- $str: $str + ', ' + json-encode($item);
970
- }
971
- @return '[' + str-slice($str, 3) + ']';
972
- }
973
-
974
- // Encode a map to JSON
975
- // --------------------------------------------------------------------------------
976
- // @param $map: map to be encoded
977
- // --------------------------------------------------------------------------------
978
- // @return [string] encoded map
979
-
980
- @function _json-encode--map($map) {
981
- $str: "";
982
- @each $key, $value in $map {
983
- $str: $str + ', ' + _proof-quote($key) + ': ' + json-encode($value);
984
- }
985
- @return '{' + str-slice($str, 3) + '}';
986
- }
987
-
988
- // Encode a number to JSON
989
- // --------------------------------------------------------------------------------
990
- // @param $number: number to be encoded
991
- // --------------------------------------------------------------------------------
992
- // @return [string] encoded number
993
-
994
- @function _json-encode--number($number) {
995
- @return if(unitless($number), $number, _proof-quote($number));
996
- }
997
-
998
- // Encode a string to JSON
999
- // --------------------------------------------------------------------------------
1000
- // @param $string: string to be encoded
1001
- // --------------------------------------------------------------------------------
1002
- // @return [string] encoded string
1003
-
1004
- @function _json-encode--string($string) {
1005
- @return _proof-quote($string);
1006
- }
1007
-
1008
- // Encode `null` to JSON
1009
- // --------------------------------------------------------------------------------
1010
- // @param $null: `null`
1011
- // --------------------------------------------------------------------------------
1012
- // @return [string] `null`
1013
-
1014
- @function _json-encode--null($null) {
1015
- @return "null";
1016
- }
1017
-
1018
- // JSON.stringify a value and pass it as a font-family of head element
1019
- // --------------------------------------------------------------------------------
1020
- // @param $value: value to be stringified
1021
- // @parem $flag: output driver
1022
-
1023
- @mixin json-encode($value, $flag: all) {
1024
- $flag: if(not index(all regular media comment, $flag), all, $flag);
1025
- $json: json-encode($value);
1026
-
1027
- // Persistent comment
1028
- @if $flag == comment or $flag == all {
1029
- /*! json-encode: #{$json} */
1030
- }
1031
- // Regular property value pair
1032
- @if $flag == regular or $flag == all {
1033
- // All browsers except IE8-
1034
- body::before {
1035
- // This element must be in the render tree to get it via getComputedStyle(document.body, ':before');
1036
- content: json-encode($value);
1037
- display: block;
1038
- height: 0;
1039
- overflow: hidden;
1040
- width: 0;
1041
- }
1042
-
1043
- // All browsers except Opera (Presto based)
1044
- head {
1045
- font-family: json-encode($value);
1046
- }
1047
- }
1048
-
1049
- // Falsy media query
1050
- @if $flag == media or $flag == all {
1051
- @media -json-encode {
1052
- json {
1053
- json: $json;
1054
- }
1055
- }
1056
- }
1057
- }
1058
-
1059
- // Delay the encoding of ta literal to JSON
1060
- // to a type-specific method
1061
- // --------------------------------------------------------------------------------
1062
- // @param $value: value to be stringified
1063
- // --------------------------------------------------------------------------------
1064
- // @throw "Unknown type for $value ( {x} )."
1065
- // --------------------------------------------------------------------------------
1066
- // @return [string|false] JSON encoded string
1067
-
1068
- @function json-encode($value) {
1069
- $type: type-of($value);
1070
- @if function_exists('_json-encode--#{$type}') {
1071
- @return call('_json-encode--#{$type}', $value);
1072
- }
1073
- @warn "Unknown type for #{$value} (#{$type}).";
1074
- @return false;
1075
- }