gerillass 0.0.6 → 2.3.1

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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +13 -0
  3. data/README.md +328 -0
  4. data/SKILL.md +283 -0
  5. data/gerillass.json +2551 -0
  6. data/lib/gerillass/engine.rb +55 -0
  7. data/lib/gerillass/jekyll.rb +13 -0
  8. data/lib/gerillass.rb +26 -0
  9. data/scss/_gerillass.scss +15 -0
  10. data/scss/internal/_color-problem.scss +99 -0
  11. data/scss/internal/_color-stops-problem.scss +94 -0
  12. data/scss/internal/_condition-width.scss +22 -0
  13. data/scss/internal/_custom-property-in.scss +25 -0
  14. data/scss/internal/_image-value.scss +68 -0
  15. data/scss/internal/_is-condition-value.scss +94 -0
  16. data/scss/internal/_is-css-function.scss +21 -0
  17. data/scss/internal/_is-size.scss +22 -0
  18. data/scss/internal/_keyword-value.scss +76 -0
  19. data/scss/internal/_length-problem.scss +127 -0
  20. data/scss/internal/_sibling-index.scss +51 -0
  21. data/scss/internal/_words.scss +35 -0
  22. data/scss/library/_adaptive.scss +31 -0
  23. data/scss/library/_after.scss +28 -0
  24. data/scss/library/_all-buttons.scss +21 -0
  25. data/scss/library/_all-text-inputs.scss +21 -0
  26. data/{core → scss}/library/_antialias.scss +5 -1
  27. data/scss/library/_aspect-ratio.scss +27 -0
  28. data/scss/library/_background-dots.scss +103 -0
  29. data/scss/library/_background-image.scss +113 -0
  30. data/scss/library/_background-stripes.scss +99 -0
  31. data/scss/library/_before.scss +28 -0
  32. data/scss/library/_border-box.scss +30 -0
  33. data/scss/library/_border-radius.scss +164 -0
  34. data/scss/library/_brand-logo.scss +33 -0
  35. data/scss/library/_breakpoint.scss +96 -0
  36. data/scss/library/_breakpointer.scss +40 -0
  37. data/scss/library/_center.scss +19 -0
  38. data/scss/library/_circle.scss +15 -0
  39. data/{core → scss}/library/_clearfix.scss +1 -1
  40. data/scss/library/_columnizer.scss +125 -0
  41. data/scss/library/_container-query.scss +119 -0
  42. data/scss/library/_container.scss +72 -0
  43. data/scss/library/_counter.scss +59 -0
  44. data/scss/library/_ellipsis.scss +87 -0
  45. data/scss/library/_escape-to-parent.scss +12 -0
  46. data/scss/library/_except.scss +71 -0
  47. data/scss/library/_focus-ring.scss +63 -0
  48. data/scss/library/_font-face.scss +240 -0
  49. data/scss/library/_hide.scss +25 -0
  50. data/scss/library/_index.scss +58 -0
  51. data/scss/library/_line-clamp.scss +38 -0
  52. data/scss/library/_linear-gradient.scss +33 -0
  53. data/scss/library/_loadify.scss +62 -0
  54. data/scss/library/_motion-safe.scss +28 -0
  55. data/scss/library/_only.scss +73 -0
  56. data/scss/library/_placeholder-shown.scss +7 -0
  57. data/scss/library/_placeholder.scss +19 -0
  58. data/scss/library/_position.scss +72 -0
  59. data/scss/library/_radial-gradient.scss +184 -0
  60. data/scss/library/_remove.scss +40 -0
  61. data/scss/library/_reset-css.scss +57 -0
  62. data/scss/library/_reset-figure.scss +10 -0
  63. data/scss/library/_resizable.scss +34 -0
  64. data/scss/library/_responsive-image.scss +6 -0
  65. data/scss/library/_scissors.scss +34 -0
  66. data/scss/library/_screen-agent.scss +34 -0
  67. data/scss/library/_sizer.scss +15 -0
  68. data/scss/library/_smartphone.scss +29 -0
  69. data/scss/library/_sprite.scss +100 -0
  70. data/scss/library/_stretched-link.scss +21 -0
  71. data/scss/library/_tablet.scss +29 -0
  72. data/scss/library/_text-gradient.scss +38 -0
  73. data/scss/library/_text-image.scss +15 -0
  74. data/scss/library/_text-selection.scss +22 -0
  75. data/scss/library/_text-shadow.scss +145 -0
  76. data/scss/library/_text-stroke.scss +43 -0
  77. data/scss/library/_tokens.scss +111 -0
  78. data/scss/library/_triangle.scss +115 -0
  79. data/scss/lists/_index.scss +8 -0
  80. data/scss/lists/_list-of-anchor-pseudo-classes.scss +9 -0
  81. data/scss/lists/_list-of-buttons.scss +8 -0
  82. data/scss/lists/_list-of-counter-styles.scss +59 -0
  83. data/scss/lists/_list-of-directions.scss +12 -0
  84. data/scss/lists/_list-of-length-units.scss +23 -0
  85. data/scss/lists/_list-of-text-inputs.scss +20 -0
  86. data/scss/maps/_index.scss +8 -0
  87. data/scss/maps/_map-for-breakpoints.scss +9 -0
  88. data/scss/maps/_map-for-directions.scss +12 -0
  89. data/scss/maps/_map-for-font-formats.scss +9 -0
  90. data/scss/maps/_map-for-positions.scss +13 -0
  91. data/scss/maps/_map-for-smartphones.scss +72 -0
  92. data/scss/maps/_map-for-tablets.scss +32 -0
  93. data/scss/utilities/_clear-unit.scss +11 -0
  94. data/scss/utilities/_clear-whitespace.scss +15 -0
  95. data/scss/utilities/_convert-to-em.scss +16 -0
  96. data/scss/utilities/_convert-to-number.scss +45 -0
  97. data/scss/utilities/_fill-nulls.scss +18 -0
  98. data/scss/utilities/_fluid.scss +76 -0
  99. data/scss/utilities/_font-sizer.scss +19 -0
  100. data/scss/utilities/_font-source.scss +23 -0
  101. data/scss/utilities/_index.scss +25 -0
  102. data/scss/utilities/_is-color.scss +16 -0
  103. data/scss/utilities/_is-gutter.scss +24 -0
  104. data/scss/utilities/_is-number.scss +11 -0
  105. data/scss/utilities/_is-time.scss +14 -0
  106. data/scss/utilities/_map-deep-get.scss +10 -0
  107. data/scss/utilities/_pixelify.scss +20 -0
  108. data/scss/utilities/_pseudo-selector.scss +12 -0
  109. data/scss/utilities/_remify.scss +16 -0
  110. data/scss/utilities/_shade.scss +10 -0
  111. data/scss/utilities/_shorthand-property.scss +17 -0
  112. data/scss/utilities/_tint.scss +10 -0
  113. data/scss/utilities/_validate-breakpoint.scss +41 -0
  114. data/scss/utilities/_validate-length.scss +37 -0
  115. data/scss/utilities/_validate-ratio.scss +77 -0
  116. data/scss/utilities/_validate-scissors.scss +34 -0
  117. metadata +130 -46
  118. data/core/_gerillass.scss +0 -4
  119. data/core/library/_before.scss +0 -18
  120. data/core/library/_border-box.scss +0 -26
@@ -0,0 +1,240 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:list";
4
+ @use "sass:map";
5
+ @use "sass:math";
6
+ @use "sass:meta";
7
+ @use "sass:string";
8
+ @use "../maps/map-for-font-formats" as *;
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
+ }
112
+
113
+ @mixin font-face(
114
+ $font-family,
115
+ $file-path,
116
+ $font-style: normal,
117
+ $font-weight: 400,
118
+ $file-formats: eot woff2 woff ttf svg,
119
+ $font-display: null
120
+ ) {
121
+ @if & {
122
+ @error "You must call the mixin at the root level of your style sheet, not in the `#{&+'{'+'}'}` selector.";
123
+ } @else if meta.type-of($font-family) != "string" {
124
+ @error "`#{$font-family}` is not a valid $font-family for `font-face`. Pass the family name as a string, such as `\"Inter\"`.";
125
+ } @else if meta.type-of($file-path) != "string" {
126
+ @error "`#{$file-path}` is not a valid $file-path for `font-face`. Pass the path to the font files without an extension, as a string.";
127
+ } @else if string.slice(meta.inspect($file-path), 1, 1) != "\"" and string.index($file-path, "var(") {
128
+ // The path is written into url("..."), where var() is only text: the
129
+ // browser would request a file literally named var(--x).woff2.
130
+ @error "`#{$file-path}` is not a valid $file-path for `font-face`. A custom property cannot supply a font path, because the path is written into url() as text. Pass the path as a string.";
131
+ } @else if string.slice(meta.inspect($font-family), 1, 1) != "\"" and string.index($font-family, "var(") {
132
+ // Measured in Chrome 152, a @font-face rule dropped `font-family: var(--f)`,
133
+ // and a rule with no family is never used. A quoted "var(--f)" is only a
134
+ // name, which the browser kept, so it is left alone like a quoted path.
135
+ @error "`#{$font-family}` is not a valid $font-family for `font-face`. A custom property cannot supply it, because a @font-face rule drops var() in a descriptor, and without a family the font is never used. Pass the family name as a string, such as `\"Inter\"`.";
136
+ } @else if string.slice(meta.inspect($font-family), 1, 1) != "\"" and (list.index("serif" "sans-serif" "monospace" "cursive" "fantasy" "system-ui" "math" "inherit" "initial" "unset" "revert" "revert-layer" "default", string.to-lower-case($font-family)) or string.index($font-family, "env(") or string.index($font-family, "attr(")) {
137
+ // Measured in Chrome 152, a @font-face rule dropped an unquoted `serif`,
138
+ // `sans-serif`, `monospace`, `cursive`, `fantasy`, `system-ui`, `math`,
139
+ // `default` or CSS-wide keyword, in any case, and `env()` and `attr()`. The
140
+ // same words quoted are names and were kept, as were `emoji`, `fangsong` and
141
+ // the `ui-` families unquoted.
142
+ @error "`#{$font-family}` is not a valid $font-family for `font-face`. A @font-face rule drops a generic family, a CSS-wide keyword or a function as its family, and without a family the font is never used. Pass the family name as a quoted string, such as `\"Inter\"`.";
143
+ } @else {
144
+
145
+ $list: ();
146
+
147
+ // The same rule dropped `font-style: var(--s)`, `font-weight: var(--w)` and
148
+ // `font-weight: 100 var(--w)`, so var() is refused anywhere in either,
149
+ // before $font-style is reinterpreted below.
150
+ @if string.index(meta.inspect($font-style), "var(") {
151
+ @error "`#{meta.inspect($font-style)}` is not a valid $font-style for `font-face`. A custom property cannot supply it, because a @font-face rule drops var() in a descriptor. Pass the style itself, such as `italic`.";
152
+ }
153
+ @if string.index(meta.inspect($font-weight), "var(") {
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`.";
155
+ }
156
+
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 {
161
+ $font-weight: $font-style;
162
+ $font-style: normal;
163
+ } @else if not
164
+ list.index("normal" "italic" "oblique", $font-style) and
165
+ meta.type-of($font-style) !=
166
+ "number"
167
+ {
168
+ $font-style-list: ();
169
+ @for $i from 1 through list.length($font-style) {
170
+ $font-style-list: list.append($font-style-list, list.nth($font-style, $i), comma);
171
+ }
172
+ @for $i from 1 through list.length($font-style-list) {
173
+ @if list.index("eot" "woff2" "woff" "ttf" "svg", list.nth($font-style-list, $i)) {
174
+ $file-formats: $font-style-list;
175
+ $font-style: normal;
176
+ }
177
+ }
178
+ }
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
+
190
+ // $font-display comes last so the reinterpretation of $font-style above is
191
+ // left alone, and it is written only when given: the browser's default is
192
+ // what a call without it has always had. Measured in Chrome 152, a
193
+ // @font-face rule drops `font-display: "swap"` and `font-display: var(--d)`
194
+ // without a word, so a quoted keyword is unquoted and var() is refused.
195
+ @if $font-display != null {
196
+ @if meta.type-of($font-display) == "string" and string.index($font-display, "var(") {
197
+ @error "`#{meta.inspect($font-display)}` is not a valid $font-display for `font-face`. A custom property cannot supply it, because a @font-face rule drops var() in a descriptor. Pass one of: auto, block, swap, fallback, optional.";
198
+ } @else if not list.index("auto" "block" "swap" "fallback" "optional", $font-display) {
199
+ @error "`#{meta.inspect($font-display)}` is not a valid $font-display for `font-face`. Pass one of: auto, block, swap, fallback, optional.";
200
+ }
201
+ }
202
+
203
+ // fontSource returns nothing for a format it does not know, so a typo
204
+ // dropped that source and a list of nothing but typos dropped `src`.
205
+ @each $format in $file-formats {
206
+ @if not map.has-key($map-for-font-formats, $format) {
207
+ @error "`#{meta.inspect($format)}` is not a valid file format for `font-face`. Pass one or more of: #{map.keys($map-for-font-formats)}.";
208
+ }
209
+ }
210
+
211
+ @font-face {
212
+ font-family: $font-family;
213
+ @if list.index($file-formats, eot) {
214
+ src: url("#{$file-path}.eot");
215
+ }
216
+ @for $i from 1 through list.length($file-formats) {
217
+ $list: list.append($list, fontSource($font-family, $file-path, list.nth($file-formats, $i)), comma);
218
+ }
219
+ src: $list;
220
+ // A quoted keyword is written without its quotes. Measured in Chrome 152,
221
+ // `font-style: "italic"` and `font-weight: "bold"` were dropped, and this
222
+ // is what a quoted argument used to produce. The family keeps its quotes,
223
+ // since there they make it a name.
224
+ @if meta.type-of($font-style) == "string" {
225
+ font-style: string.unquote($font-style);
226
+ } @else {
227
+ font-style: $font-style;
228
+ }
229
+ @if meta.type-of($font-weight) == "string" {
230
+ font-weight: string.unquote($font-weight);
231
+ } @else {
232
+ font-weight: $font-weight;
233
+ }
234
+ @if $font-display {
235
+ font-display: string.unquote($font-display);
236
+ }
237
+ @content;
238
+ }
239
+ }
240
+ }
@@ -0,0 +1,25 @@
1
+ @charset "UTF-8";
2
+
3
+ @mixin hide($toggle: "hide") {
4
+ @if $toggle == "hide" {
5
+ position: absolute;
6
+ width: 1px;
7
+ height: 1px;
8
+ padding: 0;
9
+ border: 0;
10
+ overflow: hidden;
11
+ clip: rect(1px, 1px, 1px, 1px);
12
+ clip-path: inset(100%);
13
+ white-space: nowrap;
14
+ } @else if $toggle == "unhide" {
15
+ position: static;
16
+ width: auto;
17
+ height: auto;
18
+ overflow: visible;
19
+ clip: auto;
20
+ clip-path: none;
21
+ white-space: inherit;
22
+ } @else if not index ("hide" "unhide", $toggle) {
23
+ @error "#{$toggle} is not a valid value for the `$toggle` argument. The value must be either `hide` or `unhide`.";
24
+ }
25
+ }
@@ -0,0 +1,58 @@
1
+ @charset "UTF-8";
2
+
3
+ @forward "adaptive";
4
+ @forward "after";
5
+ @forward "all-buttons";
6
+ @forward "all-text-inputs";
7
+ @forward "antialias";
8
+ @forward "aspect-ratio";
9
+ @forward "background-dots";
10
+ @forward "background-image";
11
+ @forward "background-stripes";
12
+ @forward "before";
13
+ @forward "border-box";
14
+ @forward "border-radius";
15
+ @forward "brand-logo";
16
+ @forward "breakpoint";
17
+ @forward "breakpointer";
18
+ @forward "center";
19
+ @forward "circle";
20
+ @forward "clearfix";
21
+ @forward "columnizer";
22
+ @forward "container";
23
+ @forward "container-query";
24
+ @forward "counter";
25
+ @forward "ellipsis";
26
+ @forward "escape-to-parent";
27
+ @forward "except";
28
+ @forward "focus-ring";
29
+ @forward "font-face";
30
+ @forward "hide";
31
+ @forward "line-clamp";
32
+ @forward "linear-gradient";
33
+ @forward "loadify";
34
+ @forward "motion-safe";
35
+ @forward "only";
36
+ @forward "placeholder";
37
+ @forward "placeholder-shown";
38
+ @forward "position";
39
+ @forward "radial-gradient";
40
+ @forward "remove";
41
+ @forward "reset-css";
42
+ @forward "reset-figure";
43
+ @forward "resizable";
44
+ @forward "responsive-image";
45
+ @forward "scissors";
46
+ @forward "screen-agent";
47
+ @forward "sizer";
48
+ @forward "smartphone";
49
+ @forward "sprite";
50
+ @forward "stretched-link";
51
+ @forward "tablet";
52
+ @forward "text-gradient";
53
+ @forward "text-image";
54
+ @forward "text-selection";
55
+ @forward "text-shadow";
56
+ @forward "text-stroke";
57
+ @forward "tokens";
58
+ @forward "triangle";
@@ -0,0 +1,38 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:math";
4
+ @use "sass:meta";
5
+ @use "../internal/is-css-function" as *;
6
+
7
+ // Truncates text after a number of lines. `ellipsis` does one line; this does
8
+ // several, and needs five declarations rather than one because -webkit-line-clamp
9
+ // only works alongside two other properties.
10
+ //
11
+ // All five were measured in a browser, on a paragraph that runs to five lines
12
+ // with a clamp of three:
13
+ //
14
+ // the three together 3 lines, with an ellipsis
15
+ // without -webkit-box-orient 5 lines, no clamping and no warning
16
+ // without display: -webkit-box 5 lines, likewise
17
+ // the standard line-clamp alone 5 lines; it is not Baseline yet
18
+ // without overflow: hidden the box is 3 lines, but the rest of the text
19
+ // spills out below it
20
+ //
21
+ // So the standard property is emitted for the future and the prefixed trio is
22
+ // what actually does the work today.
23
+ @mixin line-clamp($lines: 3) {
24
+ // var() is resolved by the browser, so only a literal count is checked.
25
+ @if $lines != none and not isCssFunction($lines, "var" "env") {
26
+ @if meta.type-of($lines) != "number" or not math.is-unitless($lines) {
27
+ @error "`#{$lines}` is not a valid $lines for `line-clamp`. Pass a whole number of lines, or `none` to undo a clamp.";
28
+ }
29
+ @if $lines < 1 or $lines != math.round($lines) {
30
+ @error "`#{$lines}` is not a valid $lines for `line-clamp`. Pass a whole number of lines that is at least 1, or `none` to undo a clamp.";
31
+ }
32
+ }
33
+ display: -webkit-box;
34
+ -webkit-box-orient: vertical;
35
+ -webkit-line-clamp: $lines;
36
+ line-clamp: $lines;
37
+ overflow: hidden;
38
+ }
@@ -0,0 +1,33 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:list";
4
+ @use "sass:map";
5
+ @use "sass:math";
6
+ @use "sass:meta";
7
+ @use "../maps/map-for-directions" as *;
8
+ @use "../internal/color-stops-problem" as *;
9
+
10
+ @mixin linear-gradient($direction, $colors) {
11
+ // A stop the browser does not keep drops the whole gradient; see
12
+ // scss/internal/_color-stops-problem.scss for what was measured.
13
+ $problem: colorStopsProblem($colors);
14
+ @if $problem {
15
+ @error "`#{meta.inspect($colors)}` is not a valid $colors for `linear-gradient`: #{$problem}. A browser drops the whole gradient.";
16
+ }
17
+ $list: ();
18
+ @for $i from 1 through list.length($colors) {
19
+ $list: list.append($list, list.nth($colors, $i), comma);
20
+ }
21
+ @if map.has-key($map-for-directions, $direction) {
22
+ background: linear-gradient(
23
+ map.get($map-for-directions, $direction),
24
+ $list
25
+ );
26
+ } @else if not map.has-key($map-for-directions, $direction) {
27
+ @if meta.type-of($direction) != "number" or not list.index("deg", math.unit($direction)) {
28
+ @error "`#{$direction}` is not a valid $direction for `linear-gradient`. Pass an angle such as `45deg`, or one of: #{map.keys($map-for-directions)}.";
29
+ } @else {
30
+ background: linear-gradient($direction, $list);
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,62 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:list";
4
+ @use "sass:meta";
5
+ @use "../utilities/is-time" as *;
6
+
7
+ // `init` defines the %loadify placeholder, and every call extends it. Under the
8
+ // module system a selector can only extend a placeholder from a module it
9
+ // loads, so the file with the call must be the file that calls `init`, or must
10
+ // `@use` it. Anything else fails with "The target selector was not found".
11
+ // An entry file calling `init` does not help a partial it loads, since the
12
+ // partial does not load the entry file. Stylesheets using @import share one
13
+ // scope and are unaffected.
14
+ @mixin loadify($params...) {
15
+ @if not & {
16
+ @if list.length($params) == 0 or (list.length($params) == 1 and list.nth($params, 1) == "init") {
17
+ @keyframes loadify {
18
+ to {
19
+ opacity: 1;
20
+ visibility: visible;
21
+ backface-visibility: visible;
22
+ }
23
+ }
24
+ %loadify {
25
+ opacity: 0;
26
+ visibility: hidden;
27
+ backface-visibility: hidden;
28
+ animation-name: loadify;
29
+ animation-fill-mode: forwards;
30
+
31
+ // The element starts invisible and the animation is what reveals it,
32
+ // so switching the animation off is not enough on its own: it would
33
+ // leave the content hidden for good. Under reduced motion the end
34
+ // state is applied directly instead, and nothing moves.
35
+ @media (prefers-reduced-motion: reduce) {
36
+ opacity: 1;
37
+ visibility: visible;
38
+ backface-visibility: visible;
39
+ animation: none;
40
+ }
41
+ }
42
+ } @else if (list.length($params) == 1 and list.nth($params, 1) != "init") or (list.length($params) == 1 and meta.type-of(list.nth($params, 1)) != "string") {
43
+ @error "#{list.nth($params, 1)} is not a valid argument. Please pass `init` as an argument to initialize the effect or do not pass any argument at all.";
44
+ } @else if list.length($params) > 1 {
45
+ @error "Only one argument is allowed when you call this mixin at the root of your stylesheet! Please pass `init` as an argument to initialize the effect or do not pass any argument at all.";
46
+ }
47
+ } @else if & {
48
+ @extend %loadify;
49
+ @if list.length($params) == 0 {
50
+ animation-delay: 0.2s;
51
+ animation-duration: 0.5s;
52
+ } @else if list.length($params) == 1 {
53
+ animation-delay: #{isTime(list.nth($params, 1))};
54
+ animation-duration: 0.5s;
55
+ } @else if list.length($params) == 2 {
56
+ animation-delay: #{isTime(list.nth($params, 1))};
57
+ animation-duration: #{isTime(list.nth($params, 2))};
58
+ } @else if list.length($params) > 2 {
59
+ @error "You cannot pass more than two arguments.";
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,28 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:meta";
4
+
5
+ // Applies its content only for users who have not asked their system for less
6
+ // motion. Motion is opt-in here rather than switched off afterwards: the usual
7
+ // way round writes the animation and then overrides it under
8
+ // `prefers-reduced-motion: reduce`, and that override has to catch every
9
+ // animation and transition, including the ones added later. Written inside this
10
+ // block, nothing moves for a user who asked for less, without a list to keep.
11
+ //
12
+ // Two agent trials wrote this same wrapper by hand, as `motion-safe` and
13
+ // `motion-ok`. Both media queries were checked to parse in Chrome 152; the
14
+ // reduced-motion setting itself could not be emulated in the browser used.
15
+ //
16
+ // The trap is the resting state. An element hidden in its base rule and
17
+ // revealed by an animation inside the block stays hidden when the block does
18
+ // not apply, which is what `loadify` avoids by applying the end state. Keep the
19
+ // visible state in the base rule and the start of the motion in the keyframes.
20
+ @mixin motion-safe {
21
+ @if not meta.content-exists() {
22
+ @error "`motion-safe` wraps the motion you pass it, so call it with a block, such as `.card { @include motion-safe { transition: transform 0.2s; } }`.";
23
+ }
24
+
25
+ @media (prefers-reduced-motion: no-preference) {
26
+ @content;
27
+ }
28
+ }
@@ -0,0 +1,73 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:list";
4
+ @use "sass:meta";
5
+ @use "sass:string";
6
+ @use "../internal/sibling-index" as *;
7
+
8
+ @mixin only($params...) {
9
+ @if list.length($params) == 0 {
10
+ @error "Please pass an argument. The argument must be either a negative or positive number or list of numbers. Or pass one of the following predefined string values: 'first', 'last', 'odd', 'even'.";
11
+ } @else if list.length($params) == 1 {
12
+ $value: list.nth($params, 1);
13
+ @if meta.type-of($value) == "number" {
14
+ // A unit or a fraction makes a selector the browser drops, and 0 matches
15
+ // nothing; see scss/internal/_sibling-index.scss.
16
+ $problem: siblingIndexProblem($value, "only");
17
+ @if $problem {
18
+ @error "`#{meta.inspect($value)}` is not a valid position for `only`: #{$problem}.";
19
+ }
20
+ @if $value < 0 {
21
+ &:nth-last-of-type(#{$value * -1}) {
22
+ @content;
23
+ }
24
+ } @else {
25
+ &:nth-of-type(#{$value}) {
26
+ @content;
27
+ }
28
+ }
29
+ } @else if meta.type-of($value) == "string" {
30
+ @if $value == "odd" {
31
+ &:nth-of-type(odd) {
32
+ @content;
33
+ }
34
+ } @else if $value == "even" {
35
+ &:nth-of-type(even) {
36
+ @content;
37
+ }
38
+ } @else if $value == "first" {
39
+ &:first-of-type {
40
+ @content;
41
+ }
42
+ } @else if $value == "last" {
43
+ &:last-of-type {
44
+ @content;
45
+ }
46
+ } @else {
47
+ // For class, id or attribute selectors.
48
+ &#{$value} {
49
+ @content;
50
+ }
51
+ }
52
+ } @else {
53
+ @error "`#{$value}` is not a valid argument for `only`. Pass a positive or negative number, one of `first`, `last`, `odd`, `even`, or a selector such as `.foo`.";
54
+ }
55
+ } @else if list.length($params) > 1 {
56
+ // Every item is checked first. A word used to fail with Sass's own
57
+ // `Undefined operation`, and one bad position emptied the whole selector
58
+ // list, taking the good positions with it.
59
+ @each $item in $params {
60
+ $problem: siblingIndexProblem($item, "only", true);
61
+ @if $problem {
62
+ @error "`#{meta.inspect($item)}` is not a valid position for `only`: #{$problem}.";
63
+ }
64
+ }
65
+ $list: ();
66
+ @for $i from 1 through list.length($params) {
67
+ $list: list.append($list, if(list.nth($params, $i) < 0, string.unquote("&:nth-last-of-type(#{list.nth($params, $i) * -1})"), string.unquote("&:nth-of-type(#{list.nth($params, $i)})")), comma);
68
+ }
69
+ #{$list} {
70
+ @content;
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,7 @@
1
+ @charset "UTF-8";
2
+
3
+ @mixin placeholder-shown {
4
+ &:placeholder-shown {
5
+ @content;
6
+ }
7
+ }
@@ -0,0 +1,19 @@
1
+ @charset "UTF-8";
2
+
3
+ @mixin placeholder {
4
+ &::-webkit-input-placeholder {
5
+ @content;
6
+ }
7
+ &::-moz-placeholder {
8
+ @content;
9
+ }
10
+ &:-ms-input-placeholder {
11
+ @content;
12
+ }
13
+ &:-moz-placeholder {
14
+ @content;
15
+ }
16
+ &::placeholder {
17
+ @content;
18
+ }
19
+ }
@@ -0,0 +1,72 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:list";
4
+ @use "sass:meta";
5
+ @use "sass:string";
6
+ @use "../utilities/shorthand-property" as *;
7
+ @use "../internal/keyword-value" as *;
8
+ @use "../internal/length-problem" as *;
9
+
10
+ // Sets position and its four offsets in shorthand order: top, right, bottom,
11
+ // left, as `margin` and `padding` take them.
12
+ //
13
+ // Pass $logical: true for the offsets that follow the writing direction, the
14
+ // same choice `triangle` and `border-radius` offer with their logical names.
15
+ // The shorthand order stays the same and each position maps to its logical
16
+ // twin: top to inset-block-start, right to inset-inline-end, bottom to
17
+ // inset-block-end, left to inset-inline-start. Measured in Chrome 152: under
18
+ // dir="ltr" each logical offset put the box where its physical twin did, and
19
+ // under dir="rtl" where the mirrored twin did, while a physical `left: 16px`
20
+ // stayed 16px from the left in both. For one offset, writing inset-* by hand is
21
+ // as short; the argument is here so the library behaves the same way
22
+ // everywhere.
23
+ @mixin position($position: absolute, $offsets: 0, $logical: false) {
24
+ // null is read as false, as a null argument means "not set" across the
25
+ // library, so a caller can pass a variable that may be unset.
26
+ @if $logical != true and $logical != false and $logical != null {
27
+ @error "`#{meta.inspect($logical)}` is not a valid $logical for `position`. Pass true for offsets that follow the writing direction, or false for top, right, bottom and left.";
28
+ }
29
+ // Measured in Chrome 152, `position` kept the five keywords in any case, the
30
+ // CSS-wide keywords and var(), and dropped anything else, a quoted keyword
31
+ // included. A vendor keyword is let through: Chrome drops `-webkit-sticky`,
32
+ // which Safari uses. null leaves position out, as it always has.
33
+ $problem: keywordProblem($position, "static" "relative" "absolute" "fixed" "sticky", $vendor: true);
34
+ @if $problem {
35
+ @error "`#{meta.inspect($position)}` is not a valid $position for `position`: #{$problem}. A browser drops the declaration.";
36
+ }
37
+
38
+ $offsets: shorthandProperty($offsets);
39
+ // Each offset is a declaration of its own. Measured in Chrome 152, top, left
40
+ // and the inset-* properties kept a length, a negative length, a percentage,
41
+ // 0, auto and a CSS-wide keyword in any case, var(), maths functions, anchor()
42
+ // and anchor-size(), and dropped any other word, a unitless number, a unit
43
+ // that is not a length, a colour, an image and a quoted length. This used to
44
+ // go through validateLength, which only warns, and warned about working
45
+ // values such as AUTO and revert-layer while saying nothing about 10deg or
46
+ // url(); validateLength itself is unchanged, for callers who want a warning.
47
+ @each $value in $offsets {
48
+ @if $value != null {
49
+ $problem: lengthProblem($value, $keywords: ("auto",), $functions: "anchor" "anchor-size", $css-wide: true);
50
+ @if $problem {
51
+ @error "`#{meta.inspect($value)}` is not a valid offset for `position`: #{$problem}. A browser drops the declaration.";
52
+ }
53
+ }
54
+ }
55
+ $edges: top right bottom left;
56
+ @if $logical {
57
+ $edges: inset-block-start inset-inline-end inset-block-end inset-inline-start;
58
+ }
59
+
60
+ // Written without quotes, since `position: "sticky"` was dropped.
61
+ @if meta.type-of($position) == "string" {
62
+ position: string.unquote($position);
63
+ } @else {
64
+ position: $position;
65
+ }
66
+ @for $i from 1 through 4 {
67
+ $value: list.nth($offsets, $i);
68
+ @if $value != null {
69
+ #{list.nth($edges, $i)}: $value;
70
+ }
71
+ }
72
+ }