gerillass 0.0.6 → 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.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.md +13 -0
  3. data/README.md +328 -0
  4. data/SKILL.md +282 -0
  5. data/gerillass.json +2713 -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/_gradient.scss +425 -0
  15. data/scss/internal/_image-value.scss +68 -0
  16. data/scss/internal/_is-condition-value.scss +94 -0
  17. data/scss/internal/_is-css-function.scss +21 -0
  18. data/scss/internal/_is-size.scss +22 -0
  19. data/scss/internal/_keyword-value.scss +76 -0
  20. data/scss/internal/_length-problem.scss +127 -0
  21. data/scss/internal/_sibling-index.scss +51 -0
  22. data/scss/internal/_words.scss +35 -0
  23. data/scss/library/_adaptive.scss +31 -0
  24. data/scss/library/_after.scss +28 -0
  25. data/scss/library/_all-buttons.scss +21 -0
  26. data/scss/library/_all-text-inputs.scss +21 -0
  27. data/{core → scss}/library/_antialias.scss +5 -1
  28. data/scss/library/_aspect-ratio.scss +27 -0
  29. data/scss/library/_background-dots.scss +104 -0
  30. data/scss/library/_background-image.scss +89 -0
  31. data/scss/library/_background-stripes.scss +88 -0
  32. data/scss/library/_before.scss +28 -0
  33. data/scss/library/_border-box.scss +30 -0
  34. data/scss/library/_border-radius.scss +164 -0
  35. data/scss/library/_brand-logo.scss +33 -0
  36. data/scss/library/_breakpoint.scss +96 -0
  37. data/scss/library/_breakpointer.scss +40 -0
  38. data/scss/library/_center.scss +19 -0
  39. data/scss/library/_circle.scss +15 -0
  40. data/{core → scss}/library/_clearfix.scss +1 -1
  41. data/scss/library/_columnizer.scss +125 -0
  42. data/scss/library/_container-query.scss +119 -0
  43. data/scss/library/_container.scss +72 -0
  44. data/scss/library/_counter.scss +59 -0
  45. data/scss/library/_ellipsis.scss +87 -0
  46. data/scss/library/_escape-to-parent.scss +12 -0
  47. data/scss/library/_except.scss +71 -0
  48. data/scss/library/_focus-ring.scss +63 -0
  49. data/scss/library/_font-face.scss +240 -0
  50. data/scss/library/_gradient.scss +31 -0
  51. data/scss/library/_hide.scss +25 -0
  52. data/scss/library/_index.scss +57 -0
  53. data/scss/library/_line-clamp.scss +38 -0
  54. data/scss/library/_loadify.scss +62 -0
  55. data/scss/library/_motion-safe.scss +28 -0
  56. data/scss/library/_only.scss +73 -0
  57. data/scss/library/_placeholder-shown.scss +7 -0
  58. data/scss/library/_placeholder.scss +19 -0
  59. data/scss/library/_position.scss +72 -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 +48 -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/_gradient-value.scss +24 -0
  102. data/scss/utilities/_index.scss +26 -0
  103. data/scss/utilities/_is-color.scss +16 -0
  104. data/scss/utilities/_is-gutter.scss +24 -0
  105. data/scss/utilities/_is-number.scss +11 -0
  106. data/scss/utilities/_is-time.scss +14 -0
  107. data/scss/utilities/_map-deep-get.scss +10 -0
  108. data/scss/utilities/_pixelify.scss +20 -0
  109. data/scss/utilities/_pseudo-selector.scss +12 -0
  110. data/scss/utilities/_remify.scss +16 -0
  111. data/scss/utilities/_shade.scss +10 -0
  112. data/scss/utilities/_shorthand-property.scss +17 -0
  113. data/scss/utilities/_tint.scss +10 -0
  114. data/scss/utilities/_validate-breakpoint.scss +41 -0
  115. data/scss/utilities/_validate-length.scss +37 -0
  116. data/scss/utilities/_validate-ratio.scss +77 -0
  117. data/scss/utilities/_validate-scissors.scss +34 -0
  118. metadata +131 -46
  119. data/core/_gerillass.scss +0 -4
  120. data/core/library/_before.scss +0 -18
  121. data/core/library/_border-box.scss +0 -26
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gerillass
4
+ # Tells Rails' Sass compiler where the library is. Each Sass setup reads its
5
+ # load paths from a different place, so each gets the folder where it looks.
6
+ #
7
+ # dartsass-rails, the Sass setup for Propshaft, passes its build options to
8
+ # Sass, so the folder goes in as --load-path. It would also accept the folder
9
+ # on config.assets.paths (lib/dartsass/runner.rb passes those as load paths
10
+ # too), but Propshaft copies everything on its asset paths into public/assets
11
+ # when precompiling, which published all 109 of the library's .scss sources,
12
+ # and Propshaft's excluded_paths cannot help: it removes the folder from
13
+ # config.assets.paths as well. dartsass-rails splits build options on
14
+ # whitespace, so a path containing a space falls back to the asset paths.
15
+ #
16
+ # dartsass-sprockets reads config.sass.load_paths on every compile
17
+ # (lib/sassc/rails/template.rb). Appending to config.assets.paths after
18
+ # initialization did not work there: sprockets-rails had already built its
19
+ # environment from that list in its own after_initialize.
20
+ #
21
+ # Both of those are appended after initialization, so an app that assigns
22
+ # config.dartsass.build_options or config.sass.load_paths in its own
23
+ # initializers does not overwrite them. Anything else gets the folder on
24
+ # config.assets.paths during initialization, before an asset environment is
25
+ # built from it.
26
+ class Engine < ::Rails::Engine
27
+ initializer "gerillass.assets" do |app|
28
+ next unless app.config.respond_to?(:assets)
29
+ next if Gerillass::Engine.dartsass_rails?(app) || Gerillass::Engine.sass_load_paths?(app)
30
+
31
+ app.config.assets.paths << Gerillass.load_path
32
+ end
33
+
34
+ config.after_initialize do |app|
35
+ path = Gerillass.load_path
36
+
37
+ if Gerillass::Engine.dartsass_rails?(app)
38
+ option = "--load-path=#{path}"
39
+ options = app.config.dartsass.build_options
40
+ options << option unless options.include?(option)
41
+ elsif Gerillass::Engine.sass_load_paths?(app)
42
+ paths = app.config.sass.load_paths
43
+ paths << path unless paths.map(&:to_s).include?(path)
44
+ end
45
+ end
46
+
47
+ def self.dartsass_rails?(app)
48
+ app.config.respond_to?(:dartsass) && !Gerillass.load_path.match?(/\s/)
49
+ end
50
+
51
+ def self.sass_load_paths?(app)
52
+ app.config.respond_to?(:sass) && app.config.sass.respond_to?(:load_paths) && app.config.sass.load_paths.is_a?(Array)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Adds the library's scss/ folder to Jekyll's Sass load paths.
4
+ #
5
+ # jekyll-sass-converter reads sass.load_paths from the site configuration when
6
+ # it first converts a stylesheet, and expands each entry with File.expand_path,
7
+ # so an absolute path outside the site works. In safe mode it would confine
8
+ # every path to the site source, but plugins do not run in safe mode anyway.
9
+ Jekyll::Hooks.register :site, :after_init do |site|
10
+ sass = (site.config["sass"] ||= {})
11
+ paths = Array(sass["load_paths"])
12
+ sass["load_paths"] = paths + [Gerillass.load_path] unless paths.include?(Gerillass.load_path)
13
+ end
data/lib/gerillass.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Gerillass is a Sass library. The Ruby in this gem only tells a project where
4
+ # its stylesheets are, so that `@use "gerillass" as *;` resolves:
5
+ #
6
+ # Rails add the gem to the Gemfile; lib/gerillass/engine.rb puts the folder
7
+ # on the asset paths, which dartsass-rails and dartsass-sprockets
8
+ # pass to Sass as load paths.
9
+ # Jekyll add the gem to the :jekyll_plugins group or to `plugins:` in
10
+ # _config.yml; lib/gerillass/jekyll.rb adds the folder to
11
+ # sass.load_paths.
12
+ # Ruby pass Gerillass.load_path yourself, for example
13
+ # Sass.compile("app.scss", load_paths: [Gerillass.load_path]).
14
+ module Gerillass
15
+ # The folder that holds _gerillass.scss.
16
+ def self.load_path
17
+ File.expand_path("../scss", __dir__)
18
+ end
19
+ end
20
+
21
+ # Each integration is loaded only when its framework is already loaded, so the
22
+ # gem adds nothing to a project that uses neither. Rails is loaded before
23
+ # Bundler.require in config/application.rb, and Jekyll requires its plugins after
24
+ # itself, so both are defined by the time this file is required.
25
+ require "gerillass/engine" if defined?(::Rails::Engine)
26
+ require "gerillass/jekyll" if defined?(::Jekyll::Hooks)
@@ -0,0 +1,15 @@
1
+ @charset "UTF-8";
2
+
3
+ // https://www.gerillass.com/
4
+ // Copyright 2020 by Halil İbrahim Çakıroğlu
5
+ // Apache License 2.0
6
+
7
+ @forward "lists";
8
+ @forward "maps";
9
+ @forward "utilities";
10
+ @forward "library";
11
+
12
+ // The gls- prefixed half of the API. Until 2.0.0 this was a generated file:
13
+ // gulpfile.js concatenated scss/library and rewrote "@mixin " to "@mixin gls-".
14
+ // The module system does the same thing in one line, so the generator is gone.
15
+ @forward "library" as gls-*;
@@ -0,0 +1,99 @@
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
+ // What a browser keeps as a colour, measured in Chrome 152 in `color`,
10
+ // `-webkit-text-stroke-color`, `outline: 2px solid ...`, `background` and a
11
+ // gradient's colour stop:
12
+ //
13
+ // - kept: a colour Sass knows (red, #333, rgba(), hsl(), oklch(), color()),
14
+ // currentColor in any case, every system colour, deprecated ones included
15
+ // (Canvas, AccentColor, ActiveBorder), a vendor colour such as -webkit-link,
16
+ // var() and env(), and the colour functions Sass leaves as text: rgb() with
17
+ // var() in it, rgb(from ...), color-mix(), light-dark() and contrast-color();
18
+ // - dropped: a word that is none of those (huge, auto, none), a quoted colour,
19
+ // a length, a number, calc(), and two colours side by side;
20
+ // - CSS-wide keywords were kept in a declaration of their own and dropped inside
21
+ // `outline` and inside a gradient, so $css-wide says which this is.
22
+ //
23
+ // device-cmyk() is in the specification and Chrome drops it; it is let through,
24
+ // as `run-in` is for display, because refusing it would refuse valid CSS once a
25
+ // browser ships it.
26
+ //
27
+ // Deliberately looser than isColor, which stays strict because tint and shade
28
+ // pass its result to color.mix, and that needs a real Sass colour.
29
+ $-system-colors: "canvas" "canvastext" "linktext" "visitedtext" "activetext" "buttonface" "buttontext" "buttonborder" "field" "fieldtext" "highlight" "highlighttext" "selecteditem" "selecteditemtext" "mark" "marktext" "graytext" "accentcolor" "accentcolortext" "activeborder" "activecaption" "appworkspace" "background" "buttonhighlight" "buttonshadow" "captiontext" "inactiveborder" "inactivecaption" "inactivecaptiontext" "infobackground" "infotext" "menu" "menutext" "scrollbar" "threeddarkshadow" "threedface" "threedhighlight" "threedlightshadow" "threedshadow" "window" "windowframe" "windowtext";
30
+ $-functions: "var" "env" "attr" "rgb" "rgba" "hsl" "hsla" "hwb" "lab" "lch" "oklab" "oklch" "color" "color-mix" "light-dark" "contrast-color" "device-cmyk";
31
+ $-css-wide: "inherit" "initial" "unset" "revert" "revert-layer";
32
+
33
+ // The CSS named colours and transparent, for a colour that reaches the check as
34
+ // an unquoted string rather than as a Sass colour.
35
+ $-named-colors: "transparent" "aliceblue" "antiquewhite" "aqua" "aquamarine" "azure" "beige" "bisque" "black" "blanchedalmond" "blue" "blueviolet" "brown" "burlywood" "cadetblue" "chartreuse" "chocolate" "coral" "cornflowerblue" "cornsilk" "crimson" "cyan" "darkblue" "darkcyan" "darkgoldenrod" "darkgray" "darkgreen" "darkgrey" "darkkhaki" "darkmagenta" "darkolivegreen" "darkorange" "darkorchid" "darkred" "darksalmon" "darkseagreen" "darkslateblue" "darkslategray" "darkslategrey" "darkturquoise" "darkviolet" "deeppink" "deepskyblue" "dimgray" "dimgrey" "dodgerblue" "firebrick" "floralwhite" "forestgreen" "fuchsia" "gainsboro" "ghostwhite" "gold" "goldenrod" "gray" "green" "greenyellow" "grey" "honeydew" "hotpink" "indianred" "indigo" "ivory" "khaki" "lavender" "lavenderblush" "lawngreen" "lemonchiffon" "lightblue" "lightcoral" "lightcyan" "lightgoldenrodyellow" "lightgray" "lightgreen" "lightgrey" "lightpink" "lightsalmon" "lightseagreen" "lightskyblue" "lightslategray" "lightslategrey" "lightsteelblue" "lightyellow" "lime" "limegreen" "linen" "magenta" "maroon" "mediumaquamarine" "mediumblue" "mediumorchid" "mediumpurple" "mediumseagreen" "mediumslateblue" "mediumspringgreen" "mediumturquoise" "mediumvioletred" "midnightblue" "mintcream" "mistyrose" "moccasin" "navajowhite" "navy" "oldlace" "olive" "olivedrab" "orange" "orangered" "orchid" "palegoldenrod" "palegreen" "paleturquoise" "palevioletred" "papayawhip" "peachpuff" "peru" "pink" "plum" "powderblue" "purple" "rebeccapurple" "red" "rosybrown" "royalblue" "saddlebrown" "salmon" "sandybrown" "seagreen" "seashell" "sienna" "silver" "skyblue" "slateblue" "slategray" "slategrey" "snow" "springgreen" "steelblue" "tan" "teal" "thistle" "tomato" "turquoise" "violet" "wheat" "white" "whitesmoke" "yellow" "yellowgreen";
36
+
37
+ // A hex colour written as text: # and then 3, 4, 6 or 8 hex digits.
38
+ @function -is-hex($text) {
39
+ @if string.index($text, "#") != 1 or not list.index(4 5 7 9, string.length($text)) {
40
+ @return false;
41
+ }
42
+ @for $i from 2 through string.length($text) {
43
+ @if not string.index("0123456789abcdef", string.slice($text, $i, $i)) {
44
+ @return false;
45
+ }
46
+ }
47
+ @return true;
48
+ }
49
+
50
+ // Returns what is wrong with $value as one colour, or null when a browser keeps
51
+ // it. null itself is the caller's to decide, since it means a default in some
52
+ // mixins and leaving a declaration out in others.
53
+ @function colorProblem($value, $css-wide: false) {
54
+ @if meta.type-of($value) == "color" {
55
+ @return null;
56
+ }
57
+ @if meta.type-of($value) == "list" and list.length($value) > 1 {
58
+ @return "it is several values where one colour is meant";
59
+ }
60
+ @if meta.type-of($value) != "string" {
61
+ @return "it is not a colour";
62
+ }
63
+ @if string.slice(meta.inspect($value), 1, 1) == "\"" {
64
+ @return "a colour in quotes is text, not a colour";
65
+ }
66
+ $lower: string.to-lower-case($value);
67
+ $open: string.index($lower, "(");
68
+ @if $open {
69
+ @if list.index($-functions, string.slice($lower, 1, $open - 1)) {
70
+ @return null;
71
+ }
72
+ @return "`#{string.slice($value, 1, $open - 1)}()` is not a colour function";
73
+ }
74
+ @if $lower == "currentcolor" or list.index($-system-colors, $lower) {
75
+ @return null;
76
+ }
77
+ // Interpolation, such as `#{$name}` or `#{$hex}`, gives an unquoted string
78
+ // rather than a colour, and it is written into the CSS as it reads, so a
79
+ // named or hex colour in one works exactly as the colour itself does.
80
+ @if list.index($-named-colors, $lower) or -is-hex($lower) {
81
+ @return null;
82
+ }
83
+ // Vendor colours are named rather than matched by prefix. Measured in Chrome
84
+ // 152, `-webkit-link` and `-webkit-activelink` were kept as colours while
85
+ // `-webkit-fill-available`, `-webkit-box` and `-webkit-text` were dropped, and
86
+ // the prefix rule this replaced had let those through. `-webkit-focus-ring-color`
87
+ // is Safari's, and `-moz-` colours are Firefox's; neither could be measured
88
+ // here, so they are let through rather than refused unseen.
89
+ @if list.index("-webkit-link" "-webkit-activelink" "-webkit-focus-ring-color", $lower) or string.index($lower, "-moz-") == 1 {
90
+ @return null;
91
+ }
92
+ @if list.index($-css-wide, $lower) {
93
+ @if $css-wide {
94
+ @return null;
95
+ }
96
+ @return "a CSS-wide keyword only works as a whole declaration, not inside this value";
97
+ }
98
+ @return "it is not a colour";
99
+ }
@@ -0,0 +1,94 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:list";
4
+ @use "sass:meta";
5
+ @use "sass:string";
6
+ @use "color-problem" as *;
7
+ @use "is-condition-value" as *;
8
+
9
+ // Shared by the mixins and not public API; see _is-css-function.scss.
10
+
11
+ // Returns what is wrong with a list of gradient colour stops, or null. The items
12
+ // are read the way the mixins write them, one per comma in the gradient.
13
+ // Measured in Chrome 152 in linear-gradient():
14
+ //
15
+ // - kept: a colour on its own, even a single one (`linear-gradient(to top,
16
+ // red)`), a colour with one or two positions (`red 0 10%`), a position between
17
+ // two colours as a hint (`red, 30%, blue`), and var() as a whole stop;
18
+ // - dropped: a position first or last, two positions in a row, a colour with
19
+ // three positions, a position that is not a length or a percentage
20
+ // (`red 10deg`), a colour and another colour in one stop (`red 10% blue`), and
21
+ // anything colorProblem refuses, CSS-wide keywords included.
22
+
23
+ // True for a value a stop takes as a position: a length, a percentage, 0 or a
24
+ // calculation.
25
+ @function -is-position($value) {
26
+ @return isConditionValue($value, "length-percentage");
27
+ }
28
+
29
+ // True for var(), env() or attr(), which may stand for a whole stop or a list of
30
+ // them, so nothing around it can be judged.
31
+ @function -is-substitution($value) {
32
+ @if meta.type-of($value) != "string" or string.slice(meta.inspect($value), 1, 1) == "\"" {
33
+ @return false;
34
+ }
35
+ $lower: string.to-lower-case($value);
36
+ @return string.index($lower, "var(") == 1 or string.index($lower, "env(") == 1 or string.index($lower, "attr(") == 1;
37
+ }
38
+
39
+ @function colorStopsProblem($colors) {
40
+ @if $colors == null or list.length($colors) == 0 {
41
+ @return "a gradient needs at least one colour";
42
+ }
43
+ $count: list.length($colors);
44
+ $previous: null;
45
+ $colors-seen: 0;
46
+ @for $i from 1 through $count {
47
+ $item: list.nth($colors, $i);
48
+ $kind: null;
49
+ @if -is-substitution($item) {
50
+ $kind: "substitution";
51
+ } @else if meta.type-of($item) != "list" and -is-position($item) {
52
+ $kind: "hint";
53
+ } @else if meta.type-of($item) == "list" and list.length($item) > 1 {
54
+ $problem: colorProblem(list.nth($item, 1));
55
+ @if $problem {
56
+ @return "`#{meta.inspect($item)}` does not start with a colour: #{$problem}";
57
+ }
58
+ @if list.length($item) > 3 {
59
+ @return "`#{meta.inspect($item)}` has more than two positions, and a colour stop takes at most two";
60
+ }
61
+ @for $j from 2 through list.length($item) {
62
+ @if not -is-position(list.nth($item, $j)) and not -is-substitution(list.nth($item, $j)) {
63
+ @return "in `#{meta.inspect($item)}`, `#{meta.inspect(list.nth($item, $j))}` is not a position; a stop is a colour followed by up to two lengths or percentages";
64
+ }
65
+ }
66
+ $kind: "stop";
67
+ } @else {
68
+ $problem: colorProblem($item);
69
+ @if $problem {
70
+ @return "`#{meta.inspect($item)}` is not a colour stop: #{$problem}";
71
+ }
72
+ $kind: "stop";
73
+ }
74
+
75
+ @if $kind == "hint" {
76
+ @if $i == 1 {
77
+ @return "it starts with the position `#{meta.inspect($item)}`; a position on its own goes between two colours";
78
+ }
79
+ @if $i == $count {
80
+ @return "it ends with the position `#{meta.inspect($item)}`; a position on its own goes between two colours";
81
+ }
82
+ @if $previous == "hint" {
83
+ @return "it has two positions in a row; a position on its own goes between two colours";
84
+ }
85
+ } @else {
86
+ $colors-seen: $colors-seen + 1;
87
+ }
88
+ $previous: $kind;
89
+ }
90
+ @if $colors-seen == 0 {
91
+ @return "a gradient needs at least one colour";
92
+ }
93
+ @return null;
94
+ }
@@ -0,0 +1,22 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:meta";
4
+ @use "../utilities/validate-breakpoint" as *;
5
+ @use "is-condition-value" as *;
6
+
7
+ // Shared by the mixins and not public API; see _is-css-function.scss.
8
+
9
+ // Resolves a size for a width condition and refuses one no condition can match.
10
+ // validateBreakpoint turns a key into its width and refuses a word that is not a
11
+ // key; it passes a percentage or a bare number through, because a declaration
12
+ // takes them. A width condition does not: `(min-width: 50%)` and
13
+ // `(min-width: 768)` never matched in Chrome 152, so they are refused here.
14
+ // Returns the same value validateBreakpoint does, so a call that worked writes
15
+ // the same query.
16
+ @function conditionWidth($value, $mixin, $at-rule: "@media") {
17
+ $width: validateBreakpoint($value);
18
+ @if not isConditionValue($width, "length") {
19
+ @error "`#{meta.inspect($value)}` cannot be used as a size in `#{$mixin}`: a width condition takes a length, and one written with `#{meta.inspect($width)}` would never match in #{$at-rule}. Pass a length such as `600px`, `40em` or `calc(30em + 1px)`, or a key from $map-for-breakpoints.";
20
+ }
21
+ @return $width;
22
+ }
@@ -0,0 +1,25 @@
1
+ @charset "UTF-8";
2
+
3
+ @use "sass:meta";
4
+ @use "sass:string";
5
+
6
+ // Shared by the mixins and not public API; see _is-css-function.scss.
7
+
8
+ // Returns the first value in $value that holds var(), looking inside lists and
9
+ // calculations, or null. Custom properties are not evaluated in a @media or
10
+ // @container condition, so a rule built from one never applies, and nothing
11
+ // warns. Measured in Chrome 152: `(min-width: var(--wide))` did not match with
12
+ // `--wide: 200px`, while `(min-width: 200px)` did.
13
+ @function customPropertyIn($value) {
14
+ @each $item in $value {
15
+ @if meta.type-of($item) == "list" or meta.type-of($item) == "arglist" {
16
+ $found: customPropertyIn($item);
17
+ @if $found {
18
+ @return $found;
19
+ }
20
+ } @else if string.index(meta.inspect($item), "var(") {
21
+ @return $item;
22
+ }
23
+ }
24
+ @return null;
25
+ }