gerillass 2.3.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -7
- package/SKILL.md +37 -12
- package/gerillass.json +527 -145
- package/package.json +1 -1
- package/scss/internal/_color-problem.scss +99 -0
- package/scss/internal/_color-stops-problem.scss +94 -0
- package/scss/internal/_condition-width.scss +22 -0
- package/scss/internal/_custom-property-in.scss +25 -0
- package/scss/internal/_gradient.scss +425 -0
- package/scss/internal/_image-value.scss +68 -0
- package/scss/internal/_is-condition-value.scss +94 -0
- package/scss/internal/_is-css-function.scss +21 -0
- package/scss/internal/_is-size.scss +22 -0
- package/scss/internal/_keyword-value.scss +76 -0
- package/scss/internal/_length-problem.scss +127 -0
- package/scss/internal/_sibling-index.scss +51 -0
- package/scss/internal/_words.scss +35 -0
- package/scss/library/_adaptive.scss +17 -0
- package/scss/library/_after.scss +2 -12
- package/scss/library/_background-dots.scss +36 -43
- package/scss/library/_background-image.scss +40 -52
- package/scss/library/_background-stripes.scss +40 -54
- package/scss/library/_before.scss +2 -12
- package/scss/library/_border-radius.scss +83 -0
- package/scss/library/_brand-logo.scss +10 -24
- package/scss/library/_breakpoint.scss +19 -26
- package/scss/library/_circle.scss +7 -0
- package/scss/library/_columnizer.scss +62 -2
- package/scss/library/_container-query.scss +13 -29
- package/scss/library/_container.scss +2 -19
- package/scss/library/_counter.scss +3 -14
- package/scss/library/_ellipsis.scss +78 -1
- package/scss/library/_except.scss +15 -0
- package/scss/library/_focus-ring.scss +29 -0
- package/scss/library/_font-face.scss +117 -1
- package/scss/library/_gradient.scss +31 -0
- package/scss/library/_index.scss +1 -2
- package/scss/library/_line-clamp.scss +2 -13
- package/scss/library/_only.scss +16 -0
- package/scss/library/_position.scss +34 -3
- package/scss/library/_remove.scss +1 -1
- package/scss/library/_resizable.scss +29 -2
- package/scss/library/_screen-agent.scss +8 -22
- package/scss/library/_sizer.scss +9 -0
- package/scss/library/_sprite.scss +65 -0
- package/scss/library/_text-gradient.scss +36 -18
- package/scss/library/_text-image.scss +2 -23
- package/scss/library/_text-stroke.scss +30 -0
- package/scss/library/_triangle.scss +25 -56
- package/scss/utilities/_gradient-value.scss +24 -0
- package/scss/utilities/_index.scss +1 -0
- package/scss/utilities/_validate-breakpoint.scss +32 -6
- package/scss/utilities/_validate-scissors.scss +7 -0
- package/scss/library/_linear-gradient.scss +0 -26
- package/scss/library/_radial-gradient.scss +0 -30
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
+
@use "sass:meta";
|
|
4
|
+
@use "../internal/length-problem" as *;
|
|
5
|
+
|
|
3
6
|
@mixin circle($size) {
|
|
7
|
+
$problem: sizeProblem($size);
|
|
8
|
+
@if $problem {
|
|
9
|
+
@error "`#{meta.inspect($size)}` is not a valid $size for `circle`: #{$problem}. A browser drops the width and height.";
|
|
10
|
+
}
|
|
4
11
|
width: $size;
|
|
5
12
|
height: $size;
|
|
6
13
|
display: inline-block;
|
|
@@ -1,15 +1,75 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
3
|
@use "sass:list";
|
|
4
|
+
@use "sass:math";
|
|
4
5
|
@use "sass:meta";
|
|
6
|
+
@use "sass:string";
|
|
5
7
|
@use "../library/border-box" as *;
|
|
6
8
|
@use "../utilities/is-gutter" as *;
|
|
9
|
+
@use "../internal/length-problem" as *;
|
|
10
|
+
|
|
11
|
+
// The count divides 100% in calc(), which in Chrome 152 kept a unitless number
|
|
12
|
+
// and a function that resolves to one, var(), env() or attr(), or maths with
|
|
13
|
+
// one of those inside. It dropped a count with a unit, a word and maths on
|
|
14
|
+
// lengths alone, such as calc(100% - 10px): 100% divided by a length is not a
|
|
15
|
+
// length.
|
|
16
|
+
@function -count-problem($columns) {
|
|
17
|
+
@if meta.type-of($columns) == "number" {
|
|
18
|
+
@if math.is-unitless($columns) {
|
|
19
|
+
@return null;
|
|
20
|
+
}
|
|
21
|
+
@return "a column count has no unit";
|
|
22
|
+
}
|
|
23
|
+
// Interpolation, as in `#{$cols}`, gives the number as an unquoted string,
|
|
24
|
+
// which is written into calc() as it reads.
|
|
25
|
+
@if meta.type-of($columns) == "string" and string.slice(meta.inspect($columns), 1, 1) != "\"" and not string.index($columns, "(") {
|
|
26
|
+
$digits: 0;
|
|
27
|
+
@for $i from 1 through string.length($columns) {
|
|
28
|
+
$character: string.slice($columns, $i, $i);
|
|
29
|
+
@if string.index("0123456789", $character) {
|
|
30
|
+
$digits: $digits + 1;
|
|
31
|
+
} @else if not string.index(".+-", $character) {
|
|
32
|
+
@return "it is not a column count";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
@if $digits > 0 {
|
|
36
|
+
@return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
@if meta.type-of($columns) == "calculation" or (meta.type-of($columns) == "string" and string.index($columns, "(")) {
|
|
40
|
+
$text: string.to-lower-case(meta.inspect($columns));
|
|
41
|
+
@if string.index($text, "var(") or string.index($text, "env(") or string.index($text, "attr(") {
|
|
42
|
+
@return null;
|
|
43
|
+
}
|
|
44
|
+
@return "maths on lengths does not give a count; pass a number, or var(), env() or attr()";
|
|
45
|
+
}
|
|
46
|
+
@return "it is not a column count";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The gutter is multiplied in calc() and written as a margin. Chrome 152 kept a
|
|
50
|
+
// length, a percentage and a negative length, and dropped the flex-basis for a
|
|
51
|
+
// unitless number, a unit that is not a length and a word. A unitless 0 made
|
|
52
|
+
// `(3 - 1) * 0`, a number rather than a length, so it is written as 0px.
|
|
53
|
+
@function -gutter($gutter) {
|
|
54
|
+
$problem: lengthProblem($gutter);
|
|
55
|
+
@if $problem {
|
|
56
|
+
@error "`#{meta.inspect($gutter)}` is not a valid gutter for `columnizer`: #{$problem}. A browser drops the column width.";
|
|
57
|
+
}
|
|
58
|
+
@if (meta.type-of($gutter) == "number" and math.is-unitless($gutter)) or (meta.type-of($gutter) == "string" and string.unquote($gutter) == string.unquote("0")) {
|
|
59
|
+
@return 0px;
|
|
60
|
+
}
|
|
61
|
+
@return $gutter;
|
|
62
|
+
}
|
|
7
63
|
|
|
8
64
|
@mixin columnizer($params...) {
|
|
9
65
|
@if list.length($params) < 1 or list.length($params) > 3 {
|
|
10
66
|
@error "`columnizer` takes 1 to 3 arguments; you passed #{list.length($params)}. Pass the column count, optionally a gutter length, and optionally a boolean telling the last row whether to fill.";
|
|
11
67
|
}
|
|
12
68
|
$columns: list.nth($params, 1);
|
|
69
|
+
$count-problem: -count-problem($columns);
|
|
70
|
+
@if $count-problem {
|
|
71
|
+
@error "`#{meta.inspect($columns)}` is not a valid column count for `columnizer`: #{$count-problem}. A browser drops the column width.";
|
|
72
|
+
}
|
|
13
73
|
$gutter: null;
|
|
14
74
|
$fill: false;
|
|
15
75
|
display: flex;
|
|
@@ -33,7 +93,7 @@
|
|
|
33
93
|
margin-right: 0;
|
|
34
94
|
}
|
|
35
95
|
} @else if isGutter(list.nth($params, 2)) {
|
|
36
|
-
$gutter: list.nth($params, list.length($params));
|
|
96
|
+
$gutter: -gutter(list.nth($params, list.length($params)));
|
|
37
97
|
flex-grow: 0;
|
|
38
98
|
flex-shrink: 0;
|
|
39
99
|
flex-basis: calc((100% - (#{$columns} - 1) * #{$gutter}) / #{$columns});
|
|
@@ -48,7 +108,7 @@
|
|
|
48
108
|
@error "`#{list.nth($params, 2)}` is not a valid second argument for `columnizer`. Pass a gutter length such as `20px` or `var(--gap)`, or a boolean telling the last row whether to fill.";
|
|
49
109
|
}
|
|
50
110
|
} @else if list.length($params) == 3 {
|
|
51
|
-
$gutter: list.nth($params, 2);
|
|
111
|
+
$gutter: -gutter(list.nth($params, 2));
|
|
52
112
|
$fill: list.nth($params, list.length($params));
|
|
53
113
|
flex-grow: if($fill == true, 1, 0);
|
|
54
114
|
flex-shrink: 0;
|
|
@@ -5,26 +5,8 @@
|
|
|
5
5
|
@use "sass:meta";
|
|
6
6
|
@use "sass:string";
|
|
7
7
|
@use "../maps/map-for-breakpoints" as *;
|
|
8
|
-
@use "../
|
|
9
|
-
|
|
10
|
-
// Returns the first value in $value that holds var(), looking inside lists and
|
|
11
|
-
// calculations, or null. Custom properties are not evaluated in a @media or
|
|
12
|
-
// @container condition, so a rule built from one never applies, and nothing
|
|
13
|
-
// warns. Measured in Chrome 152: `(min-width: var(--wide))` did not match with
|
|
14
|
-
// `--wide: 200px`, while `(min-width: 200px)` did.
|
|
15
|
-
@function -custom-property-in($value) {
|
|
16
|
-
@each $item in $value {
|
|
17
|
-
@if meta.type-of($item) == "list" or meta.type-of($item) == "arglist" {
|
|
18
|
-
$found: -custom-property-in($item);
|
|
19
|
-
@if $found {
|
|
20
|
-
@return $found;
|
|
21
|
-
}
|
|
22
|
-
} @else if string.index(meta.inspect($item), "var(") {
|
|
23
|
-
@return $item;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
@return null;
|
|
27
|
-
}
|
|
8
|
+
@use "../internal/custom-property-in" as *;
|
|
9
|
+
@use "../internal/condition-width" as *;
|
|
28
10
|
|
|
29
11
|
// Characters and names a browser will not keep as the name in an @container
|
|
30
12
|
// rule. Measured in Chrome 152, the rule was dropped for `var(--n)`, `none`,
|
|
@@ -88,7 +70,7 @@ $-forbidden-in-name: "." "," "/" "#" ":" ";" "(" ")" "[" "]" "{" "}" "!" "@" "$"
|
|
|
88
70
|
}
|
|
89
71
|
}
|
|
90
72
|
|
|
91
|
-
$custom-property:
|
|
73
|
+
$custom-property: customPropertyIn($params);
|
|
92
74
|
@if $custom-property {
|
|
93
75
|
@error "`#{$custom-property}` cannot be used in a container query: custom properties are not evaluated in a @container condition, so the rule would never apply. Pass a length or a key from $map-for-breakpoints.";
|
|
94
76
|
}
|
|
@@ -96,27 +78,29 @@ $-forbidden-in-name: "." "," "/" "#" ":" ";" "(" ")" "[" "]" "{" "}" "!" "@" "$"
|
|
|
96
78
|
|
|
97
79
|
@if $count == 1 {
|
|
98
80
|
$value: list.nth($params, 1);
|
|
99
|
-
|
|
81
|
+
// Checked before the warning, as in `breakpoint`. conditionWidth returns
|
|
82
|
+
// what validateBreakpoint did, so a working call writes the same condition.
|
|
83
|
+
$width: conditionWidth($value, "container-query", "@container");
|
|
100
84
|
$condition: "(width: #{$width})";
|
|
101
|
-
// A single pixel, as in `breakpoint`; still emitted
|
|
102
|
-
@warn "`container-query(#{$value})` matches only a container exactly #{$width} wide, `(width: #{$width})`. Write `container-query(only, #{$value})` for that width, or `container-query(min, #{$value})` from it upwards.
|
|
85
|
+
// A single pixel, as in `breakpoint`; still emitted, with a warning.
|
|
86
|
+
@warn "`container-query(#{$value})` matches only a container exactly #{$width} wide, `(width: #{$width})`. Write `container-query(only, #{$value})` for that width, or `container-query(min, #{$value})` from it upwards.";
|
|
103
87
|
} @else if $count == 2 {
|
|
104
88
|
$mode: list.nth($params, 1);
|
|
105
89
|
@if not list.index("only" "min" "max" "between", $mode) {
|
|
106
90
|
// Two bare sizes mean a range, as they do in `breakpoint`.
|
|
107
|
-
$condition: "(min-width: #{
|
|
91
|
+
$condition: "(min-width: #{conditionWidth($mode, "container-query", "@container")}) and (max-width: #{conditionWidth(list.nth($params, 2), "container-query", "@container")})";
|
|
108
92
|
} @else {
|
|
109
93
|
$value: list.nth($params, 2);
|
|
110
94
|
@if $mode == "only" {
|
|
111
|
-
$condition: "(width: #{
|
|
95
|
+
$condition: "(width: #{conditionWidth($value, "container-query", "@container")})";
|
|
112
96
|
} @else if $mode == "min" {
|
|
113
|
-
$condition: "(min-width: #{
|
|
97
|
+
$condition: "(min-width: #{conditionWidth($value, "container-query", "@container")})";
|
|
114
98
|
} @else if $mode == "max" {
|
|
115
|
-
$condition: "(max-width: #{
|
|
99
|
+
$condition: "(max-width: #{conditionWidth($value, "container-query", "@container")})";
|
|
116
100
|
} @else {
|
|
117
101
|
$start: list.nth($value, 1);
|
|
118
102
|
$end: list.nth($value, 2);
|
|
119
|
-
$condition: "(min-width: #{
|
|
103
|
+
$condition: "(min-width: #{conditionWidth($start, "container-query", "@container")}) and (max-width: #{conditionWidth($end, "container-query", "@container")})";
|
|
120
104
|
}
|
|
121
105
|
}
|
|
122
106
|
} @else {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
@use "sass:list";
|
|
4
4
|
@use "sass:meta";
|
|
5
5
|
@use "sass:string";
|
|
6
|
+
@use "../internal/words" as *;
|
|
6
7
|
|
|
7
8
|
// What a browser will not keep in `container-name`. Measured in Chrome 152, the
|
|
8
9
|
// declaration was dropped for `and`, `or`, `not` and `default` in any case, a
|
|
@@ -16,30 +17,12 @@ $-reserved-names: "and" "or" "not" "default";
|
|
|
16
17
|
$-alone-names: "none" "inherit" "initial" "unset" "revert" "revert-layer";
|
|
17
18
|
$-forbidden-in-name: "." "," "/" "#" ":" ";" "(" ")" "[" "]" "{" "}" "!" "@" "$" "%" "^" "&" "*" "+" "=" "<" ">" "?" "\\" "|" "~" "`" "'" "\"";
|
|
18
19
|
|
|
19
|
-
@function -words($text) {
|
|
20
|
-
$words: ();
|
|
21
|
-
$rest: $text;
|
|
22
|
-
$at: string.index($rest, " ");
|
|
23
|
-
@while $at {
|
|
24
|
-
$word: string.slice($rest, 1, $at - 1);
|
|
25
|
-
@if string.length($word) > 0 {
|
|
26
|
-
$words: list.append($words, $word);
|
|
27
|
-
}
|
|
28
|
-
$rest: string.slice($rest, $at + 1);
|
|
29
|
-
$at: string.index($rest, " ");
|
|
30
|
-
}
|
|
31
|
-
@if string.length($rest) > 0 {
|
|
32
|
-
$words: list.append($words, $rest);
|
|
33
|
-
}
|
|
34
|
-
@return $words;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
20
|
@function -name-problem($name) {
|
|
38
21
|
$text: "#{$name}";
|
|
39
22
|
@if string.index($text, "var(") {
|
|
40
23
|
@return null;
|
|
41
24
|
}
|
|
42
|
-
$words:
|
|
25
|
+
$words: wordsOf($text);
|
|
43
26
|
@each $word in $words {
|
|
44
27
|
$lower: string.to-lower-case($word);
|
|
45
28
|
@if list.index($-alone-names, $lower) and list.length($words) > 1 {
|
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
3
|
@use "sass:list";
|
|
4
|
-
@use "sass:meta";
|
|
5
|
-
@use "sass:string";
|
|
6
4
|
@use "../lists/list-of-counter-styles" as *;
|
|
7
|
-
|
|
8
|
-
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
9
|
-
// stays text, so `"var(--x)"` is not a call.
|
|
10
|
-
@function -is-css-function($value, $names) {
|
|
11
|
-
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
12
|
-
@return false;
|
|
13
|
-
}
|
|
14
|
-
$open: string.index($value, "(");
|
|
15
|
-
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
16
|
-
}
|
|
5
|
+
@use "../internal/is-css-function" as *;
|
|
17
6
|
|
|
18
7
|
@mixin counter($params...) {
|
|
19
8
|
$counter: null;
|
|
@@ -49,10 +38,10 @@
|
|
|
49
38
|
// quoting would turn into the literal characters.
|
|
50
39
|
$quote-before: '"';
|
|
51
40
|
$quote-after: '"';
|
|
52
|
-
@if
|
|
41
|
+
@if isCssFunction($counter-before, "var" "attr" "counter" "counters") {
|
|
53
42
|
$quote-before: "";
|
|
54
43
|
}
|
|
55
|
-
@if
|
|
44
|
+
@if isCssFunction($counter-after, "var" "attr" "counter" "counters") {
|
|
56
45
|
$quote-after: "";
|
|
57
46
|
}
|
|
58
47
|
&.counter-start {
|
|
@@ -1,7 +1,84 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
6
|
+
@use "../internal/keyword-value" as *;
|
|
7
|
+
@use "../internal/length-problem" as *;
|
|
8
|
+
@use "../internal/words" as *;
|
|
9
|
+
|
|
10
|
+
// The display keywords, sorted by the part of the value each one fills.
|
|
11
|
+
// Measured in Chrome 152, one keyword, or two or three in any order, were kept
|
|
12
|
+
// when they named at most one outer type, one inner type and one list-item:
|
|
13
|
+
// `inline flex`, `flex block`, `block flow list-item`, `list-item inline flow`.
|
|
14
|
+
// These were dropped: two of a kind (`block inline`, `flex grid`,
|
|
15
|
+
// `block block`), `list-item` beside an inner type other than flow or
|
|
16
|
+
// flow-root (`list-item flex`), and a compound keyword such as `inline-block`
|
|
17
|
+
// beside anything. Chrome also dropped `run-in`, the ruby-base family and the
|
|
18
|
+
// -moz- and -ms- boxes; they are in the specification or used by other
|
|
19
|
+
// engines, so they are let through.
|
|
20
|
+
$-outer: "block" "inline" "run-in";
|
|
21
|
+
$-inner: "flow" "flow-root" "table" "flex" "grid" "ruby" "math";
|
|
22
|
+
$-alone: "none" "contents" "inline-block" "inline-table" "inline-flex" "inline-grid" "table-row-group" "table-header-group" "table-footer-group" "table-row" "table-cell" "table-column-group" "table-column" "table-caption" "ruby-base" "ruby-text" "ruby-base-container" "ruby-text-container";
|
|
23
|
+
|
|
24
|
+
@function -display-problem($display) {
|
|
25
|
+
$keywords: list.join(list.join(list.join($-outer, $-inner), $-alone), ("list-item",));
|
|
26
|
+
$problem: keywordProblem($display, $keywords, 3, $vendor: true);
|
|
27
|
+
@if $problem or $display == null {
|
|
28
|
+
@return $problem;
|
|
29
|
+
}
|
|
30
|
+
$words: wordsOf($display);
|
|
31
|
+
$outer: 0;
|
|
32
|
+
$inner: null;
|
|
33
|
+
$inners: 0;
|
|
34
|
+
$list-items: 0;
|
|
35
|
+
@each $word in $words {
|
|
36
|
+
@if string.index($word, "(") {
|
|
37
|
+
@return null;
|
|
38
|
+
}
|
|
39
|
+
$lower: string.to-lower-case(string.unquote($word));
|
|
40
|
+
@if list.length($words) > 1 and not list.index($-outer, $lower) and not list.index($-inner, $lower) and $lower != "list-item" {
|
|
41
|
+
@return "`#{$lower}` only works as the whole value";
|
|
42
|
+
}
|
|
43
|
+
@if list.index($-outer, $lower) {
|
|
44
|
+
$outer: $outer + 1;
|
|
45
|
+
} @else if list.index($-inner, $lower) {
|
|
46
|
+
$inners: $inners + 1;
|
|
47
|
+
$inner: $lower;
|
|
48
|
+
} @else if $lower == "list-item" {
|
|
49
|
+
$list-items: $list-items + 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
@if $outer > 1 {
|
|
53
|
+
@return "it names two outer display types; pass one of block, inline or run-in";
|
|
54
|
+
}
|
|
55
|
+
@if $inners > 1 {
|
|
56
|
+
@return "it names two inner display types; pass one of flow, flow-root, table, flex, grid, ruby or math";
|
|
57
|
+
}
|
|
58
|
+
@if $list-items > 1 {
|
|
59
|
+
@return "it names list-item twice";
|
|
60
|
+
}
|
|
61
|
+
@if $list-items == 1 and $inner and not list.index("flow" "flow-root", $inner) {
|
|
62
|
+
@return "`list-item` only goes with flow or flow-root, not `#{$inner}`";
|
|
63
|
+
}
|
|
64
|
+
@return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
3
67
|
@mixin ellipsis($width: 100%, $display: inline-block) {
|
|
4
|
-
|
|
68
|
+
$problem: -display-problem($display);
|
|
69
|
+
@if $problem {
|
|
70
|
+
@error "`#{meta.inspect($display)}` is not a valid $display for `ellipsis`: #{$problem}. A browser drops the declaration.";
|
|
71
|
+
}
|
|
72
|
+
$problem: sizeProblem($width, $max: true);
|
|
73
|
+
@if $problem {
|
|
74
|
+
@error "`#{meta.inspect($width)}` is not a valid $width for `ellipsis`, which sets max-width: #{$problem}. A browser drops the declaration.";
|
|
75
|
+
}
|
|
76
|
+
// Written without quotes, since `display: "block"` was dropped.
|
|
77
|
+
@if meta.type-of($display) == "string" {
|
|
78
|
+
display: string.unquote($display);
|
|
79
|
+
} @else {
|
|
80
|
+
display: $display;
|
|
81
|
+
}
|
|
5
82
|
max-width: $width;
|
|
6
83
|
text-overflow: ellipsis;
|
|
7
84
|
white-space: nowrap;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
@use "sass:list";
|
|
4
4
|
@use "sass:meta";
|
|
5
5
|
@use "sass:string";
|
|
6
|
+
@use "../internal/sibling-index" as *;
|
|
6
7
|
|
|
7
8
|
@mixin except($params...) {
|
|
8
9
|
@if list.length($params) == 0 {
|
|
@@ -10,6 +11,12 @@
|
|
|
10
11
|
} @else if list.length($params) == 1 {
|
|
11
12
|
$value: list.nth($params, 1);
|
|
12
13
|
@if meta.type-of($value) == "number" {
|
|
14
|
+
// A unit or a fraction makes a selector the browser drops, and 0 excludes
|
|
15
|
+
// nothing; see scss/internal/_sibling-index.scss.
|
|
16
|
+
$problem: siblingIndexProblem($value, "except");
|
|
17
|
+
@if $problem {
|
|
18
|
+
@error "`#{meta.inspect($value)}` is not a valid position for `except`: #{$problem}.";
|
|
19
|
+
}
|
|
13
20
|
@if $value < 0 {
|
|
14
21
|
&:not(:nth-last-of-type(#{$value * -1})) {
|
|
15
22
|
@content;
|
|
@@ -45,6 +52,14 @@
|
|
|
45
52
|
@error "`#{$value}` is not a valid argument for `except`. Pass a positive or negative number, one of `first`, `last`, `odd`, `even`, or a selector such as `.foo`.";
|
|
46
53
|
}
|
|
47
54
|
} @else if list.length($params) > 1 {
|
|
55
|
+
// Every item is checked first. A word used to fail with Sass's own
|
|
56
|
+
// `Undefined operation`, and one bad position dropped the whole rule.
|
|
57
|
+
@each $item in $params {
|
|
58
|
+
$problem: siblingIndexProblem($item, "except", true);
|
|
59
|
+
@if $problem {
|
|
60
|
+
@error "`#{meta.inspect($item)}` is not a valid position for `except`: #{$problem}.";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
48
63
|
$items: "";
|
|
49
64
|
@for $i from 1 through list.length($params) {
|
|
50
65
|
$items: $items + if(list.nth($params, $i) < 0, string.unquote(":not(:nth-last-of-type(#{list.nth($params, $i) * -1}))"), string.unquote(":not(:nth-of-type(#{list.nth($params, $i)}))"));
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
+
@use "sass:meta";
|
|
4
|
+
@use "../internal/color-problem" as *;
|
|
5
|
+
@use "../internal/length-problem" as *;
|
|
6
|
+
|
|
3
7
|
// Draws a focus ring for keyboard users. Two things are usually got wrong by
|
|
4
8
|
// hand, and this writes the version that avoids both.
|
|
5
9
|
//
|
|
@@ -26,6 +30,31 @@
|
|
|
26
30
|
@if not & {
|
|
27
31
|
@error "`focus-ring` styles the element it is called in, so call it inside a selector, such as `.button { @include focus-ring; }`.";
|
|
28
32
|
}
|
|
33
|
+
// The colour goes into the outline shorthand, where Chrome 152 dropped a word
|
|
34
|
+
// that is not a colour, a quoted colour, a length and a CSS-wide keyword, so
|
|
35
|
+
// the ring was not drawn at all. null leaves the colour to the browser.
|
|
36
|
+
@if $color != null {
|
|
37
|
+
$problem: colorProblem($color);
|
|
38
|
+
@if $problem {
|
|
39
|
+
@error "`#{meta.inspect($color)}` is not a valid $color for `focus-ring`: #{$problem}. A browser drops the outline, so no ring is drawn. Pass a colour such as `#1a73e8`, `currentColor`, or a function such as `var(--focus)`.";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// The width goes into the same shorthand, which in Chrome 152 kept a length,
|
|
43
|
+
// 0 and thin, medium or thick, and dropped a percentage, a negative width and
|
|
44
|
+
// a CSS-wide keyword. The offset is a declaration of its own: it kept a
|
|
45
|
+
// negative length and a CSS-wide keyword, and dropped a percentage and thin.
|
|
46
|
+
@if $width != null {
|
|
47
|
+
$problem: lengthProblem($width, $percent: false, $negative: false, $keywords: "thin" "medium" "thick");
|
|
48
|
+
@if $problem {
|
|
49
|
+
@error "`#{meta.inspect($width)}` is not a valid $width for `focus-ring`: #{$problem}. A browser drops the outline, so no ring is drawn.";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
@if $offset != null {
|
|
53
|
+
$problem: lengthProblem($offset, $percent: false, $css-wide: true);
|
|
54
|
+
@if $problem {
|
|
55
|
+
@error "`#{meta.inspect($offset)}` is not a valid $offset for `focus-ring`: #{$problem}. A browser drops the declaration.";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
29
58
|
|
|
30
59
|
&:focus-visible {
|
|
31
60
|
outline: $width solid $color;
|
|
@@ -2,10 +2,113 @@
|
|
|
2
2
|
|
|
3
3
|
@use "sass:list";
|
|
4
4
|
@use "sass:map";
|
|
5
|
+
@use "sass:math";
|
|
5
6
|
@use "sass:meta";
|
|
6
7
|
@use "sass:string";
|
|
7
8
|
@use "../maps/map-for-font-formats" as *;
|
|
8
9
|
@use "../utilities/font-source" as *;
|
|
10
|
+
@use "../internal/is-condition-value" as *;
|
|
11
|
+
@use "../internal/words" as *;
|
|
12
|
+
|
|
13
|
+
// What a @font-face rule keeps in `font-style` and `font-weight`, measured in
|
|
14
|
+
// Chrome 152 by inserting the rule and reading the descriptor back, in any
|
|
15
|
+
// case. font-style kept normal, italic, auto, oblique, and oblique with one or
|
|
16
|
+
// two angles from -90deg to 90deg (`oblique 10deg 20deg`, `oblique 0.2rad`),
|
|
17
|
+
// and dropped a CSS-wide keyword, `oblique 100deg`, an angle without a unit
|
|
18
|
+
// and a weight such as `400`. font-weight kept normal, bold, auto, a number
|
|
19
|
+
// from 1 to 1000 (`450`, `400.5`, `calc(400 + 100)`) and two numbers as a range
|
|
20
|
+
// in either order, and dropped bolder and lighter, a CSS-wide keyword, 0, 1001,
|
|
21
|
+
// three numbers, and a keyword beside a number or another keyword.
|
|
22
|
+
//
|
|
23
|
+
// A quoted value is split on its spaces and checked word by word, but Sass
|
|
24
|
+
// cannot turn the text of a number into one, so a quoted number is checked for
|
|
25
|
+
// its shape and not its range: "1001" and "oblique 100deg" are let through.
|
|
26
|
+
|
|
27
|
+
// A quoted or unquoted number, without a unit, for a weight.
|
|
28
|
+
@function -is-weight-number($word) {
|
|
29
|
+
@if meta.type-of($word) == "number" {
|
|
30
|
+
@return math.is-unitless($word) and $word >= 1 and $word <= 1000;
|
|
31
|
+
}
|
|
32
|
+
@if meta.type-of($word) != "string" {
|
|
33
|
+
@return false;
|
|
34
|
+
}
|
|
35
|
+
$text: string.unquote($word);
|
|
36
|
+
$nonzero: false;
|
|
37
|
+
@for $i from 1 through string.length($text) {
|
|
38
|
+
$character: string.slice($text, $i, $i);
|
|
39
|
+
@if not string.index("0123456789.", $character) {
|
|
40
|
+
@return false;
|
|
41
|
+
}
|
|
42
|
+
@if string.index("123456789", $character) {
|
|
43
|
+
$nonzero: true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
@return $nonzero;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@function -weight-problem($weight) {
|
|
50
|
+
@if $weight == null or meta.type-of($weight) == "calculation" {
|
|
51
|
+
@return null;
|
|
52
|
+
}
|
|
53
|
+
$words: wordsOf($weight);
|
|
54
|
+
@if list.length($words) > 2 {
|
|
55
|
+
@return "a weight is one value, or two numbers for a range such as `100 900`";
|
|
56
|
+
}
|
|
57
|
+
@if list.length($words) == 1 {
|
|
58
|
+
$word: list.nth($words, 1);
|
|
59
|
+
@if meta.type-of($word) == "string" and list.index("normal" "bold" "auto", string.to-lower-case(string.unquote($word))) {
|
|
60
|
+
@return null;
|
|
61
|
+
}
|
|
62
|
+
@if -is-weight-number($word) {
|
|
63
|
+
@return null;
|
|
64
|
+
}
|
|
65
|
+
@return "a weight is normal, bold, auto or a number from 1 to 1000; bolder, lighter and the CSS-wide keywords are dropped";
|
|
66
|
+
}
|
|
67
|
+
@each $word in $words {
|
|
68
|
+
@if not -is-weight-number($word) {
|
|
69
|
+
@return "a range is two numbers from 1 to 1000, such as `100 900`";
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
@return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@function -style-problem($style) {
|
|
76
|
+
@if $style == null {
|
|
77
|
+
@return null;
|
|
78
|
+
}
|
|
79
|
+
$words: wordsOf($style);
|
|
80
|
+
$first: list.nth($words, 1);
|
|
81
|
+
$keyword: null;
|
|
82
|
+
@if meta.type-of($first) == "string" {
|
|
83
|
+
$keyword: string.to-lower-case(string.unquote($first));
|
|
84
|
+
}
|
|
85
|
+
@if list.index("normal" "italic" "auto", $keyword) {
|
|
86
|
+
@if list.length($words) > 1 {
|
|
87
|
+
@return "`#{$keyword}` takes nothing after it; only oblique takes angles";
|
|
88
|
+
}
|
|
89
|
+
@return null;
|
|
90
|
+
}
|
|
91
|
+
@if $keyword != "oblique" {
|
|
92
|
+
@return "a style is normal, italic, oblique or auto; the CSS-wide keywords are dropped";
|
|
93
|
+
}
|
|
94
|
+
@if list.length($words) > 3 {
|
|
95
|
+
@return "oblique takes at most two angles";
|
|
96
|
+
}
|
|
97
|
+
@for $i from 2 through list.length($words) {
|
|
98
|
+
$angle: list.nth($words, $i);
|
|
99
|
+
@if meta.type-of($angle) == "number" {
|
|
100
|
+
@if not isConditionValue($angle, "angle") {
|
|
101
|
+
@return "`#{$angle}` is not an angle; pass one such as `10deg`";
|
|
102
|
+
}
|
|
103
|
+
@if $angle < -90deg or $angle > 90deg {
|
|
104
|
+
@return "an oblique angle is between -90deg and 90deg";
|
|
105
|
+
}
|
|
106
|
+
} @else if not isConditionValue($angle, "angle") {
|
|
107
|
+
@return "`#{$angle}` is not an angle; pass one such as `10deg`";
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
@return null;
|
|
111
|
+
}
|
|
9
112
|
|
|
10
113
|
@mixin font-face(
|
|
11
114
|
$font-family,
|
|
@@ -51,7 +154,10 @@
|
|
|
51
154
|
@error "`#{meta.inspect($font-weight)}` is not a valid $font-weight for `font-face`. A custom property cannot supply it, because a @font-face rule drops var() in a descriptor. Pass the weight itself, such as `700`, or a range such as `160 700`.";
|
|
52
155
|
}
|
|
53
156
|
|
|
54
|
-
|
|
157
|
+
// A number in $font-style is a weight. Only the hundreds used to be read
|
|
158
|
+
// that way, so `font-face("I", "/f/i", 450)` wrote `font-style: 450`, which
|
|
159
|
+
// a @font-face rule drops; any weight a rule keeps, 1 to 1000, is read so.
|
|
160
|
+
@if meta.type-of($font-style) == "number" and math.is-unitless($font-style) and $font-style >= 1 and $font-style <= 1000 {
|
|
55
161
|
$font-weight: $font-style;
|
|
56
162
|
$font-style: normal;
|
|
57
163
|
} @else if not
|
|
@@ -71,6 +177,16 @@
|
|
|
71
177
|
}
|
|
72
178
|
}
|
|
73
179
|
|
|
180
|
+
// Checked after the reinterpretation above, on the values that are written.
|
|
181
|
+
$problem: -style-problem($font-style);
|
|
182
|
+
@if $problem {
|
|
183
|
+
@error "`#{meta.inspect($font-style)}` is not a valid $font-style for `font-face`: #{$problem}. A @font-face rule drops the descriptor.";
|
|
184
|
+
}
|
|
185
|
+
$problem: -weight-problem($font-weight);
|
|
186
|
+
@if $problem {
|
|
187
|
+
@error "`#{meta.inspect($font-weight)}` is not a valid $font-weight for `font-face`: #{$problem}. A @font-face rule drops the descriptor.";
|
|
188
|
+
}
|
|
189
|
+
|
|
74
190
|
// $font-display comes last so the reinterpretation of $font-style above is
|
|
75
191
|
// left alone, and it is written only when given: the browser's default is
|
|
76
192
|
// what a call without it has always had. Measured in Chrome 152, a
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "../internal/gradient" as *;
|
|
4
|
+
|
|
5
|
+
// One mixin for linear, radial and conic gradients, plain or repeating, with an
|
|
6
|
+
// optional colour interpolation space. It replaced linear-gradient and
|
|
7
|
+
// radial-gradient in 3.0.0; MIGRATION.md has each old call's new form.
|
|
8
|
+
//
|
|
9
|
+
// It writes background-image, not the background shorthand: measured in Chrome
|
|
10
|
+
// 152, the shorthand reset a background-color set before it to transparent.
|
|
11
|
+
// What each argument takes, and what was measured, is in
|
|
12
|
+
// scss/internal/_gradient.scss.
|
|
13
|
+
@mixin gradient(
|
|
14
|
+
$colors,
|
|
15
|
+
$type: linear,
|
|
16
|
+
$direction: null,
|
|
17
|
+
$shape: null,
|
|
18
|
+
$position: null,
|
|
19
|
+
$from: null,
|
|
20
|
+
$in: null,
|
|
21
|
+
$repeating: false
|
|
22
|
+
) {
|
|
23
|
+
$value: gradientOf($colors, $type, $direction, $shape, $position, $from, $in, $repeating);
|
|
24
|
+
// Written without the space first. A browser that does not know `in` drops
|
|
25
|
+
// the second declaration and keeps this one; measured in Chrome by giving it
|
|
26
|
+
// a space name it does not know.
|
|
27
|
+
@if $in != null {
|
|
28
|
+
background-image: gradientOf($colors, $type, $direction, $shape, $position, $from, null, $repeating, $warn: false);
|
|
29
|
+
}
|
|
30
|
+
background-image: $value;
|
|
31
|
+
}
|
package/scss/library/_index.scss
CHANGED
|
@@ -27,16 +27,15 @@
|
|
|
27
27
|
@forward "except";
|
|
28
28
|
@forward "focus-ring";
|
|
29
29
|
@forward "font-face";
|
|
30
|
+
@forward "gradient";
|
|
30
31
|
@forward "hide";
|
|
31
32
|
@forward "line-clamp";
|
|
32
|
-
@forward "linear-gradient";
|
|
33
33
|
@forward "loadify";
|
|
34
34
|
@forward "motion-safe";
|
|
35
35
|
@forward "only";
|
|
36
36
|
@forward "placeholder";
|
|
37
37
|
@forward "placeholder-shown";
|
|
38
38
|
@forward "position";
|
|
39
|
-
@forward "radial-gradient";
|
|
40
39
|
@forward "remove";
|
|
41
40
|
@forward "reset-css";
|
|
42
41
|
@forward "reset-figure";
|
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
-
@use "sass:list";
|
|
4
3
|
@use "sass:math";
|
|
5
4
|
@use "sass:meta";
|
|
6
|
-
@use "
|
|
7
|
-
|
|
8
|
-
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
9
|
-
// stays text, so `"var(--x)"` is not a call.
|
|
10
|
-
@function -is-css-function($value, $names) {
|
|
11
|
-
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
12
|
-
@return false;
|
|
13
|
-
}
|
|
14
|
-
$open: string.index($value, "(");
|
|
15
|
-
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
16
|
-
}
|
|
5
|
+
@use "../internal/is-css-function" as *;
|
|
17
6
|
|
|
18
7
|
// Truncates text after a number of lines. `ellipsis` does one line; this does
|
|
19
8
|
// several, and needs five declarations rather than one because -webkit-line-clamp
|
|
@@ -33,7 +22,7 @@
|
|
|
33
22
|
// what actually does the work today.
|
|
34
23
|
@mixin line-clamp($lines: 3) {
|
|
35
24
|
// var() is resolved by the browser, so only a literal count is checked.
|
|
36
|
-
@if $lines != none and not
|
|
25
|
+
@if $lines != none and not isCssFunction($lines, "var" "env") {
|
|
37
26
|
@if meta.type-of($lines) != "number" or not math.is-unitless($lines) {
|
|
38
27
|
@error "`#{$lines}` is not a valid $lines for `line-clamp`. Pass a whole number of lines, or `none` to undo a clamp.";
|
|
39
28
|
}
|