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
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:meta";
|
|
4
|
+
@use "sass:string";
|
|
5
|
+
@use "is-css-function" as *;
|
|
6
|
+
|
|
7
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
8
|
+
|
|
9
|
+
// An image path goes into url(). A var(), url(), image-set() or gradient is
|
|
10
|
+
// already an image, and wrapping it produced url(var(--x)), which loads nothing.
|
|
11
|
+
//
|
|
12
|
+
// $unquote is there because the copies this replaced differed:
|
|
13
|
+
// background-dots and background-stripes wrote `url(a.png)`, the other three
|
|
14
|
+
// `url("a.png")`. Both load the same file, and keeping each as it was means no
|
|
15
|
+
// stylesheet changes.
|
|
16
|
+
//
|
|
17
|
+
// What it refuses, measured in Chrome 152:
|
|
18
|
+
//
|
|
19
|
+
// - a list where one image is meant: `url(16 9)` was dropped;
|
|
20
|
+
// - a number, a colour or a boolean: `url(42)`, `url(#ff0000)` and `url(true)`
|
|
21
|
+
// are kept, but ask for a file named 42, a fragment of the page, or a file
|
|
22
|
+
// named true, which is never the image meant. background-dots and
|
|
23
|
+
// background-stripes refused these already.
|
|
24
|
+
//
|
|
25
|
+
// And an unquoted path is quoted when it has to be: `url(a b)`, `url(a(1).png)`
|
|
26
|
+
// and `url(a'b.png)` were dropped, while the same paths in quotes were kept and
|
|
27
|
+
// `url("a b")` resolved to `a%20b`. Every other path is written as before.
|
|
28
|
+
@function imageValue($value, $mixin, $argument, $unquote: false) {
|
|
29
|
+
// paint(), image() and -webkit-cross-fade() were kept as images in Chrome
|
|
30
|
+
// 152 and used to be wrapped into url(paint(...)), which loads nothing;
|
|
31
|
+
// cross-fade(), element() and -moz-element() are in the specification or
|
|
32
|
+
// other engines.
|
|
33
|
+
@if isCssFunction($value, "var" "url" "image-set" "linear-gradient" "radial-gradient" "conic-gradient" "repeating-linear-gradient" "repeating-radial-gradient" "repeating-conic-gradient" "paint" "image" "cross-fade" "-webkit-cross-fade" "element" "-moz-element") {
|
|
34
|
+
@return $value;
|
|
35
|
+
}
|
|
36
|
+
@if meta.type-of($value) == "list" or meta.type-of($value) == "arglist" or meta.type-of($value) == "map" {
|
|
37
|
+
@error "`#{meta.inspect($value)}` is not a valid #{$argument} for `#{$mixin}`: it is a list where one image is meant, and a browser drops `url()` with a list in it. Pass one path as a string, such as `\"/img/hero.png\"`.";
|
|
38
|
+
}
|
|
39
|
+
@if meta.type-of($value) != "string" {
|
|
40
|
+
@error "`#{meta.inspect($value)}` is not a valid #{$argument} for `#{$mixin}`: an image path is a string, and `url(#{meta.inspect($value)})` asks for a file of that name, which is never the image. Pass a path as a string, such as `\"/img/hero.png\"`, or var() or a gradient.";
|
|
41
|
+
}
|
|
42
|
+
@if not $unquote {
|
|
43
|
+
@return url($value);
|
|
44
|
+
}
|
|
45
|
+
$text: string.unquote($value);
|
|
46
|
+
@if not (string.index($text, " ") or string.index($text, "(") or string.index($text, ")") or string.index($text, "'") or string.index($text, "\"")) {
|
|
47
|
+
@return url(string.unquote($value));
|
|
48
|
+
}
|
|
49
|
+
@if string.index($text, "\"") {
|
|
50
|
+
@return string.unquote("url('#{-escaped-single-quotes($text)}')");
|
|
51
|
+
}
|
|
52
|
+
@return string.unquote("url(\"#{$text}\")");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// A path holding a double quote goes into single quotes, so any single quote in
|
|
56
|
+
// it is escaped.
|
|
57
|
+
@function -escaped-single-quotes($text) {
|
|
58
|
+
$result: "";
|
|
59
|
+
@for $i from 1 through string.length($text) {
|
|
60
|
+
$character: string.slice($text, $i, $i);
|
|
61
|
+
@if $character == "'" {
|
|
62
|
+
$result: $result + "\\'";
|
|
63
|
+
} @else {
|
|
64
|
+
$result: $result + $character;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
@return $result;
|
|
68
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:math";
|
|
5
|
+
@use "sass:meta";
|
|
6
|
+
@use "sass:string";
|
|
7
|
+
|
|
8
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
9
|
+
|
|
10
|
+
// Every length unit a width condition kept in Chrome 152, in @media and
|
|
11
|
+
// @container alike and in any case: `(min-width: 10PX)` matched. `x`, `dppx`,
|
|
12
|
+
// `fr`, `s`, `%` and a made-up unit never matched, and neither did a unitless
|
|
13
|
+
// number other than 0.
|
|
14
|
+
$-length-units: "px" "cm" "mm" "q" "in" "pt" "pc" "em" "rem" "ex" "rex" "ch" "rch" "cap" "rcap" "ic" "ric" "lh" "rlh" "vw" "vh" "vi" "vb" "vmin" "vmax" "svw" "svh" "svi" "svb" "svmin" "svmax" "lvw" "lvh" "lvi" "lvb" "lvmin" "lvmax" "dvw" "dvh" "dvi" "dvb" "dvmin" "dvmax" "cqw" "cqh" "cqi" "cqb" "cqmin" "cqmax";
|
|
15
|
+
|
|
16
|
+
// The units a resolution condition kept, also in any case. A unitless number, a
|
|
17
|
+
// length and a negative resolution never matched; `0dppx` was kept.
|
|
18
|
+
$-resolution-units: "dpi" "dpcm" "dppx" "x";
|
|
19
|
+
|
|
20
|
+
// Angles, for an oblique `font-style`: `oblique 0.2rad` was kept in a @font-face
|
|
21
|
+
// rule and `oblique 10`, unitless, was dropped.
|
|
22
|
+
$-angle-units: "deg" "grad" "rad" "turn";
|
|
23
|
+
|
|
24
|
+
// True for a value a @media or @container condition can match: a number in one
|
|
25
|
+
// of the units above, a calculation, or either written as a quoted string, which
|
|
26
|
+
// Sass writes into a condition without its quotes, so `breakpoint(min, "600px")`
|
|
27
|
+
// has always worked. A calculation is taken on trust: `calc(30em + 1px)`,
|
|
28
|
+
// `clamp()`, `min()` and `max()` were all kept, and Sass reduces `calc(10deg)`
|
|
29
|
+
// to a number before it gets here, so that one is checked like any other.
|
|
30
|
+
//
|
|
31
|
+
// $kind is "length" or "resolution" for a condition. A negative length was
|
|
32
|
+
// kept, since it is valid and simply matches every width or none; a negative
|
|
33
|
+
// resolution was not. Two more kinds serve values outside a condition, where a
|
|
34
|
+
// caller rules out a negative itself if the property does: "length-percentage",
|
|
35
|
+
// a length or a percentage, and "angle".
|
|
36
|
+
@function isConditionValue($value, $kind: "length") {
|
|
37
|
+
$units: $-length-units;
|
|
38
|
+
@if $kind == "resolution" {
|
|
39
|
+
$units: $-resolution-units;
|
|
40
|
+
} @else if $kind == "length-percentage" {
|
|
41
|
+
$units: list.append($-length-units, "%");
|
|
42
|
+
} @else if $kind == "angle" {
|
|
43
|
+
$units: $-angle-units;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@if meta.type-of($value) == "calculation" {
|
|
47
|
+
@return true;
|
|
48
|
+
}
|
|
49
|
+
@if meta.type-of($value) == "number" {
|
|
50
|
+
@if math.is-unitless($value) {
|
|
51
|
+
@return ($kind == "length" or $kind == "length-percentage") and $value == 0;
|
|
52
|
+
}
|
|
53
|
+
@if $kind == "resolution" and $value < 0 {
|
|
54
|
+
@return false;
|
|
55
|
+
}
|
|
56
|
+
@return list.index($units, string.to-lower-case(math.unit($value))) != null;
|
|
57
|
+
}
|
|
58
|
+
@if meta.type-of($value) != "string" {
|
|
59
|
+
@return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
$text: string.to-lower-case(string.unquote($value));
|
|
63
|
+
@each $function in "calc(" "clamp(" "min(" "max(" {
|
|
64
|
+
@if string.index($text, $function) == 1 {
|
|
65
|
+
@return true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// A quoted length, such as "600px": the number runs up to the first
|
|
70
|
+
// character that cannot be part of one, and the rest is the unit.
|
|
71
|
+
$unit-start: null;
|
|
72
|
+
$digits: 0;
|
|
73
|
+
@for $i from 1 through string.length($text) {
|
|
74
|
+
$character: string.slice($text, $i, $i);
|
|
75
|
+
@if $unit-start == null {
|
|
76
|
+
@if string.index("0123456789", $character) {
|
|
77
|
+
$digits: $digits + 1;
|
|
78
|
+
} @else if not string.index(".+-", $character) {
|
|
79
|
+
$unit-start: $i;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
@if $digits == 0 {
|
|
84
|
+
@return false;
|
|
85
|
+
}
|
|
86
|
+
@if $unit-start == null {
|
|
87
|
+
// A quoted unitless number: only zero, and only for a length.
|
|
88
|
+
@return ($kind == "length" or $kind == "length-percentage") and not string.index($text, "1") and not string.index($text, "2") and not string.index($text, "3") and not string.index($text, "4") and not string.index($text, "5") and not string.index($text, "6") and not string.index($text, "7") and not string.index($text, "8") and not string.index($text, "9");
|
|
89
|
+
}
|
|
90
|
+
@if $kind == "resolution" and string.index(string.slice($text, 1, $unit-start - 1), "-") {
|
|
91
|
+
@return false;
|
|
92
|
+
}
|
|
93
|
+
@return list.index($units, string.slice($text, $unit-start)) != null;
|
|
94
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
6
|
+
|
|
7
|
+
// scss/internal/ holds checks the mixins share. No _index.scss forwards it, so
|
|
8
|
+
// a user cannot reach these functions and they are not public API: through
|
|
9
|
+
// `@use "gerillass" as *` or `@import` a call to one renders as literal CSS,
|
|
10
|
+
// and through a namespace it is an undefined function. Their names must not
|
|
11
|
+
// start with `-` or `_`, which would make them private to their own file.
|
|
12
|
+
|
|
13
|
+
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
14
|
+
// stays text, so `"var(--x)"` is not a call.
|
|
15
|
+
@function isCssFunction($value, $names) {
|
|
16
|
+
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
17
|
+
@return false;
|
|
18
|
+
}
|
|
19
|
+
$open: string.index($value, "(");
|
|
20
|
+
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
6
|
+
|
|
7
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
8
|
+
|
|
9
|
+
// A size Sass can use inside calc(): a number, a calculation such as calc(),
|
|
10
|
+
// min() or clamp(), or var() and env(), which only the browser can resolve.
|
|
11
|
+
// Anything else would pass silently through calc(): `calc(nonsense * 5)`
|
|
12
|
+
// compiles.
|
|
13
|
+
@function isSize($value) {
|
|
14
|
+
@if meta.type-of($value) == "number" or meta.type-of($value) == "calculation" {
|
|
15
|
+
@return true;
|
|
16
|
+
}
|
|
17
|
+
@if meta.type-of($value) == "string" and string.slice(meta.inspect($value), 1, 1) != "\"" {
|
|
18
|
+
$open: string.index($value, "(");
|
|
19
|
+
@return $open != null and list.index("var" "env", string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
20
|
+
}
|
|
21
|
+
@return false;
|
|
22
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
6
|
+
@use "words" as *;
|
|
7
|
+
|
|
8
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
9
|
+
|
|
10
|
+
$-css-wide: "inherit" "initial" "unset" "revert" "revert-layer";
|
|
11
|
+
|
|
12
|
+
// Returns what is wrong with $value as a keyword value, or null when it is fine.
|
|
13
|
+
// It checks the kind of each word, not whether the words make sense together;
|
|
14
|
+
// a mixin whose property has a grammar, such as display, checks that itself.
|
|
15
|
+
//
|
|
16
|
+
// - null is fine: the declaration is left out, as it always was.
|
|
17
|
+
// - Any word holding a parenthesis makes the whole value fine when $functions is
|
|
18
|
+
// true. var(), env() and calc() are resolved by the browser, and a value such
|
|
19
|
+
// as `var(--x) auto` cannot be judged here. In a @font-face descriptor, which
|
|
20
|
+
// drops var(), the caller passes false.
|
|
21
|
+
// - Up to $max-words words, each one of $keywords in any case; `STICKY` and
|
|
22
|
+
// `BOTH` were kept in Chrome 152.
|
|
23
|
+
// - A CSS-wide keyword only on its own: `overflow: inherit auto` was dropped.
|
|
24
|
+
// - A vendor-prefixed word when $vendor is true. Chrome drops `-webkit-sticky`
|
|
25
|
+
// and `-moz-box`, but other engines use them, so refusing one could break a
|
|
26
|
+
// stylesheet written for Safari.
|
|
27
|
+
@function keywordProblem($value, $keywords, $max-words: 1, $functions: true, $vendor: false) {
|
|
28
|
+
@if $value == null {
|
|
29
|
+
@return null;
|
|
30
|
+
}
|
|
31
|
+
@if meta.type-of($value) == "list" and list.separator($value) == "comma" {
|
|
32
|
+
@return "it takes a space-separated value, not a comma-separated list";
|
|
33
|
+
}
|
|
34
|
+
$words: wordsOf($value);
|
|
35
|
+
@if list.length($words) == 0 {
|
|
36
|
+
@return "it is empty";
|
|
37
|
+
}
|
|
38
|
+
@each $word in $words {
|
|
39
|
+
@if meta.type-of($word) == "string" and string.index($word, "(") {
|
|
40
|
+
@if $functions {
|
|
41
|
+
@return null;
|
|
42
|
+
}
|
|
43
|
+
@return "a function cannot supply it here";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
@if list.length($words) > $max-words {
|
|
47
|
+
@if $max-words == 1 {
|
|
48
|
+
@return "it takes one keyword, and got #{list.length($words)}";
|
|
49
|
+
}
|
|
50
|
+
@return "it takes at most #{$max-words} keywords, and got #{list.length($words)}";
|
|
51
|
+
}
|
|
52
|
+
$expected: list.join($keywords, (), $separator: comma);
|
|
53
|
+
@each $word in $words {
|
|
54
|
+
@if meta.type-of($word) != "string" {
|
|
55
|
+
@if list.length($words) == 1 {
|
|
56
|
+
@return "it takes a keyword, one of: #{$expected}";
|
|
57
|
+
}
|
|
58
|
+
@return "`#{meta.inspect($word)}` is not a keyword; pass words from: #{$expected}";
|
|
59
|
+
}
|
|
60
|
+
$lower: string.to-lower-case(string.unquote($word));
|
|
61
|
+
@if list.index($-css-wide, $lower) {
|
|
62
|
+
@if list.length($words) > 1 {
|
|
63
|
+
@return "`#{$lower}` only works as the whole value";
|
|
64
|
+
}
|
|
65
|
+
} @else if not list.index($keywords, $lower) {
|
|
66
|
+
$prefixed: string.index($lower, "-webkit-") == 1 or string.index($lower, "-moz-") == 1 or string.index($lower, "-ms-") == 1 or string.index($lower, "-o-") == 1;
|
|
67
|
+
@if not ($vendor and $prefixed) {
|
|
68
|
+
@if list.length($words) == 1 {
|
|
69
|
+
@return "it is not one of: #{$expected}";
|
|
70
|
+
}
|
|
71
|
+
@return "`#{$lower}` is not one of: #{$expected}";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
@return null;
|
|
76
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:math";
|
|
5
|
+
@use "sass:meta";
|
|
6
|
+
@use "sass:string";
|
|
7
|
+
@use "is-condition-value" as *;
|
|
8
|
+
|
|
9
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
10
|
+
|
|
11
|
+
// Maths functions a browser resolves to a length, and the substitutions whose
|
|
12
|
+
// value only the browser knows. Sass reduces most maths on plain numbers before
|
|
13
|
+
// they get here (`round(10.5px, 1px)` arrives as 11px), so these are the forms
|
|
14
|
+
// it leaves as text.
|
|
15
|
+
$-functions: "var" "env" "attr" "calc" "clamp" "min" "max" "round" "abs" "sign" "mod" "rem" "hypot" "sqrt" "pow" "exp" "log";
|
|
16
|
+
$-css-wide: "inherit" "initial" "unset" "revert" "revert-layer";
|
|
17
|
+
|
|
18
|
+
// Returns what is wrong with $value as one length for a property, or null when
|
|
19
|
+
// a browser keeps it. Each caller passes what its property takes, measured in
|
|
20
|
+
// Chrome 152 (see todos/silent-values-plan.md, S7):
|
|
21
|
+
//
|
|
22
|
+
// - $percent: whether a percentage works (width yes, outline-width no);
|
|
23
|
+
// - $negative: whether a negative length works (outline-offset yes, width no);
|
|
24
|
+
// - $keywords: the words the property takes, such as auto or thin;
|
|
25
|
+
// - $functions: sizing functions beyond maths, such as anchor-size;
|
|
26
|
+
// - $css-wide: whether a CSS-wide keyword works, which is only as a whole
|
|
27
|
+
// declaration;
|
|
28
|
+
// - $quoted: whether a quoted length works, which is only where the mixin
|
|
29
|
+
// interpolates it; written raw, `width: "10px"` is dropped.
|
|
30
|
+
//
|
|
31
|
+
// A unitless 0 is accepted; a caller whose output breaks on it handles it.
|
|
32
|
+
// A calculation is taken on trust, since Sass keeps it only when it cannot
|
|
33
|
+
// reduce it.
|
|
34
|
+
@function lengthProblem($value, $percent: true, $negative: true, $keywords: (), $functions: (), $css-wide: false, $quoted: false) {
|
|
35
|
+
@if meta.type-of($value) == "calculation" {
|
|
36
|
+
@return null;
|
|
37
|
+
}
|
|
38
|
+
@if meta.type-of($value) == "list" and list.length($value) > 1 {
|
|
39
|
+
@return "it is several values where one length is meant";
|
|
40
|
+
}
|
|
41
|
+
@if meta.type-of($value) == "number" {
|
|
42
|
+
@if math.is-unitless($value) {
|
|
43
|
+
@if $value == 0 {
|
|
44
|
+
@return null;
|
|
45
|
+
}
|
|
46
|
+
@return "a unitless number is not a length; add a unit, such as `#{$value}px`";
|
|
47
|
+
}
|
|
48
|
+
@if math.unit($value) == "%" and not $percent {
|
|
49
|
+
@return "a percentage does not work here";
|
|
50
|
+
}
|
|
51
|
+
@if not isConditionValue($value, "length-percentage") {
|
|
52
|
+
@return "`#{math.unit($value)}` is not a length unit";
|
|
53
|
+
}
|
|
54
|
+
@if not $negative and $value < 0 {
|
|
55
|
+
@return "a length below zero does not work here";
|
|
56
|
+
}
|
|
57
|
+
@return null;
|
|
58
|
+
}
|
|
59
|
+
@if meta.type-of($value) != "string" {
|
|
60
|
+
@return "it is not a length";
|
|
61
|
+
}
|
|
62
|
+
$kind: "length";
|
|
63
|
+
@if $percent {
|
|
64
|
+
$kind: "length-percentage";
|
|
65
|
+
}
|
|
66
|
+
@if string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
67
|
+
@if $quoted and isConditionValue($value, $kind) {
|
|
68
|
+
@return null;
|
|
69
|
+
}
|
|
70
|
+
@return "a length in quotes is text here; write it without quotes";
|
|
71
|
+
}
|
|
72
|
+
$lower: string.to-lower-case($value);
|
|
73
|
+
$open: string.index($lower, "(");
|
|
74
|
+
@if $open {
|
|
75
|
+
$name: string.slice($lower, 1, $open - 1);
|
|
76
|
+
@if list.index($-functions, $name) or list.index($functions, $name) {
|
|
77
|
+
@return null;
|
|
78
|
+
}
|
|
79
|
+
@return "`#{$name}()` does not give a length here";
|
|
80
|
+
}
|
|
81
|
+
@if string.index($lower, " ") {
|
|
82
|
+
@return "it is several values where one length is meant";
|
|
83
|
+
}
|
|
84
|
+
// Interpolation, such as `#{$n}px`, gives an unquoted string rather than a
|
|
85
|
+
// number, and it is written into the CSS as it reads, so its content decides.
|
|
86
|
+
@if isConditionValue($value, $kind) {
|
|
87
|
+
@if not $negative and string.index($lower, "-") == 1 {
|
|
88
|
+
@return "a length below zero does not work here";
|
|
89
|
+
}
|
|
90
|
+
@return null;
|
|
91
|
+
}
|
|
92
|
+
@if string.index($lower, "%") and isConditionValue($value, "length-percentage") {
|
|
93
|
+
@return "a percentage does not work here";
|
|
94
|
+
}
|
|
95
|
+
@if list.index($keywords, $lower) {
|
|
96
|
+
@return null;
|
|
97
|
+
}
|
|
98
|
+
@if list.index($-css-wide, $lower) {
|
|
99
|
+
@if $css-wide {
|
|
100
|
+
@return null;
|
|
101
|
+
}
|
|
102
|
+
@return "a CSS-wide keyword only works as a whole declaration, not here";
|
|
103
|
+
}
|
|
104
|
+
@if list.length($keywords) > 0 {
|
|
105
|
+
@return "it is not a length or one of: #{list.join($keywords, (), $separator: comma)}";
|
|
106
|
+
}
|
|
107
|
+
@return "it is not a length";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// lengthProblem for a width or height, and for max-width with $max. Measured in
|
|
111
|
+
// Chrome 152: width and height keep the intrinsic keywords, stretch,
|
|
112
|
+
// -webkit-fill-available, anchor-size(), calc-size() and a CSS-wide keyword;
|
|
113
|
+
// max-width keeps none where width keeps auto, and drops calc-size(). Both drop
|
|
114
|
+
// a negative length. -moz-available is Firefox's spelling of stretch; Chrome
|
|
115
|
+
// drops it, and it is let through like the other vendor keywords.
|
|
116
|
+
//
|
|
117
|
+
// null is accepted, since Sass leaves the declaration out, as it always has.
|
|
118
|
+
@function sizeProblem($value, $max: false) {
|
|
119
|
+
@if $value == null {
|
|
120
|
+
@return null;
|
|
121
|
+
}
|
|
122
|
+
$keywords: "min-content" "max-content" "fit-content" "stretch" "-webkit-fill-available" "-moz-available";
|
|
123
|
+
@if $max {
|
|
124
|
+
@return lengthProblem($value, $negative: false, $keywords: list.append($keywords, "none"), $functions: ("anchor-size",), $css-wide: true);
|
|
125
|
+
}
|
|
126
|
+
@return lengthProblem($value, $negative: false, $keywords: list.append($keywords, "auto"), $functions: "anchor-size" "calc-size", $css-wide: true);
|
|
127
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:math";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
|
|
6
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
7
|
+
|
|
8
|
+
// Returns what is wrong with $value as a sibling position for `only` or
|
|
9
|
+
// `except`, or null when it is a whole number other than 0. Measured in Chrome
|
|
10
|
+
// 152 on six siblings:
|
|
11
|
+
//
|
|
12
|
+
// - a number with any unit or a fraction, `:nth-of-type(10deg)`,
|
|
13
|
+
// `:nth-of-type(10px)`, `:nth-of-type(1.5)`, is an invalid selector, and the
|
|
14
|
+
// browser drops the whole rule. In a selector list that takes every other
|
|
15
|
+
// selector with it: `.a:nth-of-type(1), .a:nth-of-type(10deg)` was dropped.
|
|
16
|
+
// - `:nth-of-type(0)` is valid and matched none of the six, and
|
|
17
|
+
// `:not(:nth-of-type(0))` matched all six, since positions count from 1.
|
|
18
|
+
// - a negative number, `+3` and `99999` were kept; `only` and `except` turn a
|
|
19
|
+
// negative position into :nth-last-of-type.
|
|
20
|
+
//
|
|
21
|
+
// $several is true when the value is one of several arguments, where only
|
|
22
|
+
// positions are taken; alone, a word is a keyword or a selector.
|
|
23
|
+
@function siblingIndexProblem($value, $mixin, $several: false) {
|
|
24
|
+
@if meta.type-of($value) != "number" {
|
|
25
|
+
@if $several {
|
|
26
|
+
@return "several arguments are all positions, whole numbers such as `1` or `-2`. Pass a keyword such as `first`, or a selector such as `.foo`, on its own";
|
|
27
|
+
}
|
|
28
|
+
@return null;
|
|
29
|
+
}
|
|
30
|
+
// A multiple of n, such as `3n`, reaches here as a number whose unit is n.
|
|
31
|
+
// Measured in Chrome 152, :nth-of-type(3n) is valid and matched two of six
|
|
32
|
+
// siblings, and main compiled only(3n) to it, so it is accepted. Its
|
|
33
|
+
// coefficient is checked like a position: `1.5n` was dropped and `0n`
|
|
34
|
+
// matched nothing.
|
|
35
|
+
$coefficient: $value;
|
|
36
|
+
@if math.unit($value) == "n" {
|
|
37
|
+
$coefficient: math.div($value, 1n);
|
|
38
|
+
} @else if not math.is-unitless($value) {
|
|
39
|
+
@return "a position is a whole number such as `2`, or a multiple of n such as `3n`, and `:nth-of-type(#{math.abs($value)})` is an invalid selector, so the browser would drop the rule. Pass a number such as `2`, or `-2` to count from the end";
|
|
40
|
+
}
|
|
41
|
+
@if math.round($coefficient) != $coefficient {
|
|
42
|
+
@return "a position is a whole number, and `:nth-of-type(#{math.abs($value)})` is an invalid selector, so the browser would drop the rule. Pass a number such as `2`, or `-2` to count from the end";
|
|
43
|
+
}
|
|
44
|
+
@if $coefficient == 0 {
|
|
45
|
+
@if $mixin == "except" {
|
|
46
|
+
@return "positions count from 1, so `:not(:nth-of-type(0))` excludes nothing. Pass `1` for the first, or `-1` for the last";
|
|
47
|
+
}
|
|
48
|
+
@return "positions count from 1, so `:nth-of-type(0)` matches nothing. Pass `1` for the first, or `-1` for the last";
|
|
49
|
+
}
|
|
50
|
+
@return null;
|
|
51
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@charset "UTF-8";
|
|
2
|
+
|
|
3
|
+
@use "sass:list";
|
|
4
|
+
@use "sass:meta";
|
|
5
|
+
@use "sass:string";
|
|
6
|
+
|
|
7
|
+
// Shared by the mixins and not public API; see _is-css-function.scss.
|
|
8
|
+
|
|
9
|
+
// The words of a value, as a space-separated list. A quoted string such as
|
|
10
|
+
// "block flow-root" is split on its spaces, the way the browser reads it once
|
|
11
|
+
// the quotes are gone; a space-separated list gives its items; anything else is
|
|
12
|
+
// one word. Empty words from repeated spaces are skipped.
|
|
13
|
+
@function wordsOf($value) {
|
|
14
|
+
@if meta.type-of($value) == "list" and list.separator($value) != "comma" {
|
|
15
|
+
@return $value;
|
|
16
|
+
}
|
|
17
|
+
@if meta.type-of($value) != "string" {
|
|
18
|
+
@return ($value,);
|
|
19
|
+
}
|
|
20
|
+
$words: ();
|
|
21
|
+
$rest: $value;
|
|
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
|
+
}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
3
|
@use "sass:map";
|
|
4
|
+
@use "sass:math";
|
|
5
|
+
@use "sass:meta";
|
|
6
|
+
@use "sass:string";
|
|
4
7
|
@use "../maps/map-for-breakpoints" as *;
|
|
8
|
+
@use "../internal/length-problem" as *;
|
|
5
9
|
|
|
6
10
|
@mixin adaptive($gutter: 30px) {
|
|
11
|
+
// The gutter is subtracted twice inside calc(), which in Chrome 152 kept a
|
|
12
|
+
// length, a percentage, a negative length and var(), and dropped the
|
|
13
|
+
// max-width for a word, a CSS-wide keyword, a unitless number and a unit that
|
|
14
|
+
// is not a length. A quoted length works, since it is interpolated.
|
|
15
|
+
$problem: lengthProblem($gutter, $functions: ("anchor-size",), $quoted: true);
|
|
16
|
+
@if $problem {
|
|
17
|
+
@error "`#{meta.inspect($gutter)}` is not a valid $gutter for `adaptive`: #{$problem}. A browser drops the max-width at every breakpoint.";
|
|
18
|
+
}
|
|
19
|
+
// A unitless 0 made `calc(576px - 0 * 2)`, a length minus a number, which was
|
|
20
|
+
// dropped; 0px is kept.
|
|
21
|
+
@if (meta.type-of($gutter) == "number" and math.is-unitless($gutter)) or (meta.type-of($gutter) == "string" and string.unquote($gutter) == string.unquote("0")) {
|
|
22
|
+
$gutter: 0px;
|
|
23
|
+
}
|
|
7
24
|
$actual-breakpoints: map.remove($map-for-breakpoints, "xsmall");
|
|
8
25
|
margin: 0 auto;
|
|
9
26
|
@each $item, $value in $actual-breakpoints {
|
package/scss/library/_after.scss
CHANGED
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
@charset "UTF-8";
|
|
2
2
|
|
|
3
|
-
@use "sass:list";
|
|
4
3
|
@use "sass:meta";
|
|
5
4
|
@use "sass:string";
|
|
6
|
-
|
|
7
|
-
// True for an unquoted call to one of $names, such as var(--x). A quoted string
|
|
8
|
-
// stays text, so `"var(--x)"` is not a call.
|
|
9
|
-
@function -is-css-function($value, $names) {
|
|
10
|
-
@if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
|
|
11
|
-
@return false;
|
|
12
|
-
}
|
|
13
|
-
$open: string.index($value, "(");
|
|
14
|
-
@return $open != null and list.index($names, string.to-lower-case(string.slice($value, 1, $open - 1))) != null;
|
|
15
|
-
}
|
|
5
|
+
@use "../internal/is-css-function" as *;
|
|
16
6
|
|
|
17
7
|
@mixin after($content: null) {
|
|
18
8
|
&::after {
|
|
@@ -20,7 +10,7 @@
|
|
|
20
10
|
@content;
|
|
21
11
|
} @else if meta.type-of($content) != "string" {
|
|
22
12
|
@error "`#{$content}` is not a valid $content for `after`. Pass a string to use as the content value, a data- attribute name such as `\"data-label\"` to render it with attr(), or no argument at all and write the content yourself.";
|
|
23
|
-
} @else if
|
|
13
|
+
} @else if isCssFunction($content, "var" "attr" "counter" "counters") {
|
|
24
14
|
// Quoting would turn the call into text: content: "var(--label)".
|
|
25
15
|
content: $content;
|
|
26
16
|
@content;
|