diff --git a/Rakefile b/Rakefile
index 6f82747e1..d4c8917f2 100644
--- a/Rakefile
+++ b/Rakefile
@@ -67,6 +67,28 @@ namespace :sass do
end
end
+ namespace :migrator do
+ # Check out the latest commit of the Sass migrator into the .sass-migrator directory.
+ task :checkout do
+ unless Dir.exists?(".sass-migrator")
+ sh %{git clone git://github.com/sass/migrator .sass-migrator}
+ end
+
+ Dir.chdir(".sass-migrator") do
+ sh %{git fetch}
+ if ENV["SASS_MIGRATOR_REVISION"]
+ sh %{git checkout #{ENV["SASS_MIGRATOR_REVISION"]}}
+ else
+ sh %{git checkout origin/master}
+ end
+ end
+ end
+
+ task :version => :checkout do
+ add_version 'migrator', Dir.chdir(".sass-migrator") {latest_stable_tag}
+ end
+ end
+
namespace :libsass do
# Check out the latest commit of Dart Sass into the .libsass directory.
task :checkout do
diff --git a/config.ru b/config.ru
index 282665958..7221bdae5 100644
--- a/config.ru
+++ b/config.ru
@@ -22,9 +22,11 @@ use Rack::Rewrite do
r301 '/documentation/file.SASS_CHANGELOG.html', 'https://github.com/sass/dart-sass/blob/master/CHANGELOG.md'
r301 '/documentation/file.INDENTED_SYNTAX.html', '/documentation/syntax'
r301 '/documentation/file.SCSS_FOR_SASS_USERS.html', '/documentation/syntax'
- r301 '/documentation/Sass/Script/Functions.html', '/documentation/functions'
- r301 '/documentation/Sass/Script/Functions', '/documentation/functions'
+ r301 '/documentation/Sass/Script/Functions.html', '/documentation/modules'
+ r301 '/documentation/Sass/Script/Functions', '/documentation/modules'
r301 %r{/documentation/(Sass.*)}, 'http://www.rubydoc.info/gems/sass/$1'
+ r301 '/documentation/functions/css', '/documentation/at-rules/function#plain-css-functions'
+ r301 %r{/documentation/functions(.*)}, '/documentation/modules$1'
r301 %r{/(.+)/$}, '/$1'
r301 %r{/(.+)/index\.html$}, '/$1'
diff --git a/data/documentation.yml b/data/documentation.yml
index 67013fbd2..c786ab38c 100644
--- a/data/documentation.yml
+++ b/data/documentation.yml
@@ -14,6 +14,8 @@ toc:
- Interpolation: /documentation/interpolation
- At-Rules: /documentation/at-rules
:children:
+ - @use
: /documentation/at-rules/use
+ - @forward
: /documentation/at-rules/forward
- @import
: /documentation/at-rules/import
- @mixin
and @include
: /documentation/at-rules/mixin
- @function
: /documentation/at-rules/function
@@ -46,16 +48,15 @@ toc:
- Numeric: /documentation/operators/numeric
- String: /documentation/operators/string
- Boolean: /documentation/operators/boolean
-- Built-In Functions: /documentation/functions
+- Built-In Modules: /documentation/modules
:children:
- - Plain CSS: /documentation/functions/css
- - Numbers: /documentation/functions/math
- - Strings: /documentation/functions/string
- - Colors: /documentation/functions/color
- - Lists: /documentation/functions/list
- - Maps: /documentation/functions/map
- - Selectors: /documentation/functions/selector
- - Introspection: /documentation/functions/meta
+ - sass:color
: /documentation/modules/color
+ - sass:list
: /documentation/modules/list
+ - sass:map
: /documentation/modules/map
+ - sass:math
: /documentation/modules/math
+ - sass:meta
: /documentation/modules/meta
+ - sass:selector
: /documentation/modules/selector
+ - sass:string
: /documentation/modules/string
- Breaking Changes: /documentation/breaking-changes
:children:
- Extending Compound Selectors: /documentation/breaking-changes/extend-compound
@@ -64,4 +65,5 @@ toc:
:children:
- Dart Sass: /documentation/cli/dart-sass
- Ruby Sass: /documentation/cli/ruby-sass
+ - Migrator: /documentation/cli/migrator
- JavaScript API: /documentation/js-api
diff --git a/helpers/sass_helpers.rb b/helpers/sass_helpers.rb
index 4317ea6b7..66ed06f99 100644
--- a/helpers/sass_helpers.rb
+++ b/helpers/sass_helpers.rb
@@ -322,6 +322,7 @@ def release_url(impl)
repo =
case impl
when :dart; "dart-sass"
+ when :migrator; "migrator"
when :libsass; "libsass"
end
@@ -423,7 +424,7 @@ def _impl_status_row(name, status)
]
end
- # Renders API docs for a Sass function.
+ # Renders API docs for a Sass function (or mixin).
#
# The function's name is parsed from the signature. The API description is
# passed as a Markdown block. If `returns` is passed, it's included as the
@@ -434,7 +435,8 @@ def _impl_status_row(name, status)
def function(*signatures, returns: nil)
names = Set.new
highlighted_signatures = signatures.map do |signature|
- name = signature.split("(").first
+ name, rest = signature.split("(", 2)
+ name_without_namespace = name.split(".").last
html = Nokogiri::HTML(_render_markdown(<null', '/documentation/values/null'
when 'function'; link_to type, '/documentation/values/functions'
- when 'selector'; link_to type, '/documentation/functions/selector#selector-values'
+ when 'selector'; link_to type, '/documentation/modules/selector#selector-values'
else raise "Unknown type #{type}"
end
end.join(" | ")
diff --git a/source/assets/js/components/redirect.js b/source/assets/js/components/redirect.js
index d6d91fb9f..994f359a5 100644
--- a/source/assets/js/components/redirect.js
+++ b/source/assets/js/components/redirect.js
@@ -34,9 +34,9 @@ if (window.location.hash) {
"#color_operations": "/documentation/operators/color",
"#string_operations": "/documentation/operators/string",
"#boolean_operations": "/documentation/operators/boolean",
- "#list_operations": "/documentation/functions/list",
+ "#list_operations": "/documentation/modules/list",
"#parentheses": "/documentation/operators#parentheses",
- "#functions": "/documentation/functions",
+ "#functions": "/documentation/modules",
"#keyword_arguments": "/documentation/at-rules/function#keyword-arguments",
"#interpolation_": "/documentation/interpolation",
"#parent-script": "/documentation/style-rules/parent-selector#in-sassscript",
@@ -97,93 +97,110 @@ if (window.location.hash) {
}
if (redirect) window.location.href = redirect;
- } else if (window.location.pathname == "/documentation/functions") {
+ } else if (window.location.pathname == "/documentation/modules") {
var redirects = {
"#declare-class_method": "/ruby-sass",
"#random_number_generator-class_method": "/ruby-sass",
"#random_seed=-class_method": "/ruby-sass",
"#signature-class_method": "/ruby-sass",
- "#abs-instance_method": "/documentation/functions/math#abs",
- "#adjust_color-instance_method": "/documentation/functions/color#adjust-color",
- "#adjust_hue-instance_method": "/documentation/functions/color#adjust-hue",
- "#alpha-instance_method": "/documentation/functions/color#alpha",
- "#append-instance_method": "/documentation/functions/list#append",
- "#blue-instance_method": "/documentation/functions/color#blue",
- "#call-instance_method": "/documentation/functions/meta#call",
- "#ceil-instance_method": "/documentation/functions/math#ceil",
- "#change_color-instance_method": "/documentation/functions/color#change-color",
- "#comparable-instance_method": "/documentation/functions/math#comparable",
- "#complement-instance_method": "/documentation/functions/color#complement",
- "#content_exists-instance_method": "/documentation/functions/meta#content-exists",
- "#darken-instance_method": "/documentation/functions/color#darken",
- "#desaturate-instance_method": "/documentation/functions/color#desaturate",
- "#feature_exists-instance_method": "/documentation/functions/meta#feature-exists",
- "#floor-instance_method": "/documentation/functions/math#floor",
- "#get_function-instance_method": "/documentation/functions/meta#get-function",
- "#global_variable_exists-instance_method": "/documentation/functions/meta#global-variable-exists",
- "#grayscale-instance_method": "/documentation/functions/color#grayscale",
- "#green-instance_method": "/documentation/functions/color#green",
- "#hsl-instance_method": "/documentation/functions/color#hsl",
- "#hsla-instance_method": "/documentation/functions/color#hsla",
- "#hue-instance_method": "/documentation/functions/color#hue",
- "#ie_hex_str-instance_method": "/documentation/functions/color#ie-hex-str",
+ "#abs-instance_method": "/documentation/modules/math#abs",
+ "#adjust_color-instance_method": "/documentation/modules/color#adjust",
+ "#adjust_hue-instance_method": "/documentation/modules/color#adjust-hue",
+ "#alpha-instance_method": "/documentation/modules/color#alpha",
+ "#append-instance_method": "/documentation/modules/list#append",
+ "#blue-instance_method": "/documentation/modules/color#blue",
+ "#call-instance_method": "/documentation/modules/meta#call",
+ "#ceil-instance_method": "/documentation/modules/math#ceil",
+ "#change_color-instance_method": "/documentation/modules/color#change",
+ "#comparable-instance_method": "/documentation/modules/math#compatible",
+ "#complement-instance_method": "/documentation/modules/color#complement",
+ "#content_exists-instance_method": "/documentation/modules/meta#content-exists",
+ "#darken-instance_method": "/documentation/modules/color#darken",
+ "#desaturate-instance_method": "/documentation/modules/color#desaturate",
+ "#feature_exists-instance_method": "/documentation/modules/meta#feature-exists",
+ "#floor-instance_method": "/documentation/modules/math#floor",
+ "#get_function-instance_method": "/documentation/modules/meta#get-function",
+ "#global_variable_exists-instance_method": "/documentation/modules/meta#global-variable-exists",
+ "#grayscale-instance_method": "/documentation/modules/color#grayscale",
+ "#green-instance_method": "/documentation/modules/color#green",
+ "#hsl-instance_method": "/documentation/modules/color#hsl",
+ "#hsla-instance_method": "/documentation/modules/color#hsla",
+ "#hue-instance_method": "/documentation/modules/color#hue",
+ "#ie_hex_str-instance_method": "/documentation/modules/color#ie-hex-str",
"#if-instance_method": "/documentation/#if",
- "#index-instance_method": "/documentation/functions/list#index",
- "#inspect-instance_method": "/documentation/functions/meta#inspect",
- "#invert-instance_method": "/documentation/functions/color#invert",
- "#is_bracketed-instance_method": "/documentation/functions/list#is-bracketed",
- "#is_superselector-instance_method": "/documentation/functions/selector#is-superselector",
- "#join-instance_method": "/documentation/functions/list#join",
- "#keywords-instance_method": "/documentation/functions/meta#keywords",
- "#length-instance_method": "/documentation/functions/list#length",
- "#lighten-instance_method": "/documentation/functions/color#lighten",
- "#lightness-instance_method": "/documentation/functions/color#lightness",
- "#list_separator-instance_method": "/documentation/functions/list#list-separator",
- "#map_get-instance_method": "/documentation/functions/map#map-get",
- "#map_has_key-instance_method": "/documentation/functions/map#map-has-key",
- "#map_keys-instance_method": "/documentation/functions/map#map-keys",
- "#map_merge-instance_method": "/documentation/functions/map#map-merge",
- "#map_remove-instance_method": "/documentation/functions/map#map-remove",
- "#map_values-instance_method": "/documentation/functions/map#map-values",
- "#max-instance_method": "/documentation/functions/math#max",
- "#min-instance_method": "/documentation/functions/math#min",
- "#mix-instance_method": "/documentation/functions/color#mix",
- "#mixin_exists-instance_method": "/documentation/functions/meta#mixin-exists",
- "#nth-instance_method": "/documentation/functions/list#nth",
- "#opacify-instance_method": "/documentation/functions/color#opacify",
- "#opacity-instance_method": "/documentation/functions/color#opacity",
- "#percentage-instance_method": "/documentation/functions/math#percentage",
- "#quote-instance_method": "/documentation/functions/string#quote",
- "#random-instance_method": "/documentation/functions/math#random",
- "#red-instance_method": "/documentation/functions/color#red",
- "#rgb-instance_method": "/documentation/functions/color#rgb",
- "#rgba-instance_method": "/documentation/functions/color#rgba",
- "#round-instance_method": "/documentation/functions/math#round",
- "#saturate-instance_method": "/documentation/functions/color#saturate",
- "#saturation-instance_method": "/documentation/functions/color#saturation",
- "#scale_color-instance_method": "/documentation/functions/color#scale-color",
- "#selector_append-instance_method": "/documentation/functions/selector#selector-append",
- "#selector_extend-instance_method": "/documentation/functions/selector#selector-extend",
- "#selector_nest-instance_method": "/documentation/functions/selector#selector-nest",
- "#selector_parse-instance_method": "/documentation/functions/selector#selector-parse",
- "#selector_replace-instance_method": "/documentation/functions/selector#selector-replace",
- "#selector_unify-instance_method": "/documentation/functions/selector#selector-unify",
- "#set-instance_method": "/documentation/functions/list#set",
- "#simple_selectors-instance_method": "/documentation/functions/selector#simple-selectors",
- "#str_index-instance_method": "/documentation/functions/string#str-index",
- "#str_insert-instance_method": "/documentation/functions/string#str-insert",
- "#str_length-instance_method": "/documentation/functions/string#str-length",
- "#str_slice-instance_method": "/documentation/functions/string#str-slice",
- "#to_lower_case-instance_method": "/documentation/functions/string#to-lower-case",
- "#to_upper_case-instance_method": "/documentation/functions/string#to-upper-case",
- "#transparentize-instance_method": "/documentation/functions/color#transparentize",
- "#type_of-instance_method": "/documentation/functions/meta#type-of",
- "#unique_id-instance_method": "/documentation/functions/string#unique-id",
- "#unit-instance_method": "/documentation/functions/math#unit",
- "#unitless-instance_method": "/documentation/functions/math#unitless",
- "#unquote-instance_method": "/documentation/functions/string#unquote",
- "#variable_exists-instance_method": "/documentation/functions/meta#variable-exists",
- "#zip-instance_method": "/documentation/functions/list#zip"
+ "#index-instance_method": "/documentation/modules/list#index",
+ "#inspect-instance_method": "/documentation/modules/meta#inspect",
+ "#invert-instance_method": "/documentation/modules/color#invert",
+ "#is_bracketed-instance_method": "/documentation/modules/list#is-bracketed",
+ "#is_superselector-instance_method": "/documentation/modules/selector#is-superselector",
+ "#join-instance_method": "/documentation/modules/list#join",
+ "#keywords-instance_method": "/documentation/modules/meta#keywords",
+ "#length-instance_method": "/documentation/modules/list#length",
+ "#lighten-instance_method": "/documentation/modules/color#lighten",
+ "#lightness-instance_method": "/documentation/modules/color#lightness",
+ "#list_separator-instance_method": "/documentation/modules/list#separator",
+ "#map_get-instance_method": "/documentation/modules/map#get",
+ "#map_has_key-instance_method": "/documentation/modules/map#has-key",
+ "#map_keys-instance_method": "/documentation/modules/map#keys",
+ "#map_merge-instance_method": "/documentation/modules/map#merge",
+ "#map_remove-instance_method": "/documentation/modules/map#remove",
+ "#map_values-instance_method": "/documentation/modules/map#values",
+ "#max-instance_method": "/documentation/modules/math#max",
+ "#min-instance_method": "/documentation/modules/math#min",
+ "#mix-instance_method": "/documentation/modules/color#mix",
+ "#mixin_exists-instance_method": "/documentation/modules/meta#mixin-exists",
+ "#nth-instance_method": "/documentation/modules/list#nth",
+ "#opacify-instance_method": "/documentation/modules/color#opacify",
+ "#opacity-instance_method": "/documentation/modules/color#opacity",
+ "#percentage-instance_method": "/documentation/modules/math#percentage",
+ "#quote-instance_method": "/documentation/modules/string#quote",
+ "#random-instance_method": "/documentation/modules/math#random",
+ "#red-instance_method": "/documentation/modules/color#red",
+ "#rgb-instance_method": "/documentation/modules/color#rgb",
+ "#rgba-instance_method": "/documentation/modules/color#rgba",
+ "#round-instance_method": "/documentation/modules/math#round",
+ "#saturate-instance_method": "/documentation/modules/color#saturate",
+ "#saturation-instance_method": "/documentation/modules/color#saturation",
+ "#scale_color-instance_method": "/documentation/modules/color#scale",
+ "#selector_append-instance_method": "/documentation/modules/selector#append",
+ "#selector_extend-instance_method": "/documentation/modules/selector#extend",
+ "#selector_nest-instance_method": "/documentation/modules/selector#nest",
+ "#selector_parse-instance_method": "/documentation/modules/selector#parse",
+ "#selector_replace-instance_method": "/documentation/modules/selector#replace",
+ "#selector_unify-instance_method": "/documentation/modules/selector#unify",
+ "#set-instance_method": "/documentation/modules/list#set",
+ "#simple_selectors-instance_method": "/documentation/modules/selector#simple-selectors",
+ "#str_index-instance_method": "/documentation/modules/string#index",
+ "#str_insert-instance_method": "/documentation/modules/string#insert",
+ "#str_length-instance_method": "/documentation/modules/string#length",
+ "#str_slice-instance_method": "/documentation/modules/string#slice",
+ "#to_lower_case-instance_method": "/documentation/modules/string#to-lower-case",
+ "#to_upper_case-instance_method": "/documentation/modules/string#to-upper-case",
+ "#transparentize-instance_method": "/documentation/modules/color#transparentize",
+ "#type_of-instance_method": "/documentation/modules/meta#type-of",
+ "#unique_id-instance_method": "/documentation/modules/string#unique-id",
+ "#unit-instance_method": "/documentation/modules/math#unit",
+ "#unitless-instance_method": "/documentation/modules/math#is-unitless",
+ "#unquote-instance_method": "/documentation/modules/string#unquote",
+ "#variable_exists-instance_method": "/documentation/modules/meta#variable-exists",
+ "#zip-instance_method": "/documentation/modules/list#zip"
+ };
+
+ var redirect = redirects[window.location.hash];
+ if (redirect) window.location.href = redirect;
+ } else if (window.location.pathname == "/documentation/modules/color") {
+ var redirects = {
+ "#rgb": "/documentation/modules#rgb",
+ "#rgba": "/documentation/modules#rgba",
+ "#hsl": "/documentation/modules#hsl",
+ "#hsla": "/documentation/modules#hsla"
+ };
+
+ var redirect = redirects[window.location.hash];
+ if (redirect) window.location.href = redirect;
+ } else if (window.location.pathname == "/documentation/modules/map") {
+ var redirects = {
+ "#keywords": "/documentation/modules/meta#keywords"
};
var redirect = redirects[window.location.hash];
diff --git a/source/code-snippets/_example-advanced-nesting.html.md.erb b/source/code-snippets/_example-advanced-nesting.html.md.erb
index 0b483fa37..1b952348d 100644
--- a/source/code-snippets/_example-advanced-nesting.html.md.erb
+++ b/source/code-snippets/_example-advanced-nesting.html.md.erb
@@ -1,12 +1,14 @@
For example, suppose you want to write a selector that matches the outer
selector *and* an element selector. You could write a mixin like this one that
-uses the [`selector-unify()` function][] to combine `&` with a user's selector.
+uses the [`selector.unify()` function][] to combine `&` with a user's selector.
-[`selector-unify()` function]: ../functions/selector#selector-unify
+[`selector.unify()` function]: ../modules/selector#unify
<% example do %>
+ @use "sass:selector";
+
@mixin unify-parent($child) {
- @at-root #{selector-unify(&, $child)} {
+ @at-root #{selector.unify(&, $child)} {
@content;
}
}
@@ -20,8 +22,10 @@ uses the [`selector-unify()` function][] to combine `&` with a user's selector.
}
}
===
+ @use "sass:selector";
+
@mixin unify-parent($child)
- @at-root #{selector-unify(&, $child)}
+ @at-root #{selector.unify(&, $child)}
@content
@@ -32,4 +36,12 @@ uses the [`selector-unify()` function][] to combine `&` with a user's selector.
@include unify-parent("select")
/* ...
+ ===
+ .wrapper input.field {
+ /* ... */
+ }
+
+ .wrapper select.field {
+ /* ... */
+ }
<% end %>
diff --git a/source/code-snippets/_example-first-class-function.html.erb b/source/code-snippets/_example-first-class-function.html.erb
index ebcefe309..1b0a4490e 100644
--- a/source/code-snippets/_example-first-class-function.html.erb
+++ b/source/code-snippets/_example-first-class-function.html.erb
@@ -1,14 +1,18 @@
<%# TODO(nweiz): auto-generate this CSS once we're compiling with Dart Sass %>
<% example do %>
+ @use "sass:list";
+ @use "sass:meta";
+ @use "sass:string";
+
/// Return a copy of $list with all elements for which $condition returns `true`
/// removed.
@function remove-where($list, $condition) {
$new-list: ();
- $separator: list-separator($list);
+ $separator: list.separator($list);
@each $element in $list {
- @if not call($condition, $element) {
- $new-list: append($new-list, $element, $separator: $separator);
+ @if not meta.call($condition, $element) {
+ $new-list: list.append($new-list, $element, $separator: $separator);
}
}
@return $new-list;
@@ -18,19 +22,23 @@
content {
@function contains-helvetica($string) {
- @return str-index($string, "Helvetica");
+ @return string.index($string, "Helvetica");
}
- font-family: remove-where($fonts, get-function("contains-helvetica"));
+ font-family: remove-where($fonts, meta.get-function("contains-helvetica"));
}
===
+ @use "sass:list"
+ @use "sass:meta"
+ @use "sass:string"
+
/// Return a copy of $list with all elements for which $condition returns `true`
/// removed.
@function remove-where($list, $condition)
$new-list: ()
- $separator: list-separator($list)
+ $separator: list.separator($list)
@each $element in $list
- @if not call($condition, $element)
- $new-list: append($new-list, $element, $separator: $separator)
+ @if not meta.call($condition, $element)
+ $new-list: list.append($new-list, $element, $separator: $separator)
@return $new-list
@@ -40,9 +48,9 @@
content
@function contains-helvetica($string)
- @return str-index($string, "Helvetica")
+ @return string.index($string, "Helvetica")
- font-family: remove-where($fonts, get-function("contains-helvetica"))
+ font-family: remove-where($fonts, meta.get-function("contains-helvetica"))
===
content {
font-family: Tahoma, Geneva, Arial, sans-serif;
diff --git a/source/code-snippets/_example-list-index.html.erb b/source/code-snippets/_example-list-index.html.erb
index 9b1eba809..99d511536 100644
--- a/source/code-snippets/_example-list-index.html.erb
+++ b/source/code-snippets/_example-list-index.html.erb
@@ -1,9 +1,9 @@
<% example(autogen_css: false) do %>
- @debug index(1px solid red, 1px); // 1
- @debug index(1px solid red, solid); // 2
- @debug index(1px solid red, dashed); // null
+ @debug list.index(1px solid red, 1px); // 1
+ @debug list.index(1px solid red, solid); // 2
+ @debug list.index(1px solid red, dashed); // null
===
- @debug index(1px solid red, 1px) // 1
- @debug index(1px solid red, solid) // 2
- @debug index(1px solid red, dashed) // null
+ @debug list.index(1px solid red, 1px) // 1
+ @debug list.index(1px solid red, solid) // 2
+ @debug list.index(1px solid red, dashed) // null
<% end %>
diff --git a/source/code-snippets/_example-list-nth.html.erb b/source/code-snippets/_example-list-nth.html.erb
index 2b8ce0bbc..535a7f5c0 100644
--- a/source/code-snippets/_example-list-nth.html.erb
+++ b/source/code-snippets/_example-list-nth.html.erb
@@ -1,7 +1,7 @@
<% example(autogen_css: false) do %>
- @debug nth(10px 12px 16px, 2); // 12px
- @debug nth([line1, line2, line3], -1); // line3
+ @debug list.nth(10px 12px 16px, 2); // 12px
+ @debug list.nth([line1, line2, line3], -1); // line3
===
- @debug nth(10px 12px 16px, 2) // 12px
- @debug nth([line1, line2, line3], -1) // line3
+ @debug list.nth(10px 12px 16px, 2) // 12px
+ @debug list.nth([line1, line2, line3], -1) // line3
<% end %>
diff --git a/source/code-snippets/_example-map-get.html.erb b/source/code-snippets/_example-map-get.html.erb
index 062d80380..58d887818 100644
--- a/source/code-snippets/_example-map-get.html.erb
+++ b/source/code-snippets/_example-map-get.html.erb
@@ -1,11 +1,11 @@
<% example(autogen_css: false) do %>
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-get($font-weights, "medium"); // 500
- @debug map-get($font-weights, "extra-bold"); // null
+ @debug map.get($font-weights, "medium"); // 500
+ @debug map.get($font-weights, "extra-bold"); // null
===
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-get($font-weights, "medium") // 500
- @debug map-get($font-weights, "extra-bold") // null
+ @debug map.get($font-weights, "medium") // 500
+ @debug map.get($font-weights, "extra-bold") // null
<% end %>
diff --git a/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb b/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb
index d5bce7938..d81303c83 100644
--- a/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb
+++ b/source/code-snippets/_example-mixin-arbitrary-keyword-arguments.html.erb
@@ -1,8 +1,11 @@
<% example do %>
+ @use "sass:meta";
+
@mixin syntax-colors($args...) {
- @debug keywords($args); // (string: #080, comment: #800, $variable: $60b)
+ @debug meta.keywords($args);
+ // (string: #080, comment: #800, $variable: $60b)
- @each $name, $color in keywords($args) {
+ @each $name, $color in meta.keywords($args) {
pre span.stx-#{$name} {
color: $color;
}
@@ -15,17 +18,20 @@
$variable: #60b,
)
===
+ @use "sass:meta"
+
@mixin syntax-colors($args...)
- @debug keywords($args) // (string: #080, comment: #800, $variable: $60b)
+ @debug meta.keywords($args)
+ // (string: #080, comment: #800, $variable: $60b)
- @each $name, $color in keywords($args)
+ @each $name, $color in meta.keywords($args)
pre span.stx-#{$name}
color: $color
- @include syntax-colors($string: #080, $comment: #800, $variable: #60b);
+ @include syntax-colors($string: #080, $comment: #800, $variable: #60b)
===
pre span.stx-string {
color: #080;
diff --git a/source/code-snippets/_example-module-migrator.html.md.erb b/source/code-snippets/_example-module-migrator.html.md.erb
new file mode 100644
index 000000000..02b7a5f84
--- /dev/null
+++ b/source/code-snippets/_example-module-migrator.html.md.erb
@@ -0,0 +1,25 @@
+```shellsession
+$ cat style.scss
+$body-bg: #000;
+$body-color: #111;
+
+@import "bootstrap";
+
+@include media-breakpoint-up(sm) {
+ .navbar {
+ display: block;
+ }
+}
+$ sass-migrator --migrate-deps module style.scss
+$ cat style.scss
+@use "bootstrap" with (
+ $body-bg: #000,
+ $body-color: #111
+);
+
+@include bootstrap.media-breakpoint-up(sm) {
+ .navbar {
+ display: block;
+ }
+}
+```
diff --git a/source/code-snippets/_example-use-with.html.erb b/source/code-snippets/_example-use-with.html.erb
new file mode 100644
index 000000000..20cac3d3d
--- /dev/null
+++ b/source/code-snippets/_example-use-with.html.erb
@@ -0,0 +1,34 @@
+<% example do %>
+ // _library.scss
+ $black: #000 !default;
+ $border-radius: 0.25rem !default;
+ $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;
+
+ code {
+ border-radius: $border-radius;
+ box-shadow: $box-shadow;
+ }
+ ---
+ // style.scss
+ @use 'library' with (
+ $black: #222,
+ $border-radius: 0.1rem
+ );
+ ===
+ // _library.sass
+ $black: #000 !default
+ $border-radius: 0.25rem !default
+ $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default
+
+ code
+ border-radius: $border-radius
+ box-shadow: $box-shadow
+ ---
+ // style.sass
+ @use 'library' with ($black: #222, $border-radius: 0.1rem)
+ ===
+ code {
+ border-radius: 0.1rem;
+ box-shadow: 0 0.5rem 1rem rgba(#222, 0.15);
+ }
+<% end %>
diff --git a/source/documentation/at-rules/at-root.html.md.erb b/source/documentation/at-rules/at-root.html.md.erb
index a9df05b1c..c1b1f16c9 100644
--- a/source/documentation/at-rules/at-root.html.md.erb
+++ b/source/documentation/at-rules/at-root.html.md.erb
@@ -6,7 +6,7 @@ introduction: >
of using the normal nesting. It's most often used when doing [advanced
nesting](../style-rules/parent-selector#advanced-nesting) with the [SassScript
parent selector](../style-rules/parent-selector#in-sassscript) and [selector
- functions](../functions/selector).
+ functions](../modules/selector).
---
<%= partial 'code-snippets/example-advanced-nesting' %>
diff --git a/source/documentation/at-rules/debug.html.md.erb b/source/documentation/at-rules/debug.html.md.erb
index 9f1072205..acc4abc43 100644
--- a/source/documentation/at-rules/debug.html.md.erb
+++ b/source/documentation/at-rules/debug.html.md.erb
@@ -34,7 +34,7 @@ test.scss:3 Debug: divider offset: 132px
<% fun_fact do %>
You can pass any value to `@debug`, not just a string! It prints the same
- representation of that value as the [`inspect()` function][].
+ representation of that value as the [`meta.inspect()` function][].
- [`inspect()` function]: ../functions/meta#inspect
+ [`meta.inspect()` function]: ../modules/meta#inspect
<% end %>
diff --git a/source/documentation/at-rules/extend.html.md.erb b/source/documentation/at-rules/extend.html.md.erb
index c15cc4338..6f457f324 100644
--- a/source/documentation/at-rules/extend.html.md.erb
+++ b/source/documentation/at-rules/extend.html.md.erb
@@ -168,13 +168,13 @@ unification*:
<% fun_fact do %>
You can directly access Sass's intelligent unification using [selector
- functions][]! The [`selector-unify()` function][] returns a selector that
- matches the intersection of two selectors, while the [`selector-extend()`
+ functions][]! The [`selector.unify()` function][] returns a selector that
+ matches the intersection of two selectors, while the [`selector.extend()`
function][] works just like `@extend`, but on a single selector.
- [selector functions]: ../functions/selector
- [`selector-unify()` function]: ../functions/selector#selector-unify
- [`selector-extend()` function]: ../functions/selector#selector-extend
+ [selector functions]: ../modules/selector
+ [`selector.unify()` function]: ../modules/selector#unify
+ [`selector.extend()` function]: ../modules/selector#extend
<% end %>
<% heads_up do %>
@@ -199,6 +199,36 @@ are.
<%= partial "code-snippets/example-placeholder" %>
+### Private Placeholders
+
+Like [module members][], a placeholder selector can be marked private by
+starting its name with either `-` or `_`. A private placeholder selector can
+only be extended within the stylesheet that defines it. To any other
+stylesheets, it will look as though that selector doesn't exist.
+
+[module members]: use#private-members
+
+## Extension Scope
+
+When one stylesheet extends a selector, that extension will only affect style
+rules written in *upstream* modules—that is, modules that are loaded by that
+stylesheet using the [`@use` rule][] or the [`@forward` rule][], modules loaded
+by *those* modules, and so on. This helps make your `@extend` rules more
+predictable, ensuring that they affect only the styles you were aware of when
+you wrote them.
+
+[`@use` rule]: use
+[`@forward` rule]: forward
+
+<% heads_up do %>
+ Extensions aren't scoped at all if you're using the [`@import` rule][]. Not
+ only will they affect every stylesheet you import, they'll affect every
+ stylesheet that imports your stylesheet, everything else those stylesheets
+ import, and so on. Without `@use`, extensions are *global*.
+
+ [`@import` rule]: import
+<% end %>
+
## Mandatory and Optional Extends
Normally, if an `@extend` doesn't match any selectors in the stylesheet, Sass
diff --git a/source/documentation/at-rules/forward.html.md.erb b/source/documentation/at-rules/forward.html.md.erb
new file mode 100644
index 000000000..c0804c4e6
--- /dev/null
+++ b/source/documentation/at-rules/forward.html.md.erb
@@ -0,0 +1,181 @@
+---
+title: "@forward"
+introduction: >
+ The `@forward` rule loads a Sass stylesheet and makes its [mixins](mixin),
+ [functions](function), and [variables](../variables) available when your
+ stylesheet is loaded with the [`@use` rule](use). It makes it possible to
+ organize Sass libraries across many files, while allowing their users to load
+ a single entrypoint file.
+---
+
+The rule is written `@forward ""`. It loads the module at the given URL
+just like `@use`, but it makes the [public][] members of the loaded module
+available to users of your module as though they were defined directly in your
+module. Those members aren't available in your module, though—if you want that,
+you'll need to write a `@use` rule as well. Don't worry, it'll only load the
+module once!
+
+[public]: use#private-members
+
+<% fun_fact do %>
+ The `@forward` rule acts just like `@use` when it comes to a module's CSS.
+ Styles from a forwarded module will be included in the compiled CSS output,
+ and the module with the `@forward` can [extend][] it, even if it isn't also
+ `@use`d.
+
+ [extend]: extend
+<% end %>
+
+<% example do %>
+ // src/_list.scss
+ @mixin list-reset {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+ ---
+ // bootstrap.scss
+ @forward "src/list";
+ ---
+ // styles.scss
+ @use "bootstrap";
+
+ li {
+ @include bootstrap.list-reset;
+ }
+ ===
+ // src/_list.sass
+ @mixin list-reset
+ margin: 0
+ padding: 0
+ list-style: none
+ ---
+ // bootstrap.sass
+ @forward "src/list"
+ ---
+ // styles.sass
+ @use "bootstrap"
+
+ li
+ @include bootstrap.list-reset
+ ===
+ li {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+<% end %>
+
+## Adding a Prefix
+
+Because module members are usually used with [a namespace][], short and simple
+names are usually the most readable option. But those names might not make sense
+outside the module they're defined in, so `@forward` has the option of adding an
+extra prefix to all the members it forwards.
+
+This is written `@forward "" as -*`, and it adds the given prefix
+to the beginning of every mixin, function, and variable name forwarded by the
+module. For example, if the module defines a member named `reset` and it's
+forwarded `as list-*`, downstream stylesheets will refer to it as `list-reset`.
+
+[a namespace]: use#loading-members
+
+<% example do %>
+ // src/_list.scss
+ @mixin reset {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+ ---
+ // bootstrap.scss
+ @forward "src/list" as list-*;
+ ---
+ // styles.scss
+ @use "bootstrap";
+
+ li {
+ @include bootstrap.list-reset;
+ }
+ ===
+ // src/_list.sass
+ @mixin reset
+ margin: 0
+ padding: 0
+ list-style: none
+ ---
+ // bootstrap.sass
+ @forward "src/list" as list-*
+ ---
+ // styles.sass
+ @use "bootstrap"
+
+ li
+ @include bootstrap.list-reset
+ ===
+ li {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+<% end %>
+
+## Controlling Visibility
+
+Sometimes, you don't want to forward *every* member from a module. You may want
+to keep some members private so that only your package can use them, or you may
+want to require your users to load some members a different way. You can control
+exactly which members get forwarded by writing `@forward "" hide
+` or `@forward "" show `.
+
+The `hide` form means that the listed members shouldn't be forwarded, but
+everything else should. The `show` form means that *only* the named members
+should be forwarded. In both forms, you list the names of mixins, functions, or
+variables (including the `$`).
+
+<% example(autogen_css: false) do %>
+ // src/_list.scss
+ $horizontal-list-gap: 2em;
+
+ @mixin list-reset {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+
+ @mixin list-horizontal {
+ @include reset;
+
+ li {
+ display: inline-block;
+ margin: {
+ left: -2px;
+ right: $horizontal-list-gap;
+ }
+ }
+ }
+ ---
+ // bootstrap.scss
+ @forward "src/list" hide list-reset, $horizontal-list-gap;
+ ===
+ // src/_list.sass
+ $horizontal-list-gap: 2em
+
+ @mixin list-reset
+ margin: 0
+ padding: 0
+ list-style: none
+
+
+ @mixin list-horizontal
+ @include reset
+
+ li
+ display: inline-block
+ margin:
+ left: -2px
+ right: $horizontal-list-gap
+ ---
+ // bootstrap.sass
+ @forward "src/list" hide list-reset, $horizontal-list-gap
+<% end %>
diff --git a/source/documentation/at-rules/function.html.md.erb b/source/documentation/at-rules/function.html.md.erb
index 33b5da620..d8b5de665 100644
--- a/source/documentation/at-rules/function.html.md.erb
+++ b/source/documentation/at-rules/function.html.md.erb
@@ -190,20 +190,20 @@ argument is known as an [argument list][].
#### Taking Arbitrary Keyword Arguments
Argument lists can also be used to take arbitrary keyword arguments. The
-[`keywords()` function][] takes an argument list and returns any extra keywords
-that were passed to the function as a [map][] from argument names (not including
-`$`) to those arguments' values.
+[`meta.keywords()` function][] takes an argument list and returns any extra
+keywords that were passed to the function as a [map][] from argument names (not
+including `$`) to those arguments' values.
-[`keywords()` function]: ../functions/map#keywords
+[`meta.keywords()` function]: ../modules/meta#keywords
[map]: ../values/maps
<% fun_fact do %>
- If you don't ever pass an argument list to the [`keywords()` function][], that
- argument list won't allow extra keyword arguments. This helps callers of your
- function make sure they haven't accidentally written any typos in their
- argument names.
+ If you don't ever pass an argument list to the [`meta.keywords()` function][],
+ that argument list won't allow extra keyword arguments. This helps callers of
+ your function make sure they haven't accidentally misspelled any argument
+ names.
- [`keywords()` function]: ../functions/map#keywords
+ [`meta.keywords()` function]: ../modules/meta#keywords
<% end %>
#### Passing Arbitrary Arguments
@@ -258,26 +258,30 @@ an [`@else` block][].
[`@else` block]: control/if#else
-<% example do %>
+<% example(autogen_css: false) do %>
+ @use "sass:string";
+
@function str-insert($string, $insert, $index) {
// Avoid making new strings if we don't need to.
- @if str-length($string) == 0 {
+ @if string.length($string) == 0 {
@return $insert;
}
- $before: str-slice($string, 0, $index);
- $after: str-slice($string, $index);
+ $before: string.slice($string, 0, $index);
+ $after: string.slice($string, $index);
@return $before + $insert + $after;
}
===
+ @use "sass:string"
+
@function str-insert($string, $insert, $index)
// Avoid making new strings if we don't need to.
- @if str-length($string) == 0
+ @if string.length($string) == 0
@return $insert
- $before: str-slice($string, 0, $index)
- $after: str-slice($string, $index)
+ $before: string.slice($string, 0, $index)
+ $after: string.slice($string, $index)
@return $before + $insert + $after
<% end %>
@@ -289,7 +293,45 @@ implementations also make it possible to define [custom functions][] in the host
language. And of course, you can always call [plain CSS functions][] (even ones
with [weird syntax][]).
-[core library]: ../functions
+[core library]: ../modules
[custom functions]: ../js-api#functions
-[plain CSS functions]: ../functions/css
+[plain CSS functions]: #plain-css-functions
[weird syntax]: ../syntax/special-functions
+
+### Plain CSS Functions
+
+Any function call that's not either a user-defined or [built-in](../modules)
+function is compiled to a plain CSS function (unless it uses [Sass argument
+syntax](../at-rules/function#arguments)). The arguments will be compiled to CSS
+and included as-is in the function call. This ensures that Sass supports all CSS
+functions without needing to release new versions every time a new one is added.
+
+<% example(autogen_css: false) do %>
+ @debug var(--main-bg-color); // var(--main-bg-color)
+
+ $primary: #f2ece4;
+ $accent: #e1d7d2;
+ @debug radial-gradient($primary, $accent); // radial-gradient(#f2ece4, #e1d7d2)
+ ===
+ @debug var(--main-bg-color) // var(--main-bg-color)
+
+ $primary: #f2ece4
+ $accent: #e1d7d2
+ @debug radial-gradient($primary, $accent) // radial-gradient(#f2ece4, #e1d7d2)
+<% end %>
+
+<% heads_up do %>
+ Because any unknown function will be compiled to CSS, it's easy to miss when
+ you typo a function name. Consider running a [CSS linter][] on your
+ stylesheet's output to be notified when this happens!
+
+ [CSS linter]: https://stylelint.io/
+<% end %>
+
+<% fun_fact do %>
+ Some CSS functions, like `calc()` and `element()` have unusual syntax. Sass
+ [parses these functions specially][] as [unquoted strings][].
+
+ [parses these functions specially]: ../syntax/special-functions
+ [unquoted strings]: ../values/strings#unquoted
+<% end %>
diff --git a/source/documentation/at-rules/import.html.md.erb b/source/documentation/at-rules/import.html.md.erb
index 542addc1c..0b02f75ab 100644
--- a/source/documentation/at-rules/import.html.md.erb
+++ b/source/documentation/at-rules/import.html.md.erb
@@ -18,6 +18,48 @@ required to have quotes.
[indented syntax]: ../syntax#the-indented-syntax
+<% heads_up do %>
+ The Sass team discourages the continued use of the `@import` rule. Sass will
+ [gradually phase it out][] over the next few years, and eventually remove it
+ from the language entirely. Prefer the [`@use` rule][] instead.
+
+ [gradually phase it out]: https://github.com/sass/sass/blob/master/accepted/module-system.md#timeline
+ [`@use` rule]: use
+
+ #### What's Wrong With `@import`?
+
+ The `@import` rule has a number of serious issues:
+
+ * `@import` makes all variables, mixins, and functions globally accessible.
+ This makes it very difficult for people (or tools) to tell where anything is
+ defined.
+
+ * Because everything's global, libraries must prefix to all their members to
+ avoid naming collisions.
+
+ * [`@extend` rules][] are also global, which makes it difficult to predict
+ which style rules will be extended.
+
+ [`@extend` rules]: extend
+
+ * Each stylesheet is executed and its CSS emitted *every time* it's
+ `@import`ed, which increases compilation time and produces bloated output.
+
+ * There was no way to define private members or placeholder selectors that
+ were inaccessible to downstream stylesheets.
+
+ The new module system and the `@use` rule address all these problems.
+
+ #### How Do I Migrate?
+
+ We've written a [migration tool][] that automatically converts most
+ `@import`-based code to `@use`-based code in a flash. Just point it at your
+ entrypoints and let it run!
+
+ [migration tool]: /documentation/cli/migrator
+
+<% end %>
+
<% example do %>
// foundation/_code.scss
code {
@@ -414,3 +456,89 @@ for example based on mixin parameters.
@include google-font("Droid Sans")
<% end %>
+
+## Import and Modules
+
+<%= partial '../snippets/module-system-status' %>
+
+Sass's [module system][] integrates seamlessly with `@import`, whether you're
+importing a file that contains `@use` rules or loading a file that contains
+imports as a module. We want to make the transition from `@import` to `@use` as
+smooth as possible.
+
+[module system]: use
+
+### Importing a Module-System File
+
+When you import a file that contains `@use` rules, the importing file has access
+to all members (even private members) defined directly in that file, but *not*
+any members from modules that file has loaded. However, if that file contains
+[`@forward` rules][], the importing file will have access to forwarded members.
+This means that you can import a library that was written to be used with the
+module system.
+
+[`@forward` rules]: forward
+
+<% heads_up do %>
+ When a file with `@use` rules is imported, all the CSS transitively loaded by
+ those is included in the resulting stylesheet, even if it's already been
+ included by another import. If you're not careful, this can result in bloated
+ CSS output!
+<% end %>
+
+#### Import-Only Files
+
+An API that makes sense for `@use` might not make sense for `@import`. For
+example, `@use` adds a namespace to all members by default so you can safely use
+short names, but `@import` doesn't so you might need something longer. If you're
+a library author, you may be concerned that if you update your library to use
+the new module system, your existing `@import`-based users will break.
+
+To make this easier, Sass also supports *import-only files*. If you name a file
+`.import.scss`, it will only be loaded for imports, not for `@use`s. This
+way, you can retain compatibility for `@import` users while still providing a
+nice API for users of the new module system.
+
+<% example(autogen_css: false) do %>
+ // _reset.scss
+
+ // Module system users write `@include reset.list()`.
+ @mixin list() {
+ ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ }
+ }
+ ---
+ // _reset.import.scss
+
+ // Legacy import users can keep writing `@include reset-list()`.
+ @forward "reset" as reset-*;
+ ===
+ // _reset.sass
+
+ // Module system users write `@include reset.list()`.
+ @mixin list()
+ ul
+ margin: 0
+ padding: 0
+ list-style: none
+ ---
+ // _reset.import.sass
+
+ // Legacy import users can keep writing `@include reset-list()`.
+ @forward "reset" as reset-*
+<% end %>
+
+### Loading a Module That Contains Imports
+
+When you use `@use` (or `@forward`) load a module that uses `@import`, that
+module will contain all the public members defined by the stylesheet you load
+*and* everything that stylesheet transitively imports. In other words,
+everything that's imported is treated as though it were written in one big
+stylesheet.
+
+This makes it easy to convert start using `@use` in a stylesheet even before all
+the libraries you depend on have converted to the new module system. Be aware,
+though, that if they do convert their APIs may well change!
diff --git a/source/documentation/at-rules/mixin.html.md.erb b/source/documentation/at-rules/mixin.html.md.erb
index 40f35438a..42cb1d6a5 100644
--- a/source/documentation/at-rules/mixin.html.md.erb
+++ b/source/documentation/at-rules/mixin.html.md.erb
@@ -256,11 +256,11 @@ is known as an [argument list][].
#### Taking Arbitrary Keyword Arguments
Argument lists can also be used to take arbitrary keyword arguments. The
-[`keywords()` function][] takes an argument list and returns any extra keywords
-that were passed to the mixin as a [map][] from argument names (not including
-`$`) to those arguments' values.
+[`meta.keywords()` function][] takes an argument list and returns any extra
+keywords that were passed to the mixin as a [map][] from argument names (not
+including `$`) to those arguments' values.
-[`keywords()` function]: ../functions/map#keywords
+[`meta.keywords()` function]: ../modules/meta#keywords
[map]: ../values/maps
<%# TODO(nweiz): auto-generate this CSS once we're compiling with Dart Sass %>
@@ -268,12 +268,12 @@ that were passed to the mixin as a [map][] from argument names (not including
<%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %>
<% fun_fact do %>
- If you don't ever pass an argument list to the [`keywords()` function][], that
- argument list won't allow extra keyword arguments. This helps callers of your
- mixin make sure they haven't accidentally written any typos in their argument
+ If you don't ever pass an argument list to the [`meta.keywords()` function][],
+ that argument list won't allow extra keyword arguments. This helps callers of
+ your mixin make sure they haven't accidentally misspelled any argument
names.
- [`keywords()` function]: ../functions/map#keywords
+ [`meta.keywords()` function]: ../modules/meta#keywords
<% end %>
#### Passing Arbitrary Arguments
diff --git a/source/documentation/at-rules/use.html.md.erb b/source/documentation/at-rules/use.html.md.erb
new file mode 100644
index 000000000..d9d703143
--- /dev/null
+++ b/source/documentation/at-rules/use.html.md.erb
@@ -0,0 +1,431 @@
+---
+title: "@use"
+table_of_contents: true
+introduction: >
+ The `@use` rule loads [mixins](mixin), [functions](function), and
+ [variables](../variables) from other Sass stylesheets, and combines CSS from
+ multiple stylesheets together. Stylesheets loaded by `@use` are called
+ "modules". Sass also provides [built-in modules](../modules) full of useful
+ functions.
+---
+
+<% content_for :before_introduction do %>
+ <%= partial '../snippets/module-system-status' %>
+<% end %>
+
+The simplest `@use` rule is written `@use ""`, which loads the module at
+the given URL. Any styles loaded this way will be included exactly once in the
+compiled CSS output, no matter how many times those styles are loaded.
+
+<% heads_up do %>
+ A stylesheet's `@use` rules must come before any rules other than `@forward`,
+ including [style rules][]. However, you can declare variables before `@use`
+ rules to use when [configuring modules][].
+
+ [style rules]: ../style-rules
+ [configuring modules]: #configuring-modules
+<% end %>
+
+<% example do %>
+ // foundation/_code.scss
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+ ---
+ // foundation/_lists.scss
+ ul, ol {
+ text-align: left;
+
+ & & {
+ padding: {
+ bottom: 0;
+ left: 0;
+ }
+ }
+ }
+ ---
+ // style.scss
+ @use 'foundation/code';
+ @use 'foundation/lists';
+ ===
+ // foundation/_code.sass
+ code
+ padding: .25em
+ line-height: 0
+ ---
+ // foundation/_lists.sass
+ ul, ol
+ text-align: left
+
+ & &
+ padding:
+ bottom: 0
+ left: 0
+ ---
+ // style.sass
+ @use 'foundation/code'
+ @use 'foundation/lists'
+ ===
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+
+ ul, ol {
+ text-align: left;
+ }
+ ul ul, ol ol {
+ padding-bottom: 0;
+ padding-left: 0;
+ }
+<% end %>
+
+## Loading Members
+
+You can access variables, functions, and mixins from another module by writing
+`.`, `.()`, or `@include
+.()`. By default, the namespace is just the last component of
+the module's URL.
+
+Members (variables, functions, and mixins) loaded with `@use` are only visible
+in the stylesheet that loads them. Other stylesheets will need to write their
+own `@use` rules if they also want to access them. This helps make it easy to
+figure out exactly where each member is coming from. If you want to load members
+from many files at once, you can use the [`@forward` rule][] to forward them all
+from one shared file.
+
+[`@forward` rule]: forward
+
+<% fun_fact do %>
+ Because `@use` adds namespaces to member names, it's safe to choose very
+ simple names like `$radius` or `$width` when writing a stylesheet. This is
+ different from the old [`@import` rule][], which encouraged that users write
+ long names like `$mat-corner-radius` to avoid conflicts with other
+ libraries, and it helps keep your stylesheets clear and easy to read!
+
+ [`@import` rule]: import
+<% end %>
+
+<% example do %>
+ // src/_corners.scss
+ $radius: 3px;
+
+ @mixin rounded {
+ border-radius: $radius;
+ }
+ ---
+ // style.scss
+ @use "src/corners";
+
+ .button {
+ @include corners.rounded;
+ padding: 5px + corners.$radius;
+ }
+ ===
+ // src/_corners.sass
+ $radius: 5px
+
+ @mixin rounded
+ border-radius: $radius
+ ---
+ // style.sass
+ @use "src/corners"
+
+ .button
+ @include corners.rounded
+ padding: 5px + corners.$radius
+ ===
+ .button {
+ border-radius: 3px;
+ padding: 8px;
+ }
+<% end %>
+
+### Choosing a Namespace
+
+By default, a module's namespace is just the last component of its URL without a
+file extension. However, sometimes you might want to choose a different
+namespace—you might want to use a shorter name for a module you refer to a lot,
+or you might be loading multiple modules with the same filename. You can do this
+by writine `@use "" as `.
+
+<% example do %>
+ // src/_corners.scss
+ $radius: 3px;
+
+ @mixin rounded {
+ border-radius: $radius;
+ }
+ ---
+ // style.scss
+ @use "src/corners" as c;
+
+ .button {
+ @include c.rounded;
+ padding: 5px + c.$radius;
+ }
+ ===
+ // src/_corners.sass
+ $radius: 5px
+
+ @mixin rounded
+ border-radius: $radius
+ ---
+ // style.sass
+ @use "src/corners" as c
+
+ .button
+ @include c.rounded
+ padding: 5px + c.$radius
+ ===
+ .button {
+ border-radius: 3px;
+ padding: 8px;
+ }
+<% end %>
+
+You can even load a module *without* a namespace by writing `@use "" as *`.
+We recommend you only do this for stylesheets written by you, though; otherwise,
+they may introduce new members that cause name conflicts!
+
+<% example do %>
+ // src/_corners.scss
+ $radius: 3px;
+
+ @mixin rounded {
+ border-radius: $radius;
+ }
+ ---
+ // style.scss
+ @use "src/corners" as *;
+
+ .button {
+ @include rounded;
+ padding: 5px + $radius;
+ }
+ ===
+ // src/_corners.sass
+ $radius: 5px
+
+ @mixin rounded
+ border-radius: $radius
+ ---
+ // style.sass
+ @use "src/corners" as *
+
+ .button
+ @include rounded
+ padding: 5px + $radius
+ ===
+ .button {
+ border-radius: 3px;
+ padding: 8px;
+ }
+<% end %>
+
+### Private Members
+
+As a stylesheet author, you may not want all the members you define to be
+available outside your stylesheet. Sass makes it easy to define a private member
+by starting its name with either `-` or `_`. These members will work just like
+normal within the stylesheet that defines them, but they won't be part of a
+module's public API. That means stylesheets that load your module can't see
+them!
+
+<% fun_fact do %>
+ If you want to make a member private to an entire *package* rather than just a
+ single module, just don't [forward its module][] from any of your package's
+ entrypoints (the stylesheets you tell your users to load to use your package).
+ You can even [hide that member][] while forwarding the rest of its module!
+
+ [forward its module]: forward
+ [hide that member]: forward#controlling-visibility
+<% end %>
+
+<% example(autogen_css: false) do %>
+ // src/_corners.scss
+ $-radius: 3px;
+
+ @mixin rounded {
+ border-radius: $-radius;
+ }
+ ---
+ // style.scss
+ @use "src/corners";
+
+ .button {
+ @include corners.rounded;
+
+ // This is an error! $-radius isn't visible outside of `_corners.scss`.
+ padding: 5px + corners.$-radius;
+ }
+ ===
+ // src/_corners.sass
+ $-radius: 5px
+
+ @mixin rounded
+ border-radius: $radius
+ ---
+ // style.sass
+ @use "src/corners"
+
+ .button
+ @include corners.rounded
+
+ // This is an error! $-radius isn't visible outside of `_corners.scss`.
+ padding: 5px + corners.$-radius
+<% end %>
+
+## Configuring Modules
+
+A stylesheet can define variables with the [`!default` flag][] to make them
+configurable. To load a module with configuration, write `@use with
+(: , : )`. The configured values will override
+the variables' default values.
+
+[`!default` flag]: ../variables#default-values
+
+<%= partial '../../code-snippets/example-use-with' %>
+
+## Finding the Module
+
+It wouldn't be any fun to write out absolute URLs for every stylesheet you load,
+so Sass's algorithm for finding a module makes it a little easier. For starters,
+you don't have to explicitly write out the extension of the file you want to
+load; `@use "variables"` will automatically load `variables.scss`,
+`variables.sass`, or `variables.css`.
+
+<% heads_up do %>
+ To ensure that stylesheets work on every operating system, Sass loads files by
+ *URL*, not by *file path*. This means you need to use forward slashes, not
+ backslashes, even on Windows.
+<% end %>
+
+### Load Paths
+
+All Sass implementations allow users to provide *load paths*: paths on the
+filesystem that Sass will look in when locating modules. For example, if you
+pass `node_modules/susy/sass` as a load path, you can use `@use "susy"` to load
+`node_modules/susy/sass/susy.scss`.
+
+Modules will always be loaded relative to the current file first, though. Load
+paths will only be used if no relative file exists that matches the module's
+URL. This ensures that you can't accidentally mess up your relative imports when
+you add a new library.
+
+<% fun_fact do %>
+ Unlike some other languages, Sass doesn't require that you use `./` for
+ relative imports. Relative imports are always available.
+<% end %>
+
+### Partials
+
+As a convention, Sass files that are only meant to be loaded as modules, not
+compiled on their own, begin with `_` (as in `_code.scss`). These are called
+*partials*, and they tell Sass tools not to try to compile those files on their
+own. You can leave off the `_` when importing a partial.
+
+### Index Files
+
+If you write an `_index.scss` or `_index.sass` in a folder, the index file will
+be loaded automatically. when you load the URL for the folder itself.
+
+<% example do %>
+ // foundation/_code.scss
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+ ---
+ // foundation/_lists.scss
+ ul, ol {
+ text-align: left;
+
+ & & {
+ padding: {
+ bottom: 0;
+ left: 0;
+ }
+ }
+ }
+ ---
+ // foundation/_index.scss
+ @use 'code';
+ @use 'lists';
+ ---
+ // style.scss
+ @use 'foundation';
+ ===
+ // foundation/_code.sass
+ code
+ padding: .25em
+ line-height: 0
+ ---
+ // foundation/_lists.sass
+ ul, ol
+ text-align: left
+
+ & &
+ padding:
+ bottom: 0
+ left: 0
+ ---
+ // foundation/_index.sass
+ @use 'code'
+ @use 'lists'
+ ---
+ // style.sass
+ @use 'foundation'
+ ===
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+
+ ul, ol {
+ text-align: left;
+ }
+ ul ul, ol ol {
+ padding-bottom: 0;
+ padding-left: 0;
+ }
+<% end %>
+
+## Loading CSS
+
+In addition to loading `.sass` and `.scss` files, Sass can load plain old `.css`
+files.
+
+<% example do %>
+ // code.css
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+ ---
+ // style.scss
+ @use 'code';
+ ===
+ // code.css
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+ ---
+ // style.sass
+ @use 'code'
+ ===
+ code {
+ padding: .25em;
+ line-height: 0;
+ }
+<% end %>
+
+CSS files loaded as modules don't allow any special Sass features and so can't
+expose any Sass variables, functions, or mixins. In order to make sure authors
+don't accidentally write Sass in their CSS, all Sass features that aren't also
+valid CSS will produce errors. Otherwise, the CSS will be rendered as-is. It can
+even be [extended][]!
+
+[extended]: extend
diff --git a/source/documentation/breaking-changes/css-vars.html.md.erb b/source/documentation/breaking-changes/css-vars.html.md.erb
index f88a8a353..0b119402d 100644
--- a/source/documentation/breaking-changes/css-vars.html.md.erb
+++ b/source/documentation/breaking-changes/css-vars.html.md.erb
@@ -70,21 +70,29 @@ versions, and so is recommended for all stylesheets.
<% heads_up do %>
Because interpolation removes quotation marks from quoted strings, it may be
- necessary to wrap them in the [`inspect()` function][] to preserve their
+ necessary to wrap them in the [`meta.inspect()` function][] to preserve their
quotes.
- [`inspect()` function]: ../functions/meta#inspect
+ [`meta.inspect()` function]: ../modules/meta#inspect
<% example do %>
+ @use "sass:meta";
+
$font-family-monospace: Menlo, Consolas, "Courier New", monospace;
:root {
- --font-family-monospace: #{inspect($font-family-monospace)};
+ --font-family-monospace: #{meta.inspect($font-family-monospace)};
}
===
+ @use "sass:meta"
+
$font-family-monospace: Menlo, Consolas, "Courier New", monospace
:root
- --font-family-monospace: #{inspect($font-family-monospace)}
+ --font-family-monospace: #{meta.inspect($font-family-monospace)}
+ ===
+ :root {
+ --font-family-monospace: Menlo, Consolas, "Courier New", monospace;
+ }
<% end %>
<% end %>
diff --git a/source/documentation/breaking-changes/slash-div.html.md.erb b/source/documentation/breaking-changes/slash-div.html.md.erb
index fabeba304..149e95959 100644
--- a/source/documentation/breaking-changes/slash-div.html.md.erb
+++ b/source/documentation/breaking-changes/slash-div.html.md.erb
@@ -19,21 +19,25 @@ use `/` as a separator, this is becoming more and more painful to Sass users.
[CSS Grid]: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-row
[new `rgb()` and `hsl()` syntax]: https://drafts.csswg.org/css-color/#rgb-functions
-Because Sass is a CSS superset, it's redefining `/` to be *only* a separator. `/`
-will be treated as a new type of list separator, similar to how `,` works today.
-Division will instead be written using the new `divide()` function. This
-function will behave exactly the same as `/` does today.
+Because Sass is a CSS superset, it's redefining `/` to be *only* a separator.
+`/` will be treated as a new type of list separator, similar to how `,` works
+today. Division will instead be written using the new `math.div()` function.
+This function will behave exactly the same as `/` does today.
<% example do %>
+ @use "sass:math";
+
// Future Sass, doesn't work yet!
.item3 {
- $row: span divide(6, 2) / 7; // A two-element slash-separated list.
+ $row: span math.div(6, 2) / 7; // A two-element slash-separated list.
grid-row: $row;
}
===
+ @use "sass:math"
+
// Future Sass, doesn't work yet!
.item3
- $row: span divide(6, 2) / 7 // A two-element slash-separated list.
+ $row: span math.div(6, 2) / 7 // A two-element slash-separated list.
grid-row: $row
===
.item3 {
@@ -43,34 +47,39 @@ function will behave exactly the same as `/` does today.
## Transition Period
-<% impl_status dart: false, libsass: false, ruby: false, feature: "divide() and slash-list()" %>
+<% impl_status dart: false, libsass: false, ruby: false,
+ feature: "math.div() and list.slash()" %>
-To ease the transition, implementations will begin by adding the `divide()`
+To ease the transition, implementations will begin by adding the `math.div()`
function. The `/` operator will continue to do division, but it also prints a
deprecation warning when it does so. Users should switch all division to use
-`divide()` instead.
+`math.div()` instead.
<% example(autogen_css: false) do %>
+ @use "sass:math";
+
// WRONG, will not work in future Sass versions.
@debug (12px/4px); // 3
// RIGHT, will work in future Sass versions.
- @debug divide(12px, 4px); // 3
+ @debug math.div(12px, 4px); // 3
===
+ @use "sass:math"
+
// WRONG, will not work in future Sass versions.
@debug (12px/4px) // 3
// RIGHT, will work in future Sass versions.
- @debug divide(12px, 4px) // 3
+ @debug math.div(12px, 4px) // 3
<% end %>
Slash-separated lists will also be available in the transition period. Because
-they can't be created with `/` yet, the `slash-list()` function will be added to
+they can't be created with `/` yet, the `list.slash()` function will be added to
create them. You will also be able to pass `"slash"` as the `$separator` to the
-[`join()` function][] and the [`append()` function][].
+[`list.join()` function][] and the [`list.append()` function][].
-[`join()` function]: ../functions/list#join
-[`append()` function]: ../functions/list#append
+[`list.join()` function]: ../modules/list#join
+[`list.append()` function]: ../modules/list#append
<% example do %>
.item3 {
@@ -90,7 +99,7 @@ create them. You will also be able to pass `"slash"` as the `$separator` to the
## Automatic Migration
You can use [the Sass migrator][] to automatically update your stylesheets to
-use `divide()` and `slash-list()`.
+use `math.div()` and `list.slash()`.
[the Sass migrator]: https://github.com/sass/migrator#readme
diff --git a/source/documentation/cli/dart-sass.html.md.erb b/source/documentation/cli/dart-sass.html.md.erb
index 820916126..3d7820ce5 100644
--- a/source/documentation/cli/dart-sass.html.md.erb
+++ b/source/documentation/cli/dart-sass.html.md.erb
@@ -91,11 +91,11 @@ The `--stdin` flag may not be used with [many-to-many mode][].
This flag tells Sass to parse the input file as the [indented syntax][]. If it's
used in [many-to-many mode][], all input files are parsed as the indented
-syntax, although files they [import][] will have their syntax determined as
-usual. The inverse, `--no-indented`, can be used to force all input files to be
-parsed as [SCSS][] instead.
+syntax, although files they [use][] will have their syntax determined as usual.
+The inverse, `--no-indented`, can be used to force all input files to be parsed
+as [SCSS][] instead.
-[import]: ../at-rules/import
+[use]: ../at-rules/use
The `--indented` flag is mostly useful when the input file is coming from
[standard input][], so its syntax can't be automatically determined.
@@ -110,10 +110,10 @@ h1 {
#### `--load-path`
This option (abbreviated `-I`) adds an additional [load path][] for Sass to look
-for imports. It can be passed multiple times to provide multiple load paths.
+for stylesheets. It can be passed multiple times to provide multiple load paths.
Earlier load paths will take precedence over later ones.
-[load path]: ../at-rules/import#load-paths
+[load path]: ../at-rules/use#load-paths
```shellsession
$ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css
@@ -341,18 +341,20 @@ Error: Expected expression.
This flag (abbreviated `-i`) tells Sass to run in interactive mode, where you
can write [SassScript expressions][] and see their results. Interactive mode
-also supports [variables][].
+also supports [variables][] and [`@use` rules][].
[SassScript expressions]: ../syntax/structure#expressions
[variables]: ../variables
+[`@use` rules]: ../at-rules/use
```shellsession
$ sass --interactive
>> 1px + 1in
97px
+>> @use "sass:map"
>> $map: ("width": 100px, "height": 70px)
("width": 100px, "height": 70px)
->> map-get($map, "width")
+>> map.get($map, "width")
100px
```
diff --git a/source/documentation/cli/migrator.html.md.erb b/source/documentation/cli/migrator.html.md.erb
new file mode 100644
index 000000000..ddcc8b025
--- /dev/null
+++ b/source/documentation/cli/migrator.html.md.erb
@@ -0,0 +1,345 @@
+---
+title: "Migrator"
+table_of_contents: true
+introduction: >
+ The Sass migrator automatically updates your Sass files to help you move on to
+ the latest and greatest version of the language. Each of its commands migrates
+ a single feature, to give you as much control as possible over what you update
+ and when.
+---
+
+## Usage
+
+To use the Sass migrator, tell it [which migration][] you want to run and what
+Sass files you want to migrate:
+
+[which migration]: #migrations
+
+```
+sass-migrator
+```
+
+By default, the migrator will only change files that you explicitly pass on the
+command line. Passing the [`--migrate-deps` option][] tells the migrator to also
+change all the stylesheets that are loaded using the [`@use` rule][],
+[`@forward` rule][], or [`@import` rule][]. And if you want to do a test run to
+see what changes will be made without actually saving them, you can pass
+[--dry-run][] [--verbose][]
(or `-nv` for short).
+
+[`--migrate-deps` option]: #migrate-deps
+[`@use` rule]: ../at-rules/use
+[`@forward` rule]: ../at-rules/forward
+[`@import` rule]: ../at-rules/import
+[--dry-run]: #dry-run
+[--verbose]: #verbose
+
+<%= partial 'code-snippets/example-module-migrator' %>
+
+## Installation
+
+You can install the Sass migrator from most of the same places that you can
+install [Dart Sass](/dart-sass):
+
+### Standalone
+
+You can install the Sass migrator on Windows, Mac, or Linux by downloading the
+package for your operating system [from GitHub][] and [adding it to your
+`PATH`][].
+
+[from GitHub]: <%= release_url(:migrator) %>
+[adding it to your `PATH`]: https://katiek2.github.io/path-doc/
+
+### npm
+
+If you use Node.js, you can also install the Sass migrator using [npm][] by
+running
+
+[npm]: https://www.npmjs.com
+
+```
+npm install -g sass-migrator
+```
+
+### Chocolatey
+
+If you use [the Chocolatey package manager][] for Windows, you can install the
+Sass migrator by running
+
+[the Chocolatey package manager]: https://chocolatey.org
+
+```
+choco install sass-migrator
+```
+
+### Homebrew
+
+If you use [the Homebrew package manager][] for Mac OS X, you can install Dart
+Sass by running
+
+[the Homebrew package manager]: https://brew.sh
+
+```
+brew install sass/sass/migrator
+```
+
+## Global Options
+
+These options are available for all migrators.
+
+### `--migrate-deps`
+
+This option (abbreviated `-d`) tells the migrator to change not just the
+stylesheets that are explicitly passed on the command line, but also any
+stylesheets that they depend on using the [`@use` rule][], [`@forward` rule][],
+or [`@import` rule][].
+
+```shellsession
+$ sass-migrator module --verbose style.scss
+Migrating style.scss
+$ sass-migrator module --verbose --migrate-deps style.scss
+Migrating style.scss
+Migrating _theme.scss
+Migrating _fonts.scss
+Migrating _grid.scss
+```
+
+<% heads_up do %>
+ The [module migrator][] assumes that any stylesheet that is depended on using
+ a [`@use` rule][] or a [`@forward` rule][] has already been migrated to the
+ module system, so it won't attempt to migrate them, even when the
+ `--migrate-deps` option is passed.
+
+ [module migrator]: #module
+<% end %>
+
+### `--load-path`
+
+This option (abbreviated `-I`) tells the migrator a [load path][] where it
+should look for stylesheets. It can be passed multiple times to provide multiple
+load paths. Earlier load paths will take precedence over later ones.
+
+Dependencies loaded from load paths are assumed to be third-party libraries, so
+the migrator will not migrate them even when the [`--migrate-deps` option][] is
+passed.
+
+[load path]: ../at-rules/use#load-paths
+
+### `--dry-run`
+
+This flag (abbreviated `-n`) tells the migrator not to save any changes to
+disk. It instead prints the list of files that it would have changed. This is
+commonly paired with the [`--verbose` option][] to print the contents of the
+changes that would have been made as well.
+
+[`--verbose` option]: #verbose
+
+```shellsession
+$ sass-migrator module --dry-run --migrate-deps style.scss
+Dry run. Logging migrated files instead of overwriting...
+
+style.scss
+_theme.scss
+_fonts.scss
+_grid.scss
+```
+
+#### `--no-unicode`
+
+This flag tells the Sass migrator only to emit ASCII characters to the terminal
+as part of error messages. By default, or if `--unicode` is passed, the migrator
+will emit non-ASCII characters for these messages. This flag does not affect the
+CSS output.
+
+```shellsession
+$ sass-migrator --no-unicode module style.scss
+line 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'.
+ ,
+1 | @import "typography";
+ | ^^^^^^^^^^^^
+ '
+Migration failed!
+$ sass-migrator --unicode module style.scss
+line 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'.
+ ╷
+1 │ @import "typography";
+ │ ^^^^^^^^^^^^
+ ╵
+Migration failed!
+```
+
+### `--verbose`
+
+This flag (abbreviated `-v`) tells the migrator to print extra information to
+the console. By default, it just prints the name of files that are changed, but
+when combined with the [`--dry-run` option][] it also prints those files' new
+contents.
+
+[`--dry-run` option]: #dry-run
+
+<%# Indent this because otherwise the table-of-contents generator interprets
+the `===` as a heading. %>
+
+ $ sass-migrator module --verbose --dry-run style.scss
+ Dry run. Logging migrated files instead of overwriting...
+ <==> style.scss
+ @use "bootstrap" with (
+ $body-bg: #000,
+ $body-color: #111
+ );
+
+ @include bootstrap.media-breakpoint-up(sm) {
+ .navbar {
+ display: block;
+ }
+ }
+ $ sass-migrator module --verbose style.scss
+ Migrating style.scss
+
+## Migrations
+
+The migrator currently supports only one migration, but expect more to come as
+the Sass language continues to evolve!
+
+### Module
+
+This migration converts stylesheets that use the old [`@import` rule][] to load
+dependencies so that they use the Sass module system via the [`@use` rule][]
+instead. It doesn't just naïvely change `@import`s to `@use`s—it updates
+stylesheets intelligently so that they keep working the same way they did
+before, including:
+
+* Adding namespaces to uses of members (variables, mixins, and functions) from
+ other modules.
+
+* Adding new `@use` rules to stylesheets that were using members without
+ importing them.
+
+* Converting overridden default variables to [`with` clauses][].
+
+ [`with` clauses]: ../at-rules/use#configuring-modules
+
+* Automatically removing `-` and `_` prefixes from members that are used from
+ other files (because otherwise they'd be considered [private][] and could only
+ be used in the module they're declared).
+
+ [private]: ../at-rules/use#private-members
+
+* Converting [nested imports][] to use the [`meta.load-css()` mixin][] instead.
+
+ [nested imports]: ../at-rules/import#nesting
+ [`meta.load-css()` mixin]: ../modules/meta#load-css
+
+<% heads_up do %>
+ Because the module migrator may need to modify both member definitions *and*
+ member names, it's important to either run it with the [`--migrate-deps`
+ option][] or ensure that you pass it all the stylesheets in your package or
+ application.
+
+ [`--migrate-deps` option]: #migrate-deps
+<% end %>
+
+<%= partial 'code-snippets/example-module-migrator' %>
+
+#### Loading Dependencies
+
+The module migrator needs to be able to read all of the stylesheets depended on
+by the ones it's migrating, even if the [`--migrate-deps` option][] is not
+passed. If the migrator fails to find a dependency, you'll get an error.
+
+```shellsession
+$ ls .
+style.scss node_modules
+$ sass-migrator module style.scss
+Error: Could not find Sass file at 'dependency'.
+ ,
+1 | @import "dependency";
+ | ^^^^^^^^^^^^
+ '
+ style.scss 1:9 root stylesheet
+Migration failed!
+$ sass-migrator --load-path node_modules module style.scss
+```
+
+If you use a [load path][] when compiling your stylesheets, make sure to pass
+that to the migrator using the [`--load-path` option][].
+
+Unfortunately, the migrator does not support custom importers, but it does have
+built-in support for resolving URLs starting with `~` by searching in
+`node_modules`, similar to [what Webpack supports][].
+
+[load path]: ../at-rules/use#load-paths
+[`--load-path` option]: #load-path
+[what Webpack supports]: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules
+
+#### `--remove-prefix`
+
+This option (abbreviated `-p`) takes an identifier prefix to remove from the
+beginning of all variable, mixin, and function names when they're migrated.
+Members that don't start with this prefix will remain unchanged.
+
+The [`@import` rule][] put all top-level members in one global scope, so when it
+was the standard way of loading stylesheets, everyone was incentivized to add
+prefixes to all their member names to avoid accidentally redefining some other
+stylesheet's. The module system solves this problem, so it's useful to
+automatically strip those old prefixes now that they're unnecessary.
+
+```shellsession
+$ cat style.scss
+@import "theme";
+
+@mixin app-inverted {
+ color: $app-bg-color;
+ background-color: $app-color;
+}
+$ sass-migrator --migrate-deps module --remove-prefix=app- style.scss
+$ cat style.scss
+@import "theme";
+
+@mixin inverted {
+ color: theme.$bg-color;
+ background-color: theme.$color;
+}
+```
+
+When you pass this option, the migrator will also generate an [import-only
+stylesheet][] that [forwards][] all the members with the prefix added back, to
+preserve backwards-compatibility for users who were importing the library.
+
+[import-only stylesheet]: ../at-rules/import#import-only-files
+[forwards]: ../at-rules/forward
+
+#### `--forward`
+
+This option tells the migrator which members to forward using the [`@forward`
+rule][]. It supports the following settings:
+
+* `none` (the default) doesn't forward any members.
+
+* `all` forwards all members except those that started with `-` or `_` in the
+ original stylesheet, since that was commonly used to mark a package-private
+ member before the module system was introduced.
+
+* `prefixed` forwards only members that begin with the prefix passed to the
+ [`--remove-prefix` option][]. This option may only be used in conjunction with
+ the `--remove-prefix` option.
+
+ [`--remove-prefix` option]: #remove-prefix
+
+All files that are passed explicitly on the command line will forward members
+that are transitively loaded by those files using the `@import` rule. Files
+loaded using the [`--migrate-deps` option][] will not forward any new members.
+This option is particularly useful when migrating a Sass library, because it
+ensures that users of that library will still be able to access all the members
+it defines.
+
+```shellsession
+$ cat _index.scss
+@import "theme";
+@import "typography";
+@import "components";
+$ sass-migrator --migrate-deps module --forward=all style.scss
+$ cat _index.scss
+@forward "theme";
+@forward "typography";
+@forward "components";
+```
diff --git a/source/documentation/cli/ruby-sass.html.md.erb b/source/documentation/cli/ruby-sass.html.md.erb
index ce27d0c30..0de20b3f2 100644
--- a/source/documentation/cli/ruby-sass.html.md.erb
+++ b/source/documentation/cli/ruby-sass.html.md.erb
@@ -80,7 +80,7 @@ When compiling whole directories, Sass will ignore [partial files][] whose names
begin with `_`. You can use partials to separate out your stylesheets without
creating a bunch of unnecessary output files.
-[partial files]: ../at-rules/import#partials
+[partial files]: ../at-rules/use#partials
Many-to-many mode will only compile stylesheets whose dependencies have been
modified more recently than the corresponding CSS file was generated. It will
@@ -93,10 +93,10 @@ also print status messages when updating stylesheets.
#### `--load-path`
This option (abbreviated `-I`) adds an additional [load path][] for Sass to look
-for imports. It can be passed multiple times to provide multiple load paths.
+for stylesheets. It can be passed multiple times to provide multiple load paths.
Earlier load paths will take precedence over later ones.
-[load path]: ../at-rules/import#load-paths
+[load path]: ../at-rules/use#load-paths
```shellsession
$ sass --load-path=node_modules/bootstrap/dist/css style.scss style.css
diff --git a/source/documentation/functions.html.md.erb b/source/documentation/functions.html.md.erb
deleted file mode 100644
index 830c5b9b6..000000000
--- a/source/documentation/functions.html.md.erb
+++ /dev/null
@@ -1,68 +0,0 @@
----
-title: Built-In Functions
-introduction: >
- In addition to allowing users to [define their own
- functions](at-rules/function), there are many useful functions built right
- into Sass. These functions are called using the normal CSS function syntax,
- with the addition of [special Sass argument
- syntax](at-rules/function#arguments).
-overview: true
----
-
-Sass's built-in functions are divided into a few categories:
-
-* Any function that Sass doesn't recognize as built-in or user-defined is
- treated as a [plain CSS function][].
-
-* [Number functions][] operate on [numbers][], usually to perform some sort of
- math.
-
-* [String functions][] make it easy to combine, search, or split apart
- [strings][].
-
-* [Color functions][] generate new [colors][] based on existing ones, making it
- easy to build color themes.
-
-* [List functions][] access and modify values in [lists][].
-
-* [Map functions][] make it possible to look up the value associated with a key
- in a [map][], and much more.
-
-* [Selector functions][] provide access to Sass's powerful selector engine.
-
-* [Introspection functions][] expose the details of Sass's inner workings.
-
-[plain CSS function]: functions/css
-[Number functions]: functions/math
-[numbers]: values/numbers
-[String functions]: functions/string
-[strings]: values/strings
-[Color functions]: functions/color
-[colors]: values/colors
-[List functions]: functions/list
-[lists]: values/lists
-[Map functions]: functions/map
-[map]: values/maps
-[Selector functions]: functions/selector
-[Introspection functions]: functions/meta
-
-
-<% function "if($condition, $if-true, $if-false)" do %>
- Returns `$if-true` if `$condition` is [truthy][], and `$if-false` otherwise.
-
- This function is special in that it doesn't even evaluate the argument that
- isn't returned, so it's safe to call even if the unused argument would throw an
- error.
-
- [truthy]: at-rules/control/if#truthiness-and-falsiness
-
- <% example(autogen_css: false) do %>
- @debug if(true, 10px, 15px); // 10px
- @debug if(false, 10px, 15px); // 15px
- @debug if(variable-defined($var), $var, null); // null
- ===
- @debug if(true, 10px, 15px) // 10px
- @debug if(false, 10px, 15px) // 15px
- @debug if(variable-defined($var), $var, null) // null
- <% end %>
-<% end %>
diff --git a/source/documentation/functions/color.html.md.erb b/source/documentation/functions/color.html.md.erb
deleted file mode 100644
index 39de59929..000000000
--- a/source/documentation/functions/color.html.md.erb
+++ /dev/null
@@ -1,876 +0,0 @@
----
-title: Color Functions
----
-
-<% function <
- Increases or decreases one or more properties of `$color` by fixed amounts.
-
- Adds the value passed for each keyword argument to the corresponding property
- of the color, and returns the adjusted color. It's an error to specify an RGB
- property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL
- property (`$hue`, `$saturation`, and/or `$lightness`).
-
- All optional arguments must be numbers. The `$red`, `$green`, and `$blue`
- arguments must be [unitless][] and between -255 and 255 (inclusive). The
- `$hue` argument must have either the unit `deg` or no unit. The `$saturation`
- and `$lightness` arguments must be between `-100%` and `100%` (inclusive), and
- may be unitless. The `$alpha` argument must be unitless and between -1 and 1
- (inclusive).
-
- [unitless]: ../values/numbers#units
-
- See also:
-
- * [`scale-color()`](#scale-color) for fluidly scaling a color's properties.
- * [`change-color()`](#change-color) for setting a color's properties.
-
- <% example(autogen_css: false) do %>
- @debug adjust-color(#6b717f, $red: 15); // #7a717f
- @debug adjust-color(#d2e1dd, $red: -10, $blue: 10); // #c8e1e7
- @debug adjust-color(#998099, $lightness: -30%, $alpha: -0.4); // rgba(71, 57, 71, 0.6)
- ===
- @debug adjust-color(#6b717f, $red: 15) // #7a717f
- @debug adjust-color(#d2e1dd, $red: -10, $blue: 10) // #c8e1e7
- @debug adjust-color(#998099, $lightness: -30%, $alpha: -0.4) // rgba(71, 57, 71, 0.6)
- <% end %>
-<% end %>
-
-
-<% function 'adjust-hue($color, $degrees)', returns: 'color' do %>
- Increases or decreases `$color`'s hue.
-
- The `$hue` must be a number between `-360deg` and `360deg` (inclusive) to add
- to `$color`'s hue. It may be [unitless][].
-
- [unitless]: ../values/numbers#units
-
- See also [`adjust-color()`](#adjust-color), which can adjust any property of a
- color.
-
- <% example(autogen_css: false) do %>
- // Hue 222deg becomes 282deg.
- @debug adjust-hue(#6b717f, 60deg); // #796b7f
-
- // Hue 164deg becomes 104deg.
- @debug adjust-hue(#d2e1dd, -60deg); // #d6e1d2
-
- // Hue 210deg becomes 255deg.
- @debug adjust-hue(#036, 45); // #1a0066
- ===
- // Hue 222deg becomes 282deg.
- @debug adjust-hue(#6b717f, 60deg) // #796b7f
-
- // Hue 164deg becomes 104deg.
- @debug adjust-hue(#d2e1dd, -60deg) // #d6e1d2
-
- // Hue 210deg becomes 255deg.
- @debug adjust-hue(#036, 45) // #1a0066
- <% end %>
-<% end %>
-
-
-<% function 'alpha($color)', 'opacity($color)', returns: 'number' do %>
- Returns the alpha channel of `$color` as a number between 0 and 1.
-
- As a special case, this supports the Internet Explorer syntax
- `alpha(opacity=20)`, for which it returns an [unquoted string][].
-
- [unquoted string]: ../values/strings#unquoted
-
- See also:
-
- * [`red()`](#red) for getting a color's red channel.
- * [`green()`](#green) for getting a color's green channel.
- * [`blue()`](#blue) for getting a color's blue channel.
- * [`hue()`](#hue) for getting a color's hue.
- * [`saturation()`](#saturation) for getting a color's saturation.
- * [`lightness()`](#lightness) for getting a color's lightness.
-
- <% example(autogen_css: false) do %>
- @debug alpha(#e1d7d2); // 1
- @debug opacity(rgb(210, 225, 221, 0.4)); // 0.4
- @debug alpha(opacity=20); // alpha(opacity=20)
- ===
- @debug alpha(#e1d7d2) // 1
- @debug opacity(rgb(210, 225, 221, 0.4)) // 0.4
- @debug alpha(opacity=20) // alpha(opacity=20)
- <% end %>
-<% end %>
-
-
-<% function 'blue($color)', returns: 'number' do %>
- Returns the blue channel of `$color` as a number between 0 and 255.
-
- See also:
-
- * [`red()`](#red) for getting a color's red channel.
- * [`green()`](#green) for getting a color's green channel.
- * [`hue()`](#hue) for getting a color's hue.
- * [`saturation()`](#saturation) for getting a color's saturation.
- * [`lightness()`](#lightness) for getting a color's lightness.
- * [`alpha()`](#alpha) for getting a color's alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug blue(#e1d7d2); // 210
- @debug blue(white); // 255
- @debug blue(black); // 0
- ===
- @debug blue(#e1d7d2) // 210
- @debug blue(white) // 255
- @debug blue(black) // 0
- <% end %>
-<% end %>
-
-
-<% function <
- Sets one or more properties of a color to new values.
-
- Uses the value passed for each keyword argument in place of the corresponding
- property of the color, and returns the changed color. It's an error to specify
- an RGB property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL
- property (`$hue`, `$saturation`, and/or `$lightness`).
-
- All optional arguments must be numbers. The `$red`, `$green`, and `$blue`
- arguments must be [unitless][] and between 0 and 255 (inclusive). The `$hue`
- argument must have either the unit `deg` or no unit. The `$saturation` and
- `$lightness` arguments must be between `0%` and `100%` (inclusive), and may be
- unitless. The `$alpha` argument must be unitless and between -1 and 1
- (inclusive).
-
- [unitless]: ../values/numbers#units
-
- See also:
-
- * [`scale-color()`](#scale-color) for fluidly scaling a color's properties.
- * [`adjust-color()`](#adjust-color) for adjusting a color's properties by fixed
- amounts.
-
- <% example(autogen_css: false) do %>
- @debug change-color(#6b717f, $red: 100); // #64717f
- @debug change-color(#d2e1dd, $red: 100, $blue: 50); // #64e132
- @debug change-color(#998099, $lightness: 30%, $alpha: 0.5); // rgba(85, 68, 85, 0.5)
- ===
- @debug change-color(#6b717f, $red: 100) // #64717f
- @debug change-color(#d2e1dd, $red: 100, $blue: 50) // #64e132
- @debug change-color(#998099, $lightness: 30%, $alpha: 0.5) // rgba(85, 68, 85, 0.5)
- <% end %>
-<% end %>
-
-
-<% function 'complement($color)', returns: 'color' do %>
- Returns the RGB [complement][] of `$color`.
-
- This is identical to [`adjust-hue($color, 180deg)`](#adjust-hue).
-
- [complement]: https://en.wikipedia.org/wiki/Complementary_colors
-
- <% example(autogen_css: false) do %>
- // Hue 222deg becomes 42deg.
- @debug complement(#6b717f); // #7f796b
-
- // Hue 164deg becomes 344deg.
- @debug complement(#d2e1dd); // #e1d2d6
-
- // Hue 210deg becomes 30deg.
- @debug complement(#036); // #663300
- ===
- // Hue 222deg becomes 42deg.
- @debug complement(#6b717f) // #7f796b
-
- // Hue 164deg becomes 344deg.
- @debug complement(#d2e1dd) // #e1d2d6
-
- // Hue 210deg becomes 30deg.
- @debug complement(#036) // #663300
- <% end %>
-<% end %>
-
-
-<% function 'darken($color, $amount)', returns: 'color' do %>
- Makes `$color` darker.
-
- The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases
- the HSL lightness of `$color` by that amount.
-
- <% heads_up do %>
- The `darken()` function decreases lightness by a fixed amount, which is often
- not the desired effect. To make a color a certain percentage darker than it was
- before, use [`scale-color()`](#scale-color) instead.
-
- <% example(autogen_css: false) do %>
- // #036 has lightness 20%, so when darken() subtracts 30% it just returns black.
- @debug darken(#036, 30%); // black
-
- // scale-color() instead makes it 30% darker than it was originally.
- @debug scale-color(#036, $lightness: -30%); // #002447
- ===
- // #036 has lightness 20%, so when darken() subtracts 30% it just returns black.
- @debug darken(#036, 30%) // black
-
- // scale-color() instead makes it 30% darker than it was originally.
- @debug scale-color(#036, $lightness: -30%) // #002447
- <% end %>
- <% end %>
-
- <% example(autogen_css: false) do %>
- // Lightness 92% becomes 72%.
- @debug darken(#b37399, 20%); // #7c4465
-
- // Lightness 85% becomes 45%.
- @debug darken(#f2ece4, 40%); // #b08b5a
-
- // Lightness 20% becomes 0%.
- @debug darken(#036, 30%); // black
- ===
- // Lightness 92% becomes 72%.
- @debug darken(#b37399, 20%) // #7c4465
-
- // Lightness 85% becomes 45%.
- @debug darken(#f2ece4, 40%) // #b08b5a
-
- // Lightness 20% becomes 0%.
- @debug darken(#036, 30%) // black
- <% end %>
-<% end %>
-
-
-<% function 'desaturate($color, $amount)', returns: 'color' do %>
- Makes `$color` less saturated.
-
- The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases
- the HSL saturation of `$color` by that amount.
-
- <% heads_up do %>
- The `desaturate()` function decreases saturation by a fixed amount, which is
- often not the desired effect. To make a color a certain percentage less
- saturated than it was before, use [`scale-color()`](#scale-color) instead.
-
- <% example(autogen_css: false) do %>
- // #d2e1dd has saturation 20%, so when desaturate() subtracts 30% it just
- // returns gray.
- @debug desaturate(#d2e1dd, 30%); // #dadada
-
- // scale-color() instead makes it 30% less saturated than it was originally.
- @debug scale-color(#6b717f, $saturation: -30%); // #6e727c
- ===
- // #6b717f has saturation 20%, so when desaturate() subtracts 30% it just
- // returns gray.
- @debug desaturate(#d2e1dd, 30%) // #dadada
-
- // scale-color() instead makes it 30% less saturated than it was originally.
- @debug scale-color(#6b717f, $saturation: -30%) // #6e727c
- <% end %>
- <% end %>
-
- <% example(autogen_css: false) do %>
- // Saturation 100% becomes 80%.
- @debug desaturate(#036, 20%); // #0a335c
-
- // Saturation 35% becomes 15%.
- @debug desaturate(#f2ece4, 20%); // #eeebe8
-
- // Saturation 20% becomes 0%.
- @debug desaturate(#d2e1dd, 30%); // #dadada
- ===
- // Saturation 100% becomes 80%.
- @debug desaturate(#036, 20%) // #0a335c
-
- // Saturation 35% becomes 15%.
- @debug desaturate(#f2ece4, 20%) // #eeebe8
-
- // Saturation 20% becomes 0%.
- @debug desaturate(#d2e1dd, 30%) // #dadada
- <% end %>
-<% end %>
-
-
-<% function 'grayscale($color)', returns: 'color' do %>
- Returns a gray color with the same lightness as `$color`.
-
- This is identical to [`change-color($color, $saturation: 0%)`](#change-color).
-
- <% example(autogen_css: false) do %>
- @debug grayscale(#6b717f); // #757575
- @debug grayscale(#d2e1dd); // #dadada
- @debug grayscale(#036); // #333333
- ===
- @debug grayscale(#6b717f) // #757575
- @debug grayscale(#d2e1dd) // #dadada
- @debug grayscale(#036) // #333333
- <% end %>
-<% end %>
-
-
-<% function 'green($color)', returns: 'number' do %>
- Returns the green channel of `$color` as a number between 0 and 255.
-
- See also:
-
- * [`red()`](#red) for getting a color's red channel.
- * [`blue()`](#blue) for getting a color's blue channel.
- * [`hue()`](#hue) for getting a color's hue.
- * [`saturation()`](#saturation) for getting a color's saturation.
- * [`lightness()`](#lightness) for getting a color's lightness.
- * [`alpha()`](#alpha) for getting a color's alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug green(#e1d7d2); // 215
- @debug green(white); // 255
- @debug green(black); // 0
- ===
- @debug green(#e1d7d2) // 215
- @debug green(white) // 255
- @debug green(black) // 0
- <% end %>
-<% end %>
-
-
-<% function 'hsl($hue $saturation $lightness)',
- 'hsl($hue $saturation $lightness / $alpha)',
- 'hsl($hue, $saturation, $lightness, $alpha: 1)',
- 'hsla($hue $saturation $lightness)',
- 'hsla($hue $saturation $lightness / $alpha)',
- 'hsla($hue, $saturation, $lightness, $alpha: 1)',
- returns: 'color' do %>
- <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %>
- LibSass and Ruby Sass only support the following signatures:
-
- * `hsl($hue, $saturation, $lightness)`
- * `hsla($hue, $saturation, $lightness, $alpha)`
-
- Note that for these implementations, the `$alpha` argument is *required* if
- the function name `hsla()` is used, and *forbidden* if the function name
- `hsl()` is used.
- <% end %>
-
- <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %>
- LibSass and older versions of Ruby Sass don't support alpha values specified as
- percentages.
- <% end %>
-
- Returns a color with the given [hue, saturation, and lightness][] and the given
- alpha channel.
-
- [hue, saturation, and lightness]: https://en.wikipedia.org/wiki/HSL_and_HSV
-
- The hue is a number between `0deg` and `360deg` (inclusive). The saturation
- and lightness are numbers between `0%` and `100%` (inclusive). All these
- numbers may be [unitless][]. The alpha channel can be specified as either a
- unitless number between 0 and 1 (inclusive), or a percentage between `0%` and
- `100%` (inclusive).
-
- [unitless]: ../values/numbers#units
-
- <% fun_fact do %>
- You can pass [special functions][] like `calc()` or `var()` in place of any
- argument to `hsl()`. You can even use `var()` in place of multiple
- arguments, since it might be replaced by multiple values! When a color
- function is called this way, it returns an unquoted string using the same
- signature it was called with.
-
- [special functions]: ../syntax/special-functions
-
- <% example(autogen_css: false) do %>
- @debug hsl(210deg 100% 20% / var(--opacity)); // hsl(210deg 100% 20% / var(--opacity))
- @debug hsla(var(--peach), 20%); // hsla(var(--peach), 20%)
- ===
- @debug hsl(210deg 100% 20% / var(--opacity)) // hsl(210deg 100% 20% / var(--opacity))
- @debug hsla(var(--peach), 20%) // hsla(var(--peach), 20%)
- <% end %>
- <% end %>
-
- <% heads_up do %>
- Sass's [special parsing rules][] for slash-separated values make it
- difficult to pass variables for `$lightness` or `$alpha` when using the
- `hsl($hue $saturation $lightness / $alpha)` signature. Consider using
- `hsl($hue, $saturation, $lightness, $alpha)` instead.
-
- [special parsing rules]: ../operators/numeric#slash-separated-values
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug hsl(210deg 100% 20%); // #036
- @debug hsl(34, 35%, 92%); // #f2ece4
- @debug hsl(210deg 100% 20% / 50%); // rgba(0, 51, 102, 0.5)
- @debug hsla(34, 35%, 92%, 0.2); // rgba(242, 236, 228, 0.2)
- ===
- @debug hsl(210deg 100% 20%) // #036
- @debug hsl(34, 35%, 92%) // #f2ece4
- @debug hsl(210deg 100% 20% / 50%) // rgba(0, 51, 102, 0.5)
- @debug hsla(34, 35%, 92%, 0.2) // rgba(242, 236, 228, 0.2)
- <% end %>
-<% end %>
-
-
-<% function 'hue($color)', returns: 'number' do %>
- Returns the hue of `$color` as a number between `0deg` and `255deg`.
-
- See also:
-
- * [`red()`](#red) for getting a color's red channel.
- * [`green()`](#green) for getting a color's green channel.
- * [`blue()`](#blue) for getting a color's blue channel.
- * [`saturation()`](#saturation) for getting a color's saturation.
- * [`lightness()`](#lightness) for getting a color's lightness.
- * [`alpha()`](#alpha) for getting a color's alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug hue(#e1d7d2); // 20deg
- @debug hue(#f2ece4); // 34.2857142857deg
- @debug hue(#dadbdf); // 228deg
- ===
- @debug hue(#e1d7d2) // 20deg
- @debug hue(#f2ece4) // 34.2857142857deg
- @debug hue(#dadbdf) // 228deg
- <% end %>
-<% end %>
-
-
-<% function 'ie-hex-str($color)', returns: 'unquoted string' do %>
- Returns an unquoted string that represents `$color` in the `#AARRGGBB` format
- expected by Internet Explorer's [`-ms-filter`][] property.
-
- [`-ms-filter`]: https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter
-
- <% example(autogen_css: false) do %>
- @debug ie-hex-str(#b37399); // #FFB37399
- @debug ie-hex-str(#808c99); // #FF808C99
- @debug ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4
- ===
- @debug ie-hex-str(#b37399); // #FFB37399
- @debug ie-hex-str(#808c99); // #FF808C99
- @debug ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4
- <% end %>
-<% end %>
-
-
-<% function 'invert($color, $weight: 100%)', returns: 'color' do %>
- Returns the inverse or [negative][] of `$color`.
-
- [negative]: https://en.wikipedia.org/wiki/Negative_(photography)
-
- The `$weight` must be a number between `0%` and `100%` (inclusive). A higher
- weight means the result will be closer to the negative, and a lower weight means
- it will be closer to `$color`. Weight `50%` will always produce `#808080`.
-
- <% example(autogen_css: false) do %>
- @debug invert(#b37399); // #4c8c66
- @debug invert(black); // white
- @debug invert(#550e0c, 20%); // #663b3a
- ===
- @debug invert(#b37399) // #4c8c66
- @debug invert(black) // white
- @debug invert(#550e0c, 20%) // #663b3a
- <% end %>
-<% end %>
-
-
-<% function 'lighten($color, $amount)', returns: 'color' do %>
- Makes `$color` lighter.
-
- The `$amount` must be a number between `0%` and `100%` (inclusive). Increases
- the HSL lightness of `$color` by that amount.
-
- <% heads_up do %>
- The `lighten()` function increases lightness by a fixed amount, which is often
- not the desired effect. To make a color a certain percentage lighter than it was
- before, use [`scale-color()`](#scale-color) instead.
-
- <% example(autogen_css: false) do %>
- // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white.
- @debug lighten(#e1d7d2, 30%); // white
-
- // scale-color() instead makes it 30% lighter than it was originally.
- @debug scale-color(#e1d7d2, $lightness: 30%); // #eae3e0
- ===
- // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white.
- @debug lighten(#e1d7d2, 30%) // white
-
- // scale-color() instead makes it 30% lighter than it was originally.
- @debug scale-color(#e1d7d2, $lightness: 30%) // #eae3e0
- <% end %>
- <% end %>
-
- <% example(autogen_css: false) do %>
- // Lightness 46% becomes 66%.
- @debug lighten(#6b717f, 20%); // #a1a5af
-
- // Lightness 20% becomes 80%.
- @debug lighten(#036, 60%); // #99ccff
-
- // Lightness 85% becomes 100%.
- @debug lighten(#e1d7d2, 30%); // white
- ===
- // Lightness 46% becomes 66%.
- @debug lighten(#6b717f, 20%) // #a1a5af
-
- // Lightness 20% becomes 80%.
- @debug lighten(#036, 60%) // #99ccff
-
- // Lightness 85% becomes 100%.
- @debug lighten(#e1d7d2, 30%) // white
- <% end %>
-<% end %>
-
-
-<% function 'lightness($color)', returns: 'number' do %>
- Returns the HSL lightness of `$color` as a number between `0%` and `100%`.
-
- See also:
-
- * [`red()`](#red) for getting a color's red channel.
- * [`green()`](#green) for getting a color's green channel.
- * [`blue()`](#blue) for getting a color's blue channel.
- * [`hue()`](#hue) for getting a color's hue.
- * [`saturation()`](#saturation) for getting a color's saturation.
- * [`alpha()`](#alpha) for getting a color's alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug lightness(#e1d7d2); // 85.2941176471%
- @debug lightness(#f2ece4); // 92.1568627451%
- @debug lightness(#dadbdf); // 86.4705882353%
- ===
- @debug lightness(#e1d7d2) // 85.2941176471%
- @debug lightness(#f2ece4) // 92.1568627451%
- @debug lightness(#dadbdf) // 86.4705882353%
- <% end %>
-<% end %>
-
-
-<% function 'mix($color1, $color2, $weight: 50%)', returns: 'color' do %>
- Returns a number that's a mixture of `$color1` and `$color2`.
-
- Both the `$weight` and the relative opacity of each color determines how much of
- each color is in the result. The `$weight` must be a number between `0%` and
- `100%` (inclusive). A larger weight indicates that more of `$color1` should be
- used, and a smaller weight indicates that more of `$color2` should be used.
-
- <% example(autogen_css: false) do %>
- @debug mix(#036, #d2e1dd); // #698aa2
- @debug mix(#036, #d2e1dd, 75%); // #355f84
- @debug mix(#036, #d2e1dd, 25%); // #9eb6bf
- @debug mix(rgba(242, 236, 228, 0.5), #6b717f); // rgba(141, 144, 152, 0.75)
- ===
- @debug mix(#036, #d2e1dd) // #698aa2
- @debug mix(#036, #d2e1dd, 75%) // #355f84
- @debug mix(#036, #d2e1dd, 25%) // #9eb6bf
- @debug mix(rgba(242, 236, 228, 0.5), #6b717f) // rgba(141, 144, 152, 0.75)
- <% end %>
-<% end %>
-
-
-<% function 'opacify($color, $amount)', 'fade-in($color, $amount)', returns: 'color' do %>
- Makes `$color` more opaque.
-
- The `$amount` must be a number between `0` and `1` (inclusive). Increases the
- alpha channel of `$color` by that amount.
-
- <% heads_up do %>
- The `opacify()` function increases the alpha channel by a fixed amount, which is often
- not the desired effect. To make a color a certain percentage more opaque than it was
- before, use [`scale-color()`](#scale-color) instead.
-
- <% example(autogen_css: false) do %>
- // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully
- // opaque color.
- @debug opacify(rgba(#036, 0.7), 0.3); // #036
-
- // scale-color() instead makes it 30% more opaque than it was originally.
- @debug scale-color(rgba(#036, 0.7), $alpha: 30%); // rgba(0, 51, 102, 0.79)
- ===
- // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully
- // opaque color.
- @debug opacify(rgba(#036, 0.7), 0.3) // #036
-
- // scale-color() instead makes it 30% more opaque than it was originally.
- @debug scale-color(rgba(#036, 0.7), $alpha: 30%) // rgba(0, 51, 102, 0.79)
- <% end %>
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug opacify(rgba(#6b717f, 0.5), 0.2); // rgba(107, 113, 127, 0.7)
- @debug fade-in(rgba(#e1d7d2, 0.5), 0.4); // rgba(225, 215, 210, 0.9)
- @debug opacify(rgba(#036, 0.7), 0.3); // #036
- ===
- @debug opacify(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.7)
- @debug fade-in(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.9)
- @debug opacify(rgba(#036, 0.7), 0.3) // #036
- <% end %>
-<% end %>
-
-
-<% function 'red($color)', returns: 'number' do %>
- Returns the red channel of `$color` as a number between 0 and 255.
-
- See also:
-
- * [`green()`](#green) for getting a color's green channel.
- * [`blue()`](#blue) for getting a color's blue channel.
- * [`hue()`](#hue) for getting a color's hue.
- * [`saturation()`](#saturation) for getting a color's saturation.
- * [`lightness()`](#lightness) for getting a color's lightness.
- * [`alpha()`](#alpha) for getting a color's alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug red(#e1d7d2); // 225
- @debug red(white); // 255
- @debug red(black); // 0
- ===
- @debug red(#e1d7d2) // 225
- @debug red(white) // 255
- @debug red(black) // 0
- <% end %>
-<% end %>
-
-
-<% function 'rgb($red $green $blue)',
- 'rgb($red $green $blue / $alpha)',
- 'rgb($red, $green, $blue, $alpha: 1)',
- 'rgb($color, $alpha)',
- 'rgba($red $green $blue)',
- 'rgba($red $green $blue / $alpha)',
- 'rgba($red, $green, $blue, $alpha: 1)',
- 'rgba($color, $alpha)',
- returns: 'color' do %>
- <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %>
- LibSass and Ruby Sass only support the following signatures:
-
- * `rgb($red, $green, $blue)`
- * `rgba($red, $green, $blue, $alpha)`
- * `rgba($color, $alpha)`
-
- Note that for these implementations, the `$alpha` argument is *required* if
- the function name `rgba()` is used, and *forbidden* if the function name
- `rgb()` is used.
- <% end %>
-
- <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %>
- LibSass and older versions of Ruby Sass don't support alpha values specified
- as percentages.
- <% end %>
-
- If `$red`, `$green`, `$blue`, and optionally `$alpha` are passed, returns a
- color with the given red, green, blue, and alpha channels.
-
- Each channel can be specified as either a [unitless][] number between 0 and
- 255 (inclusive), or a percentage between `0%` and `100%` (inclusive). The
- alpha channel can be specified as either a unitless number between 0 and 1
- (inclusive), or a percentage between `0%` and `100%` (inclusive).
-
- [unitless]: ../values/numbers#units
-
- <% fun_fact do %>
- You can pass [special functions][] like `calc()` or `var()` in place of any
- argument to `rgb()`. You can even use `var()` in place of multiple
- arguments, since it might be replaced by multiple values! When a color
- function is called this way, it returns an unquoted string using the same
- signature it was called with.
-
- [special functions]: ../syntax/special-functions
-
- <% example(autogen_css: false) do %>
- @debug rgb(0 51 102 / var(--opacity)); // rgb(0 51 102 / var(--opacity))
- @debug rgba(var(--peach), 0.2); // rgba(var(--peach), 0.2)
- ===
- @debug rgb(0 51 102 / var(--opacity)) // rgb(0 51 102 / var(--opacity))
- @debug rgba(var(--peach), 0.2) // rgba(var(--peach), 0.2)
- <% end %>
- <% end %>
-
- <% heads_up do %>
- Sass's [special parsing rules][] for slash-separated values make it
- difficult to pass variables for `$blue` or `$alpha` when using the
- `rgb($red $green $blue / $alpha)` signature. Consider using
- `hsl($red, $green, $blue, $alpha)` instead.
-
- [special parsing rules]: ../operators/numeric#slash-separated-values
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug rgb(0 51 102); // #036
- @debug rgb(95%, 92.5%, 89.5%); // #f2ece4
- @debug rgb(0 51 102 / 50%); // rgba(0, 51, 102, 0.5)
- @debug rgba(95%, 92.5%, 89.5%, 0.2); // rgba(242, 236, 228, 0.2)
- ===
- @debug rgb(0 51 102) // #036
- @debug rgb(95%, 92.5%, 89.5%) // #f2ece4
- @debug rgb(0 51 102 / 50%) // rgba(0, 51, 102, 0.5)
- @debug rgba(95%, 92.5%, 89.5%, 0.2) // rgba(242, 236, 228, 0.2)
- <% end %>
-
- ---
-
- If `$color` and `$alpha` are passed, this returns `$color` with the given
- `$alpha` channel instead of its original alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug rgb(#f2ece4, 50%); // rgba(242, 236, 228, 0.5);
- @debug rgba(rgba(0, 51, 102, 0.5), 1); // #003366
- ===
- @debug rgb(#f2ece4, 50%) // rgba(242, 236, 228, 0.5)
- @debug rgba(rgba(0, 51, 102, 0.5), 1) // #003366
- <% end %>
-<% end %>
-
-
-<% function 'saturate($color, $amount)', returns: 'color' do %>
- Makes `$color` more saturated.
-
- The `$amount` must be a number between `0%` and `100%` (inclusive). Increases
- the HSL saturation of `$color` by that amount.
-
- <% heads_up do %>
- The `saturate()` function increases saturation by a fixed amount, which is often
- not the desired effect. To make a color a certain percentage more saturated than
- it was before, use [`scale-color()`](#scale-color) instead.
-
- <% example(autogen_css: false) do %>
- // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes
- // fully saturated.
- @debug saturate(#0e4982, 30%); // #004990
-
- // scale-color() instead makes it 30% more saturated than it was originally.
- @debug scale-color(#0e4982, $saturation: 30%); // #0a4986
- ===
- // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes
- // fully saturated.
- @debug saturate(#0e4982, 30%) // #004990
-
- // scale-color() instead makes it 30% more saturated than it was originally.
- @debug scale-color(#0e4982, $saturation: 30%) // #0a4986
- <% end %>
- <% end %>
-
- <% example(autogen_css: false) do %>
- // Saturation 50% becomes 70%.
- @debug saturate(#c69, 20%); // #e05299
-
- // Saturation 35% becomes 85%.
- @debug desaturate(#f2ece4, 50%); // #ebebeb
-
- // Saturation 80% becomes 100%.
- @debug saturate(#0e4982, 30%) // #004990
- ===
- // Saturation 50% becomes 70%.
- @debug saturate(#c69, 20%); // #e05299
-
- // Saturation 35% becomes 85%.
- @debug desaturate(#f2ece4, 50%); // #ebebeb
-
- // Saturation 80% becomes 100%.
- @debug saturate(#0e4982, 30%) // #004990
- <% end %>
-<% end %>
-
-
-<% function 'saturation($color)', returns: 'number' do %>
- Returns the HSL saturation of `$color` as a number between `0%` and `100%`.
-
- See also:
-
- * [`red()`](#red) for getting a color's red channel.
- * [`green()`](#green) for getting a color's green channel.
- * [`blue()`](#blue) for getting a color's blue channel.
- * [`hue()`](#hue) for getting a color's hue.
- * [`lightness()`](#lightness) for getting a color's lightness.
- * [`alpha()`](#alpha) for getting a color's alpha channel.
-
- <% example(autogen_css: false) do %>
- @debug saturation(#e1d7d2); // 20%
- @debug saturation(#f2ece4); // 30%
- @debug saturation(#dadbdf); // 7.2463768116%
- ===
- @debug saturation(#e1d7d2) // 20%
- @debug saturation(#f2ece4) // 30%
- @debug saturation(#dadbdf) // 7.2463768116%
- <% end %>
-<% end %>
-
-
-<% function <
- Fluidly scales one or more properties of `$color`.
-
- Each keyword argument must be a number between `-100%` and `100%` (inclusive).
- This indicates how far the corresponding property should be moved from its
- original position towards the maximum (if the argument is positive) or the
- minimum (if the argument is negative). This means that, for example,
- `$lightness: 50%` will make all colors `50%` closer to maximum lightness
- without making them fully white.
-
- It's an error to specify an RGB property (`$red`, `$green`, and/or `$blue`) at
- the same time as an HSL property (`$saturation`, and/or `$lightness`).
-
- See also:
-
- * [`adjust-color()`](#adjust-color) for changing a color's properties by fixed
- amounts.
- * [`change-color()`](#change-color) for setting a color's properties.
-
- <% example(autogen_css: false) do %>
- @debug scale-color(#6b717f, $red: 15%); // #81717f
- @debug scale-color(#d2e1dd, $lightness: -10%, $saturation: 10%); // #b3d4cb
- @debug scale-color(#998099, $alpha: -40%); // rgba(153, 128, 153, 0.6)
- ===
- @debug scale-color(#6b717f, $red: 15%) // #81717f
- @debug scale-color(#d2e1dd, $lightness: -10%, $saturation: 10%) // #b3d4cb
- @debug scale-color(#998099, $alpha: -40%) // rgba(153, 128, 153, 0.6)
- <% end %>
-<% end %>
-
-
-<% function 'transparentize($color, $amount)', 'fade-out($color, $amount)', returns: 'color' do %>
- Makes `$color` more transparent.
-
- The `$amount` must be a number between `0` and `1` (inclusive). Decreases the
- alpha channel of `$color` by that amount.
-
- <% heads_up do %>
- The `transparentize()` function decreases the alpha channel by a fixed amount,
- which is often not the desired effect. To make a color a certain percentage more
- transparent than it was before, use [`scale-color()`](#scale-color) instead.
-
- <% example(autogen_css: false) do %>
- // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it
- // returns a fully transparent color.
- @debug transparentize(rgba(#036, 0.3), 0.3); // rgba(0, 51, 102, 0)
-
- // scale-color() instead makes it 30% more transparent than it was originally.
- @debug scale-color(rgba(#036, 0.3), $alpha: -30%); // rgba(0, 51, 102, 0.21)
- ===
- // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it
- // returns a fully transparent color.
- @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0)
-
- // scale-color() instead makes it 30% more transparent than it was originally.
- @debug scale-color(rgba(#036, 0.3), $alpha: -30%) // rgba(0, 51, 102, 0.21)
- <% end %>
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3)
- @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1)
- @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0)
- ===
- @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3)
- @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1)
- @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0)
- <% end %>
-<% end %>
diff --git a/source/documentation/functions/css.html.md.erb b/source/documentation/functions/css.html.md.erb
deleted file mode 100644
index 1fe5b811d..000000000
--- a/source/documentation/functions/css.html.md.erb
+++ /dev/null
@@ -1,41 +0,0 @@
----
-title: Plain CSS Functions
-introduction: >
- Any function call that's not either a [built-in](../functions) or
- [user-defined](../at-rules/function) function is compiled to a plain CSS
- function (unless it uses [Sass argument
- syntax](../at-rules/function#arguments)). The arguments will be compiled to
- CSS and included as-is in the function call. This ensures that Sass supports
- all CSS functions without needing to release new versions every time a new one
- is added.
----
-
-<% example(autogen_css: false) do %>
- @debug var(--main-bg-color); // var(--main-bg-color)
-
- $primary: #f2ece4;
- $accent: #e1d7d2;
- @debug radial-gradient($primary, $accent); // radial-gradient(#f2ece4, #e1d7d2)
- ===
- @debug var(--main-bg-color) // var(--main-bg-color)
-
- $primary: #f2ece4
- $accent: #e1d7d2
- @debug radial-gradient($primary, $accent) // radial-gradient(#f2ece4, #e1d7d2)
-<% end %>
-
-<% heads_up do %>
- Because any unknown function will be compiled to CSS, it's easy to miss when
- you typo a function name. Consider running a [CSS linter][] on your
- stylesheet's output to be notified when this happens!
-
- [CSS linter]: https://stylelint.io/
-<% end %>
-
-<% fun_fact do %>
- Some CSS functions, like `calc()` and `element()` have unusual syntax. Sass
- [parses these functions specially][] as [unquoted strings][].
-
- [parses these functions specially]: ../syntax/special-functions
- [unquoted strings]: ../values/strings#unquoted
-<% end %>
diff --git a/source/documentation/functions/list.html.md.erb b/source/documentation/functions/list.html.md.erb
deleted file mode 100644
index cb1013e59..000000000
--- a/source/documentation/functions/list.html.md.erb
+++ /dev/null
@@ -1,203 +0,0 @@
----
-title: List Functions
----
-
-<% fun_fact do %>
- In Sass, every [map][] counts as a list that contains a two-element list for
- each key/value pair. For example, `(1: 2, 3: 4)` counts as `(1 2, 3 4)`. So
- all these functions work for maps as well!
-
- [map]: ../values/maps
-
- Individual values also count as lists. All these functions treat `1px` as a
- list that contains the value `1px`.
-<% end %>
-
-
-<% function 'append($list, $val, $separator: auto)', returns: 'list' do %>
- Returns a copy of `$list` with `$val` added to the end.
-
- If `$separator` is `comma`, the returned list is comma-separted. If it's
- `space`, the returned list is space-separated. If it's `auto` (the default), the
- returned list will use the same separator as `$list` (or `space` if `$list`
- doesn't have a separator). Other values aren't allowed.
-
- [separator]: ../values/lists
-
- Note that unlike [`join()`](#join), if `$val` is a list it's nested within the
- returned list rather than having all its elements added to the returned list.
-
- <% example(autogen_css: false) do %>
- @debug append(10px 20px, 30px); // 10px 20px 30px
- @debug append((blue, red), green); // blue, red, green
- @debug append(10px 20px, 30px 40px); // 10px 20px (30px 40px)
- @debug append(10px, 20px, $separator: comma); // 10px, 20px
- @debug append((blue, red), green, $separator: space); // blue red green
- ===
- @debug append(10px 20px, 30px) // 10px 20px 30px
- @debug append((blue, red), green) // blue, red, green
- @debug append(10px 20px, 30px 40px) // 10px 20px (30px 40px)
- @debug append(10px, 20px, $separator: comma) // 10px, 20px
- @debug append((blue, red), green, $separator: space) // blue red green
- <% end %>
-<% end %>
-
-
-<% function 'index($list, $value)', returns: 'number | null' do %>
- Returns the [index][] of `$value` in `$list`.
-
- [index]: ../values/lists#indexes
-
- If `$value` doesn't appear in `$list`, this returns [`null`][]. If `$value`
- appears multiple times in `$list`, this returns the index of its first
- appearance.
-
- [`null`]: ../values/null
-
- <%= partial 'code-snippets/example-list-index' %>
-<% end %>
-
-
-<% function 'is-bracketed($list)', returns: 'boolean' do %>
- Returns whether `$list` has square brackets.
-
- <% example(autogen_css: false) do %>
- @debug is-bracketed(1px 2px 3px); // false
- @debug is-bracketed([1px, 2px, 3px]); // true
- ===
- @debug is-bracketed(1px 2px 3px) // false
- @debug is-bracketed([1px, 2px, 3px]) // true
- <% end %>
-<% end %>
-
-
-<% function 'join($list1, $list2, $separator: auto, $bracketed: auto)', returns: 'list' do %>
- Returns a new list containing the elements of `$list1` followed by the elements
- of `$list2`.
-
- <% heads_up do %>
- Because individual values count as single-element lists, it's possible to
- use `join()` to add a value to the end of a list. However, *this is not
- recommended*, since if that value is a list it will be concatenated, which
- is probably not what you're expecting.
-
- Use [`append()`](#append) instead to add a single value to a list. Only use
- `join()` to combine two lists together into one.
- <% end %>
-
- If `$separator` is `comma`, the returned list is comma-separted. If it's
- `space`, the returned list is space-separated. If it's `auto` (the default),
- the returned list will use the same separator as `$list1` if it has a
- separator, or else `$list2` if it has a separator, or else `space`. Other
- values aren't allowed.
-
- If `$bracketed` is `true`, the returned list has square brackets. If it's
- `false`, the returned list has no brackets. If it's `auto` (the default), the
- returned list will be bracketed if `$list1` is. Other values aren't allowed.
-
- <% example(autogen_css: false) do %>
- @debug join(10px 20px, 30px 40px); // 10px 20px 30px 40px
- @debug join((blue, red), (#abc, #def)); // blue, red, #abc, #def
- @debug join(10px, 20px); // 10px 20px
- @debug join(10px, 20px, $separator: comma); // 10px, 20px
- @debug join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def
- @debug join([10px], 20px); // [10px 20px]
- @debug join(10px, 20px, $bracketed: true); // [10px 20px]
- ===
- @debug join(10px 20px, 30px 40px) // 10px 20px 30px 40px
- @debug join((blue, red), (#abc, #def)) // blue, red, #abc, #def
- @debug join(10px, 20px) // 10px 20px
- @debug join(10px, 20px, comma) // 10px, 20px
- @debug join((blue, red), (#abc, #def), space) // blue red #abc #def
- @debug join([10px], 20px) // [10px 20px]
- @debug join(10px, 20px, $bracketed: true) // [10px 20px]
- <% end %>
-<% end %>
-
-
-<% function 'length($list)', returns: 'number' do %>
- Returns the length of `$list`.
-
- This can also return the number of pairs in a map.
-
- <% example(autogen_css: false) do %>
- @debug length(10px); // 1
- @debug length(10px 20px 30px); // 3
- @debug length((width: 10px, height: 20px)); // 2
- ===
- @debug length(10px) // 1
- @debug length(10px 20px 30px) // 3
- @debug length((width: 10px, height: 20px)) // 2
- <% end %>
-<% end %>
-
-
-<% function 'list-separator($list)', returns: 'unquoted string' do %>
- Returns the name of the separator used by `$list`, either `space` or `comma`.
-
- If `$list` doesn't have a separator, returns `space`.
-
- <% example(autogen_css: false) do %>
- @debug list-separator(1px 2px 3px); // space
- @debug list-separator(1px, 2px, 3px); // comma
- @debug list-separator('Helvetica'); // space
- @debug list-separator(()); // space
- ===
- @debug list-separator(1px 2px 3px) // space
- @debug list-separator(1px, 2px, 3px) // comma
- @debug list-separator('Helvetica') // space
- @debug list-separator(()) // space
- <% end %>
-<% end %>
-
-
-<% function 'nth($list, $n)' do %>
- Returns the element of `$list` at [index][] `$n`.
-
- [index]: ../values/lists#indexes
-
- If `$n` is negative, it counts from the end of `$list`. Throws an error if
- there is no element at index `$n`.
-
- <%= partial 'code-snippets/example-list-nth' %>
-<% end %>
-
-
-<% function 'set-nth($list, $n, $value)', returns: 'list' do %>
- Returns a copy of `$list` with the element at [index][] `$n` replaced with
- `$value`.
-
- [index]: ../values/lists#indexes
-
- If `$n` is negative, it counts from the end of `$list`. Throws an error if
- there is no existing element at index `$n`.
-
- <% example(autogen_css: false) do %>
- @debug set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px
- @debug set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em
- @debug set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto
- ===
- @debug set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px
- @debug set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em
- @debug set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto
- <% end %>
-<% end %>
-
-
-<% function 'zip($lists...)', returns: 'list' do %>
- Combines every list in `$lists` into a single list of sub-lists.
-
- Each element in the returned list contains all the elements at that position
- in `$lists`. The returned list is as long as the shortest list in `$lists`.
-
- The returned list is always comma-separated and the sub-lists are always
- space-separated.
-
- <% example(autogen_css: false) do %>
- @debug zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long
- @debug zip(10px 50px 100px, short mid); // 10px short, 50px mid
- ===
- @debug zip(10px 50px 100px, short mid long) // 10px short, 50px mid, 100px long
- @debug zip(10px 50px 100px, short mid) // 10px short, 50px mid
- <% end %>
-<% end %>
diff --git a/source/documentation/functions/math.html.erb b/source/documentation/functions/math.html.erb
deleted file mode 100644
index 0761ba741..000000000
--- a/source/documentation/functions/math.html.erb
+++ /dev/null
@@ -1,205 +0,0 @@
----
-title: Number Functions
----
-
-<% function 'abs($number)', returns: 'number' do %>
- Returns the [absolute value][] of `$number`. If `$number` is negative, this
- returns `-$number`, and if `$number` is positive, it returns `$number` as-is.
-
- [absolute value]: https://en.wikipedia.org/wiki/Absolute_value
-
- <% example(autogen_css: false) do %>
- @debug abs(10px); // 10px
- @debug abs(-10px); // 10px
- ===
- @debug abs(10px) // 10px
- @debug abs(-10px) // 10px
- <% end %>
-<% end %>
-
-
-<% function 'ceil($number)', returns: 'number' do %>
- Rounds `$number` up to the next highest whole number.
-
- <% example(autogen_css: false) do %>
- @debug ceil(4); // 4
- @debug ceil(4.2); // 5
- @debug ceil(4.9); // 5
- ===
- @debug ceil(4) // 4
- @debug ceil(4.2) // 5
- @debug ceil(4.9) // 5
- <% end %>
-<% end %>
-
-
-<% function 'comparable($number1, $number2)', returns: 'boolean' do %>
- Returns whether `$number1` and `$number2` have compatible units.
-
- If this returns `true`, `$number1` and `$number2` can safely be [added][],
- [subtracted][], and [compared][]. Otherwise, doing so will produce errors.
-
- [added]: ../operators/numeric
- [subtracted]: ../operators/numeric
- [compared]: ../operators/relational
-
- <% example(autogen_css: false) do %>
- @debug comparable(2px, 1px); // true
- @debug comparable(100px, 3em); // false
- @debug comparable(10cm, 3mm); // true
- ===
- @debug comparable(2px, 1px) // true
- @debug comparable(100px, 3em) // false
- @debug comparable(10cm, 3mm) // true
- <% end %>
-<% end %>
-
-
-<% function 'floor($number)', returns: 'number' do %>
- Rounds `$number` down to the next lowest whole number.
-
- <% example(autogen_css: false) do %>
- @debug floor(4); // 4
- @debug floor(4.2); // 4
- @debug floor(4.9); // 4
- ===
- @debug floor(4) // 4
- @debug floor(4.2) // 4
- @debug floor(4.9) // 4
- <% end %>
-<% end %>
-
-
-<% function 'max($number...)', returns: 'number' do %>
- Returns the highest of one or more numbers. A list of numbers can be passed
- [using `...`][].
-
- [using `...`]: ../at-rules/function#passing-arbitrary-arguments
-
- <% example(autogen_css: false) do %>
- @debug max(1px, 4px); // 4px
-
- $widths: 50px, 30px, 100px;
- @debug max($widths...); // 100px
- ===
- @debug max(1px, 4px) // 4px
-
- $widths: 50px, 30px, 100px
- @debug max($widths...) // 100px
- <% end %>
-<% end %>
-
-
-<% function 'min($number...)', returns: 'number' do %>
- Returns the lowest of one or more numbers. A list of numbers can be passed
- [using `...`][].
-
- [using `...`]: ../at-rules/function#passing-arbitrary-arguments
-
- <% example(autogen_css: false) do %>
- @debug min(1px, 4px); // 1px
-
- $widths: 50px, 30px, 100px;
- @debug min($widths...); // 30px
- ===
- @debug min(1px, 4px) // 1px
-
- $widths: 50px, 30px, 100px
- @debug min($widths...) // 30px
- <% end %>
-<% end %>
-
-
-<% function 'percentage($number)', returns: 'number' do %>
- Converts a unitless `$number` (usually a decimal between 0 and 1) to a
- percentage.
-
- <% fun_fact do %>
- This function is identical to `$number * 100%`.
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug percentage(0.2); // 20%
- @debug percentage(100px / 50px); // 200%
- ===
- @debug percentage(0.2) // 20%
- @debug percentage(100px / 50px) // 200%
- <% end %>
-<% end %>
-
-
-<% function 'random($limit: null)', returns: 'number' do %>
- If `$limit` is [`null`][], returns a random decimal number between 0 and 1.
-
- [`null`]: ../values/null
-
- <% example(autogen_css: false) do %>
- @debug random(); // 0.2821251858
- @debug random(); // 0.6221325814
- ===
- @debug random() // 0.2821251858
- @debug random() // 0.6221325814
- <% end %>
-
- * * *
-
- If `$limit` is a number greater than or equal to 1, returns a random whole
- number between 1 and `$limit`.
-
- <% example(autogen_css: false) do %>
- @debug random(10); // 4
- @debug random(10000); // 5373
- ===
- @debug random(10) // 4
- @debug random(10000) // 5373
- <% end %>
-<% end %>
-
-
-<% function 'round($number)', returns: 'number' do %>
- Rounds `$number` to the nearest whole number.
-
- <% example(autogen_css: false) do %>
- @debug round(4); // 4
- @debug round(4.2); // 4
- @debug round(4.9); // 5
- ===
- @debug round(4) // 4
- @debug round(4.2) // 4
- @debug round(4.9) // 5
- <% end %>
-<% end %>
-
-
-<% function 'unit($number)', returns: 'quoted string' do %>
- Returns a string representation of `$number`'s units.
-
- <% heads_up do %>
- This function is intended for debugging; its output format is not guaranteed
- to be consistent across Sass versions or implementations.
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug unit(100); // ""
- @debug unit(100px); // "px"
- @debug unit(5px * 10px); // "px*px"
- @debug unit(5px / 1s); // "px/s"
- ===
- @debug unit(100) // ""
- @debug unit(100px) // "px"
- @debug unit(5px * 10px) // "px*px"
- @debug unit(5px / 1s) // "px/s"
- <% end %>
-<% end %>
-
-<% function 'unitless($number)', returns: 'boolean' do %>
- Returns whether `$number` has no units.
-
- <% example(autogen_css: false) do %>
- @debug unitless(100); // true
- @debug unitless(100px); // false
- ===
- @debug unitless(100) // true
- @debug unitless(100px) // false
- <% end %>
-<% end %>
diff --git a/source/documentation/functions/meta.html.md.erb b/source/documentation/functions/meta.html.md.erb
deleted file mode 100644
index 93c89913a..000000000
--- a/source/documentation/functions/meta.html.md.erb
+++ /dev/null
@@ -1,275 +0,0 @@
----
-title: Introspection Functions
----
-
-<% function 'call($function, $args...)' do %>
- <%= partial 'documentation/snippets/call-impl-status' %>
-
- Invokes `$function` with `$args` and returns the result.
-
- The `$function` should be a [function][] returned by [`get-function()`][].
-
- [function]: ../values/functions
- [`get-function()`]: #get-function
-
- <%= partial 'code-snippets/example-first-class-function' %>
-<% end %>
-
-
-<% function 'content-exists()', returns: 'boolean' do %>
- Returns whether the current mixin was passed a [`@content` block][].
-
- [`@content` block]: ../at-rules/mixin#content-blocks
-
- Throws an error if called outside of a mixin.
-
- <% example(autogen_css: false) do %>
- @mixin debug-content-exists {
- @debug content-exists();
- @content;
- }
-
- @include debug-content-exists; // false
- @include debug-content-exists { // true
- // Content!
- }
- ===
- @mixin debug-content-exists
- @debug content-exists()
- @content
-
-
- @include debug-content-exists // false
- @include debug-content-exists // true
- // Content!
- <% end %>
-<% end %>
-
-
-<% function 'feature-exists($feature)', returns: 'boolean' do %>
- Returns whether the current Sass implementation supports `$feature`.
-
- The `$feature` must be a string. The currently recognized features are:
-
- * `global-variable-shadowing`, which means that a local variable will
- [shadow][] a global variable unless it has the `!global` flag.
- * `extend-selector-pseudoclass`, which means that the [`@extend` rule][] will
- affect selectors nested in pseudo-classes like `:not()`.
- * `units-level3`, which means that [unit arithmetic][] supports units defined
- in [CSS Values and Units Level 3][].
- * `at-error`, which means that the [`@error` rule][] is supported.
- * `custom-property`, which means that [custom property declaration][] values
- don't support any [expressions][] other than [interpolation][].
-
- [shadow]: ../variables#shadowing
- [`@extend` rule]: ../at-rules/extend
- [unit arithmetic]: ../values/numbers#units
- [CSS Values and Units Level 3]: http://www.w3.org/TR/css3-values
- [`@error` rule]: ../at-rules/error
- [custom property declaration]: ../style-rules/declarations#custom-properties
- [expressions]: ../syntax/structure#expressions
- [interpolation]: ../interpolation
-
- Returns `false` for any unrecognized `$feature`.
-
- <% example(autogen_css: false) do %>
- @debug feature-exists("at-error"); // true
- @debug feature-exists("unrecognized"); // false
- ===
- @debug feature-exists("at-error") // true
- @debug feature-exists("unrecognized") // false
- <% end %>
-<% end %>
-
-
-<% function 'function-exists($name)', returns: 'boolean' do %>
- Returns whether a function named `$name` is defined, either as a built-in
- function or a user-defined function.
-
- <% example(autogen_css: false) do %>
- @debug function-exists("scale-color"); // true
- @debug function-exists("add"); // false
-
- @function add($num1, $num2) {
- @return $num1 + $num2;
- }
- @debug function-exists("add"); // true
- ===
- @debug function-exists("scale-color") // true
- @debug function-exists("add") // false
-
- @function add($num1, $num2)
- @return $num1 + $num2
-
- @debug function-exists("add") // true
- <% end %>
-<% end %>
-
-
-<% function 'get-function($name, $css: false)', returns: 'function' do %>
- Returns the [function][] named `$name`.
-
- [function]: ../values/functions
-
- This can access both built-in and [user-defined][] functions. By default, it
- throws an error if `$name` doesn't refer to either a built-in or user-defined
- function. However, if `$css` is `true`, it instead returns a
- [plain CSS function][].
-
- [user-defined]: ../at-rules/function
- [plain CSS function]: css
-
- The returned function can be called using [`call()`](#call).
-
- <%= partial 'code-snippets/example-first-class-function' %>
-<% end %>
-
-
-<% function 'global-variable-exists($name)', returns: 'boolean' do %>
- Returns whether a [global variable][] named `$name` (without the `$`) exists.
-
- [global variable]: ../variables#scope
-
- See also [`variable-exists()`](#variable-exists).
-
- <% example(autogen_css: false) do %>
- @debug global-variable-exists("var1"); // false
-
- $var1: value;
- @debug global-variable-exists("var1"); // true
-
- h1 {
- // $var2 is local.
- $var2: value;
- @debug global-variable-exists("var2"); // false
- }
- ===
- @debug global-variable-exists("var1") // false
-
- $var1: value
- @debug global-variable-exists("var1") // true
-
- h1
- // $var2 is local.
- $var2: value
- @debug global-variable-exists("var2") // false
- <% end %>
-<% end %>
-
-
-<% function 'inspect($value)', returns: 'unquoted string' do %>
-
- Returns a string representation of `$value`.
-
- Returns a representation of *any* Sass value, not just those that can be
- represented in CSS. As such, its return value is not guaranteed to be valid
- CSS.
-
- <% heads_up do %>
- This function is intended for debugging; its output format is not guaranteed
- to be consistent across Sass versions or implementations.
- <% end %>
-
- <% example(autogen_css: false) do %>
- @debug inspect(10px 20px 30px); // unquote("10px 20px 30px")
- @debug inspect(("width": 200px)); // unquote('("width": 200px)')
- @debug inspect(null); // unquote("null")
- @debug inspect("Helvetica"); // unquote('"Helvetica"')
- ===
- @debug inspect(10px 20px 30px) // unquote("10px 20px 30px")
- @debug inspect(("width": 200px)) // unquote('("width": 200px)')
- @debug inspect(null) // unquote("null")
- @debug inspect("Helvetica") // unquote('"Helvetica"')
- <% end %>
-<% end %>
-
-
-<% function 'mixin-exists($name)', returns: 'boolean' do %>
- Returns whether a [mixin][] named `$name` exists.
-
- [mixin]: ../at-rules/mixin
-
- <% example(autogen_css: false) do %>
- @debug mixin-exists("shadow-none"); // false
-
- @mixin shadow-none {
- box-shadow: none;
- }
-
- @debug mixin-exists("shadow-none"); // true
- ===
- @debug mixin-exists("shadow-none") // false
-
- @mixin shadow-none
- box-shadow: none
-
-
- @debug mixin-exists("shadow-none") // true
- <% end %>
-<% end %>
-
-
-<% function 'type-of($value)', returns: 'unquoted string' do %>
- Returns the type of `$value`.
-
- This can return the following values:
-
- * [`number`](../values/numbers)
- * [`string`](../values/strings)
- * [`color`](../values/colors)
- * [`list`](../values/lists)
- * [`map`](../values/maps)
- * [`bool`](../values/booleans)
- * [`null`](../values/null)
- * [`function`](../values/functions)
- * [`arglist`](../values/lists#argument-lists)
-
- New possible values may be added in the future. It may return either `list` or
- `map` for `()`, depending on whether or not it was returned by a
- [map function][].
-
- [map function]: map
-
- <% example(autogen_css: false) do %>
- @debug type-of(10px); // number
- @debug type-of(10px 20px 30px); // list
- @debug type-of(()); // list
- ===
- @debug type-of(10px) // number
- @debug type-of(10px 20px 30px) // list
- @debug type-of(()) // list
- <% end %>
-<% end %>
-
-
-<% function 'variable-exists($name)', returns: 'boolean' do %>
- Returns whether a variable named `$name` (without the `$`) exists in the
- current [scope][].
-
- [scope]: ../variables#scope
-
- See also [`global-variable-exists()`](#global-variable-exists).
-
- <% example(autogen_css: false) do %>
- @debug variable-exists("var1"); // false
-
- $var1: value;
- @debug variable-exists("var1"); // true
-
- h1 {
- // $var2 is local.
- $var2: value;
- @debug variable-exists("var2"); // true
- }
- ===
- @debug variable-exists("var1") // false
-
- $var1: value
- @debug variable-exists("var1") // true
-
- h1
- // $var2 is local.
- $var2: value
- @debug variable-exists("var2") // true
- <% end %>
-<% end %>
diff --git a/source/documentation/functions/string.html.md.erb b/source/documentation/functions/string.html.md.erb
deleted file mode 100644
index 7bcea53b8..000000000
--- a/source/documentation/functions/string.html.md.erb
+++ /dev/null
@@ -1,149 +0,0 @@
----
-title: String Functions
----
-
-<% function 'quote($string)', returns: 'string' do %>
- Returns `$string` as a quoted string.
-
- <% example(autogen_css: false) do %>
- @debug quote(Helvetica); // "Helvetica"
- @debug quote("Helvetica"); // "Helvetica"
- ===
- @debug quote(Helvetica) // "Helvetica"
- @debug quote("Helvetica") // "Helvetica"
- <% end %>
-<% end %>
-
-
-<% function 'str-index($string, $substring)', returns: 'number' do %>
- Returns the first [index][] of `$substring` in `$string`, or `null` if
- `$string` doesn't contain `$substring`.
-
- [index]: ../values/strings#string-indexes
-
- <% example(autogen_css: false) do %>
- @debug str-index("Helvetica Neue", "Helvetica"); // 1
- @debug str-index("Helvetica Neue", "Neue"); // 11
- ===
- @debug str-index("Helvetica Neue", "Helvetica") // 1
- @debug str-index("Helvetica Neue", "Neue") // 11
- <% end %>
-<% end %>
-
-
-<% function 'str-insert($string, $insert, $index)', returns: 'string' do %>
- Returns a copy of `$string` with `$insert` inserted at [`$index`][].
-
- [`$index`]: ../values/strings#string-indexes
-
- <% example(autogen_css: false) do %>
- @debug str-insert("Roboto Bold", " Mono", 7); // "Roboto Mono Bold"
- @debug str-insert("Roboto Bold", " Mono", -6); // "Roboto Mono Bold"
- ===
- @debug str-insert("Roboto Bold", " Mono", 7) // "Roboto Mono Bold"
- @debug str-insert("Roboto Bold", " Mono", -6) // "Roboto Mono Bold"
- <% end %>
-
- If of `$index` is higher than the length of `$string`, `$insert` is added to
- the end. If `$index` is smaller than the negative length of the string,
- `$insert` is added to the beginning.
-
- <% example(autogen_css: false) do %>
- @debug str-insert("Roboto", " Bold", 100); // "Roboto Bold"
- @debug str-insert("Bold", "Roboto ", -100); // "Roboto Bold"
- ===
- @debug str-insert("Roboto", " Bold", 100) // "Roboto Bold"
- @debug str-insert("Bold", "Roboto ", -100) // "Roboto Bold"
- <% end %>
-<% end %>
-
-
-<% function 'str-length($string)', returns: 'number' do %>
- Returns the number of characters in `$string`.
-
- <% example(autogen_css: false) do %>
- @debug str-length("Helvetica Neue"); // 14
- @debug str-length(bold); // 4
- @debug str-index(""); // 0
- ===
- @debug str-length("Helvetica Neue") // 14
- @debug str-length(bold) // 4
- @debug str-index("") // 0
- <% end %>
-<% end %>
-
-
-<% function 'str-slice($string, $start-at, $end-at: -1)', returns: 'string' do %>
- Returns the slice of `$string` starting at [index][] `$start-at` and ending at
- index `$end-at` (both inclusive).
-
- [index]: ../values/strings#string-indexes
-
- <% example(autogen_css: false) do %>
- @debug str-slice("Helvetica Neue", 11); // "Neue"
- @debug str-slice("Helvetica Neue", 1, 3); // "Hel"
- @debug str-slice("Helvetica Neue", 1, -6); // "Helvetica"
- ===
- @debug str-slice("Helvetica Neue", 11) // "Neue"
- @debug str-slice("Helvetica Neue", 1, 3) // "Hel"
- @debug str-slice("Helvetica Neue", 1, -6) // "Helvetica"
- <% end %>
-<% end %>
-
-
-<% function 'to-upper-case($string)', returns: 'string' do %>
- Returns a copy of `$string` with the [ASCII][] letters converted to upper case.
-
- [ASCII]: https://en.wikipedia.org/wiki/ASCII
-
- <% example(autogen_css: false) do %>
- @debug to-upper-case("Bold"); // "BOLD"
- @debug to-upper-case(sans-serif); // SANS-SERIF
- ===
- @debug to-upper-case("Bold") // "BOLD"
- @debug to-upper-case(sans-serif) // SANS-SERIF
- <% end %>
-<% end %>
-
-
-<% function 'to-lower-case($string)', returns: 'string' do %>
- Returns a copy of `$string` with the [ASCII][] letters converted to lower case.
-
- [ASCII]: https://en.wikipedia.org/wiki/ASCII
-
- <% example(autogen_css: false) do %>
- @debug to-lower-case("Bold"); // "bold"
- @debug to-lower-case(SANS-SERIF); // sans-serif
- ===
- @debug to-lower-case("Bold") // "bold"
- @debug to-lower-case(SANS-SERIF) // sans-serif
- <% end %>
-<% end %>
-
-
-<% function 'unique-id()', returns: 'string' do %>
- Returns a randomly-generated unquoted string that's guaranteed to be a valid
- CSS identifier and to be unique within the current Sass compilation.
-
- <% example(autogen_css: false) do %>
- @debug unique-id(); // uabtrnzug
- @debug unique-id(); // u6w1b1def
- ===
- @debug unique-id(); // uabtrnzug
- @debug unique-id(); // u6w1b1def
- <% end %>
-<% end %>
-
-
-<% function 'unquote()', returns: 'string' do %>
- Returns `$string` as an unquoted string. This can produce strings that aren't
- valid CSS, so use with caution.
-
- <% example(autogen_css: false) do %>
- @debug unquote("Helvetica"); // Helvetica
- @debug unquote(".widget:hover"); // .widget:hover
- ===
- @debug unquote("Helvetica") // Helvetica
- @debug unquote(".widget:hover") // .widget:hover
- <% end %>
-<% end %>
diff --git a/source/documentation/index.html.md b/source/documentation/index.html.md
index e4420300b..8214f7ecb 100644
--- a/source/documentation/index.html.md
+++ b/source/documentation/index.html.md
@@ -5,7 +5,7 @@ introduction: >
[variables](/documentation/variables), [nested
rules](/documentation/style-rules#nesting),
[mixins](/documentation/at-rules/mixin),
- [functions](/documentation/functions), and more, all with a fully
+ [functions](/documentation/modules), and more, all with a fully
CSS-compatible syntax. Sass helps keep large stylesheets well-organized and
makes it easy to share design within and across projects.
overview: true
@@ -15,7 +15,7 @@ overview: true
tutorial](/guide).
* If you want to look up a built-in Sass function, look no further than [the
- function reference](/documentation/functions).
+ built-in module reference](/documentation/modules).
* If you're calling Sass from JavaScript, you may want the [JS API
documentation][js].
diff --git a/source/documentation/interpolation.html.md.erb b/source/documentation/interpolation.html.md.erb
index 0c45a0668..1706e7838 100644
--- a/source/documentation/interpolation.html.md.erb
+++ b/source/documentation/interpolation.html.md.erb
@@ -15,7 +15,7 @@ introduction: >
* [Plain CSS `@import`s](at-rules/import#plain-css-imports)
* [Quoted or unquoted strings](values/strings)
* [Special functions](syntax/special-functions)
-* [Plain CSS function names](functions/css)
+* [Plain CSS function names](at-rules/function#plain-css-functions)
* [Loud comments](syntax/comments)
<% example do %>
@@ -144,8 +144,8 @@ them into style rules.
<% heads_up do %>
While it's tempting to use this feature to convert quoted strings to unquoted
- strings, it's a lot clearer to use the [`unquote()` function][]. Instead of
- `#{$string}`, write `unquote($string)`!
+ strings, it's a lot clearer to use the [`string.unquote()` function][].
+ Instead of `#{$string}`, write `string.unquote($string)`!
- [`unquote()` function]: functions/string#unquote
+ [`string.unquote()` function]: modules/string#unquote
<% end %>
diff --git a/source/documentation/js-api.html.md.erb b/source/documentation/js-api.html.md.erb
index 9441eb4f2..fd7944629 100644
--- a/source/documentation/js-api.html.md.erb
+++ b/source/documentation/js-api.html.md.erb
@@ -137,8 +137,8 @@ console.log(result.map.toString());
An array of the absolute paths of all Sass files loaded during compilation. If a
stylesheet was loaded from an [importer][] that returned the stylesheet's
-contents, the raw strings of that stylesheet's `@import` is included in this
-array.
+contents, the raw string of the `@use` or `@import` that loaded that stylesheet
+is included in this array.
[importer]: #importer
@@ -188,9 +188,9 @@ provides the same information.
The stylesheet where the error occurred. If the error occurred in a stylesheet
loaded from disk, this is the absolute path of that stylesheet. If the error
occurred in a stylesheet that was loaded from an [importer][] which returned the
-stylesheet's contents, this is the raw string of that stylesheet's `@import`. If
-it occurred in the contents of the [`data` option][], this is the string
-`"stdin"`.
+stylesheet's contents, this is the raw string of the `@use` or `@import` that
+loaded that stylesheet. If it occurred in the contents of the [`data` option][],
+this is the string `"stdin"`.
#### `error.line`
@@ -741,21 +741,23 @@ h1 {
somewhere else to break it.
<% end %>
-This option defines one or more additional handlers for loading files when an
-[`@import` rule][] is encountered. It can either be a single JavaScript
-function, or an array of functions. These functions are always passed two
-arguments:
+This option defines one or more additional handlers for loading files when a
+[`@use` rule] or an [`@import` rule][] is encountered. It can either be a single
+JavaScript function, or an array of functions. These functions are always passed
+two arguments:
+[`@use` rule]: at-rules/use
[`@import` rule]: at-rules/import
-1. The `@import` rule's URL as a string, exactly as it appears in the
+1. The `@use` or `@import` rule's URL as a string, exactly as it appears in the
stylesheet.
-2. A string identifying for the stylesheet that contained the `@import`. This
- identifier's format depends on how that stylesheet was loaded:
+2. A string identifying for the stylesheet that contained the `@use` or
+ `@import`. This identifier's format depends on how that stylesheet was
+ loaded:
* If the stylesheet was loaded from the filesystem, it's the absolute path of
its file.
* If the stylesheet was loaded from an importer that returned its contents,
- it's the URL of the `@import` rule that loaded it.
+ it's the URL of the `@use` or `@import` rule that loaded it.
* If the stylesheet came from the [`data` option][], it's the string
`"stdin"`.
@@ -775,7 +777,7 @@ asynchronously pass the result of the import once it's complete.
Imports are resolved by trying, in order:
-* Loading a file relative to the file in which the `@import` appeared.
+* Loading a file relative to the file in which the `@use` or `@import` appeared.
* Each custom importer.
@@ -793,7 +795,7 @@ sass.render({
// This importer uses the synchronous API, and can be passed to either
// renderSync() or render().
function(url, prev) {
- // This generates a stylesheet from scratch for `@import "big-headers"`.
+ // This generates a stylesheet from scratch for `@use "big-headers"`.
if (url != "big-headers") return null;
return {
@@ -807,7 +809,7 @@ h1 {
// This importer uses the asynchronous API, and can only be passed to
// render().
function(url, prev, done) {
- // Convert `@import "foo/bar"` to "node_modules/foo/sass/bar".
+ // Convert `@use "foo/bar"` to "node_modules/foo/sass/bar".
var components = url.split('/');
var innerPath = components.slice(1).join('/');
done({
diff --git a/source/documentation/modules.html.md.erb b/source/documentation/modules.html.md.erb
new file mode 100644
index 000000000..94ce09ee7
--- /dev/null
+++ b/source/documentation/modules.html.md.erb
@@ -0,0 +1,278 @@
+---
+title: Built-In Modules
+introduction: >
+ Sass provides many built-in modules which contain useful functions (and the
+ occasional mixin). These modules can be loaded with the
+ [`@use` rule](at-rules/use) like any user-defined stylesheet, and their
+ functions can be called [like any other module
+ member](at-rules/use#loading-members). All built-in module URLs begin with
+ `sass:` to indicate that they're part of Sass itself.
+overview: true
+---
+
+<% content_for :before_introduction do %>
+ <%= partial 'snippets/built-in-module-status' %>
+<% end %>
+
+<% heads_up do %>
+ Before the Sass module system was introduced, all Sass functions were globally
+ available at all times. Many functions still have global aliases (these are
+ listed in their documentation). The Sass team discourages their use and will
+ eventually deprecate them, but for now they remain available for compatibility
+ with older Sass versions and with LibSass (which doesn't support the module
+ system yet).
+
+ [A few functions][] are *only* available globally even in the new module
+ system, either because they have special evaluation behavior ([`if()`][]) or
+ because they add extra behavior on top of built-in CSS functions ([`rgb()`][]
+ and [`hsl()`][]). These will not be deprecated and can be used freely.
+
+ [a few functions]: #global-functions
+ [`if()`]: #if
+ [`rgb()`]: #rgb
+ [`hsl()`]: #hsl
+<% end %>
+
+<% example do %>
+ @use "sass:color";
+
+ .button {
+ $primary-color: #6b717f;
+ color: $primary-color;
+ border: 1px solid color.scale($primary-color, $lightness: 20%);
+ }
+ ===
+ @use "sass:color"
+
+ .button
+ $primary-color: #6b717f
+ color: $primary-color
+ border: 1px solid color.scale($primary-color, $lightness: 20%)
+ ===
+ .button {
+ color: #6b717f;
+ border: 1px solid #878d9a;
+ }
+<% end %>
+
+Sass provides the following built-in modules:
+
+* The [`sass:math` module][] provides functions that operate on [numbers][].
+
+* The [`sass:string` module][] makes it easy to combine, search, or split apart
+ [strings][].
+
+* The [`sass:color` module][] generates new [colors][] based on existing ones,
+ making it easy to build color themes.
+
+* The [`sass:list` module][] lets you access and modify values in [lists][].
+
+* The [`sass:map` module][] makes it possible to look up the value associated
+ with a key in a [map][], and much more.
+
+* The [`sass:selector` module][] provides access to Sass's powerful selector
+ engine.
+
+* The [`sass:meta` module][] exposes the details of Sass's inner workings.
+
+[`sass:math` module]: modules/math
+[numbers]: values/numbers
+[`sass:string` module]: modules/string
+[strings]: values/strings
+[`sass:color` module]: modules/color
+[colors]: values/colors
+[`sass:list` module]: modules/list
+[lists]: values/lists
+[`sass:map` module]: modules/map
+[map]: values/maps
+[`sass:selector` module]: modules/selector
+[`sass:meta` module]: modules/meta
+
+## Global Functions
+
+<% function 'hsl($hue $saturation $lightness)',
+ 'hsl($hue $saturation $lightness / $alpha)',
+ 'hsl($hue, $saturation, $lightness, $alpha: 1)',
+ 'hsla($hue $saturation $lightness)',
+ 'hsla($hue $saturation $lightness / $alpha)',
+ 'hsla($hue, $saturation, $lightness, $alpha: 1)',
+ returns: 'color' do %>
+ <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %>
+ LibSass and Ruby Sass only support the following signatures:
+
+ * `hsl($hue, $saturation, $lightness)`
+ * `hsla($hue, $saturation, $lightness, $alpha)`
+
+ Note that for these implementations, the `$alpha` argument is *required* if
+ the function name `hsla()` is used, and *forbidden* if the function name
+ `hsl()` is used.
+ <% end %>
+
+ <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %>
+ LibSass and older versions of Ruby Sass don't support alpha values specified as
+ percentages.
+ <% end %>
+
+ Returns a color with the given [hue, saturation, and lightness][] and the given
+ alpha channel.
+
+ [hue, saturation, and lightness]: https://en.wikipedia.org/wiki/HSL_and_HSV
+
+ The hue is a number between `0deg` and `360deg` (inclusive). The saturation
+ and lightness are numbers between `0%` and `100%` (inclusive). All these
+ numbers may be [unitless][]. The alpha channel can be specified as either a
+ unitless number between 0 and 1 (inclusive), or a percentage between `0%` and
+ `100%` (inclusive).
+
+ [unitless]: values/numbers#units
+
+ <% fun_fact do %>
+ You can pass [special functions][] like `calc()` or `var()` in place of any
+ argument to `hsl()`. You can even use `var()` in place of multiple
+ arguments, since it might be replaced by multiple values! When a color
+ function is called this way, it returns an unquoted string using the same
+ signature it was called with.
+
+ [special functions]: syntax/special-functions
+
+ <% example(autogen_css: false) do %>
+ @debug hsl(210deg 100% 20% / var(--opacity)); // hsl(210deg 100% 20% / var(--opacity))
+ @debug hsla(var(--peach), 20%); // hsla(var(--peach), 20%)
+ ===
+ @debug hsl(210deg 100% 20% / var(--opacity)) // hsl(210deg 100% 20% / var(--opacity))
+ @debug hsla(var(--peach), 20%) // hsla(var(--peach), 20%)
+ <% end %>
+ <% end %>
+
+ <% heads_up do %>
+ Sass's [special parsing rules][] for slash-separated values make it
+ difficult to pass variables for `$lightness` or `$alpha` when using the
+ `hsl($hue $saturation $lightness / $alpha)` signature. Consider using
+ `hsl($hue, $saturation, $lightness, $alpha)` instead.
+
+ [special parsing rules]: operators/numeric#slash-separated-values
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug hsl(210deg 100% 20%); // #036
+ @debug hsl(34, 35%, 92%); // #f2ece4
+ @debug hsl(210deg 100% 20% / 50%); // rgba(0, 51, 102, 0.5)
+ @debug hsla(34, 35%, 92%, 0.2); // rgba(242, 236, 228, 0.2)
+ ===
+ @debug hsl(210deg 100% 20%) // #036
+ @debug hsl(34, 35%, 92%) // #f2ece4
+ @debug hsl(210deg 100% 20% / 50%) // rgba(0, 51, 102, 0.5)
+ @debug hsla(34, 35%, 92%, 0.2) // rgba(242, 236, 228, 0.2)
+ <% end %>
+<% end %>
+
+
+<% function "if($condition, $if-true, $if-false)" do %>
+ Returns `$if-true` if `$condition` is [truthy][], and `$if-false` otherwise.
+
+ This function is special in that it doesn't even evaluate the argument that
+ isn't returned, so it's safe to call even if the unused argument would throw an
+ error.
+
+ [truthy]: at-rules/control/if#truthiness-and-falsiness
+
+ <% example(autogen_css: false) do %>
+ @debug if(true, 10px, 15px); // 10px
+ @debug if(false, 10px, 15px); // 15px
+ @debug if(variable-defined($var), $var, null); // null
+ ===
+ @debug if(true, 10px, 15px) // 10px
+ @debug if(false, 10px, 15px) // 15px
+ @debug if(variable-defined($var), $var, null) // null
+ <% end %>
+<% end %>
+
+
+<% function 'rgb($red $green $blue)',
+ 'rgb($red $green $blue / $alpha)',
+ 'rgb($red, $green, $blue, $alpha: 1)',
+ 'rgb($color, $alpha)',
+ 'rgba($red $green $blue)',
+ 'rgba($red $green $blue / $alpha)',
+ 'rgba($red, $green, $blue, $alpha: 1)',
+ 'rgba($color, $alpha)',
+ returns: 'color' do %>
+ <% impl_status dart: '1.15.0', libsass: false, ruby: false, feature: "Level 4 Syntax" do %>
+ LibSass and Ruby Sass only support the following signatures:
+
+ * `rgb($red, $green, $blue)`
+ * `rgba($red, $green, $blue, $alpha)`
+ * `rgba($color, $alpha)`
+
+ Note that for these implementations, the `$alpha` argument is *required* if
+ the function name `rgba()` is used, and *forbidden* if the function name
+ `rgb()` is used.
+ <% end %>
+
+ <% impl_status dart: true, libsass: false, ruby: '3.7.0', feature: "Percent Alpha" do %>
+ LibSass and older versions of Ruby Sass don't support alpha values specified
+ as percentages.
+ <% end %>
+
+ If `$red`, `$green`, `$blue`, and optionally `$alpha` are passed, returns a
+ color with the given red, green, blue, and alpha channels.
+
+ Each channel can be specified as either a [unitless][] number between 0 and
+ 255 (inclusive), or a percentage between `0%` and `100%` (inclusive). The
+ alpha channel can be specified as either a unitless number between 0 and 1
+ (inclusive), or a percentage between `0%` and `100%` (inclusive).
+
+ [unitless]: values/numbers#units
+
+ <% fun_fact do %>
+ You can pass [special functions][] like `calc()` or `var()` in place of any
+ argument to `rgb()`. You can even use `var()` in place of multiple
+ arguments, since it might be replaced by multiple values! When a color
+ function is called this way, it returns an unquoted string using the same
+ signature it was called with.
+
+ [special functions]: syntax/special-functions
+
+ <% example(autogen_css: false) do %>
+ @debug rgb(0 51 102 / var(--opacity)); // rgb(0 51 102 / var(--opacity))
+ @debug rgba(var(--peach), 0.2); // rgba(var(--peach), 0.2)
+ ===
+ @debug rgb(0 51 102 / var(--opacity)) // rgb(0 51 102 / var(--opacity))
+ @debug rgba(var(--peach), 0.2) // rgba(var(--peach), 0.2)
+ <% end %>
+ <% end %>
+
+ <% heads_up do %>
+ Sass's [special parsing rules][] for slash-separated values make it
+ difficult to pass variables for `$blue` or `$alpha` when using the
+ `rgb($red $green $blue / $alpha)` signature. Consider using
+ `hsl($red, $green, $blue, $alpha)` instead.
+
+ [special parsing rules]: operators/numeric#slash-separated-values
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug rgb(0 51 102); // #036
+ @debug rgb(95%, 92.5%, 89.5%); // #f2ece4
+ @debug rgb(0 51 102 / 50%); // rgba(0, 51, 102, 0.5)
+ @debug rgba(95%, 92.5%, 89.5%, 0.2); // rgba(242, 236, 228, 0.2)
+ ===
+ @debug rgb(0 51 102) // #036
+ @debug rgb(95%, 92.5%, 89.5%) // #f2ece4
+ @debug rgb(0 51 102 / 50%) // rgba(0, 51, 102, 0.5)
+ @debug rgba(95%, 92.5%, 89.5%, 0.2) // rgba(242, 236, 228, 0.2)
+ <% end %>
+
+ ---
+
+ If `$color` and `$alpha` are passed, this returns `$color` with the given
+ `$alpha` channel instead of its original alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug rgb(#f2ece4, 50%); // rgba(242, 236, 228, 0.5);
+ @debug rgba(rgba(0, 51, 102, 0.5), 1); // #003366
+ ===
+ @debug rgb(#f2ece4, 50%) // rgba(242, 236, 228, 0.5)
+ @debug rgba(rgba(0, 51, 102, 0.5), 1) // #003366
+ <% end %>
+<% end %>
diff --git a/source/documentation/modules/color.html.md.erb b/source/documentation/modules/color.html.md.erb
new file mode 100644
index 000000000..75dddaf5d
--- /dev/null
+++ b/source/documentation/modules/color.html.md.erb
@@ -0,0 +1,766 @@
+---
+title: sass:color
+---
+
+<%= partial '../snippets/built-in-module-status' %>
+
+<% function <
+ Increases or decreases one or more properties of `$color` by fixed amounts.
+
+ Adds the value passed for each keyword argument to the corresponding property
+ of the color, and returns the adjusted color. It's an error to specify an RGB
+ property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL
+ property (`$hue`, `$saturation`, and/or `$lightness`).
+
+ All optional arguments must be numbers. The `$red`, `$green`, and `$blue`
+ arguments must be [unitless][] and between -255 and 255 (inclusive). The
+ `$hue` argument must have either the unit `deg` or no unit. The `$saturation`
+ and `$lightness` arguments must be between `-100%` and `100%` (inclusive), and
+ may be unitless. The `$alpha` argument must be unitless and between -1 and 1
+ (inclusive).
+
+ [unitless]: ../values/numbers#units
+
+ See also:
+
+ * [`color.scale()`](#scale) for fluidly scaling a color's properties.
+ * [`color.change()`](#change) for setting a color's properties.
+
+ <% example(autogen_css: false) do %>
+ @debug color.adjust(#6b717f, $red: 15); // #7a717f
+ @debug color.adjust(#d2e1dd, $red: -10, $blue: 10); // #c8e1e7
+ @debug color.adjust(#998099, $lightness: -30%, $alpha: -0.4); // rgba(71, 57, 71, 0.6)
+ ===
+ @debug color.adjust(#6b717f, $red: 15) // #7a717f
+ @debug color.adjust(#d2e1dd, $red: -10, $blue: 10) // #c8e1e7
+ @debug color.adjust(#998099, $lightness: -30%, $alpha: -0.4) // rgba(71, 57, 71, 0.6)
+ <% end %>
+<% end %>
+
+
+<% function 'adjust-hue($color, $degrees)', returns: 'color' do %>
+ Increases or decreases `$color`'s hue.
+
+ The `$hue` must be a number between `-360deg` and `360deg` (inclusive) to add
+ to `$color`'s hue. It may be [unitless][].
+
+ [unitless]: ../values/numbers#units
+
+ See also [`color.adjust()`](#adjust), which can adjust any property of a
+ color.
+
+ <% heads_up do %>
+ Because `adjust-hue()` is redundant with [`adjust()`](#adjust), it's not
+ included directly in the new module system. Instead of
+ `adjust-hue($color, $amount)`, you can write
+ [`color.adjust($color, $hue: $amount)`](#adjust).
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ // Hue 222deg becomes 282deg.
+ @debug adjust-hue(#6b717f, 60deg); // #796b7f
+
+ // Hue 164deg becomes 104deg.
+ @debug adjust-hue(#d2e1dd, -60deg); // #d6e1d2
+
+ // Hue 210deg becomes 255deg.
+ @debug adjust-hue(#036, 45); // #1a0066
+ ===
+ // Hue 222deg becomes 282deg.
+ @debug adjust-hue(#6b717f, 60deg) // #796b7f
+
+ // Hue 164deg becomes 104deg.
+ @debug adjust-hue(#d2e1dd, -60deg) // #d6e1d2
+
+ // Hue 210deg becomes 255deg.
+ @debug adjust-hue(#036, 45) // #1a0066
+ <% end %>
+<% end %>
+
+
+<% function 'color.alpha($color)',
+ 'alpha($color)',
+ 'opacity($color)',
+ returns: 'number' do %>
+ Returns the alpha channel of `$color` as a number between 0 and 1.
+
+ As a special case, this supports the Internet Explorer syntax
+ `alpha(opacity=20)`, for which it returns an [unquoted string][].
+
+ [unquoted string]: ../values/strings#unquoted
+
+ See also:
+
+ * [`color.red()`](#red) for getting a color's red channel.
+ * [`color.green()`](#green) for getting a color's green channel.
+ * [`color.blue()`](#blue) for getting a color's blue channel.
+ * [`color.hue()`](#hue) for getting a color's hue.
+ * [`color.saturation()`](#saturation) for getting a color's saturation.
+ * [`color.lightness()`](#lightness) for getting a color's lightness.
+
+ <% example(autogen_css: false) do %>
+ @debug color.alpha(#e1d7d2); // 1
+ @debug color.opacity(rgb(210, 225, 221, 0.4)); // 0.4
+ @debug alpha(opacity=20); // alpha(opacity=20)
+ ===
+ @debug color.alpha(#e1d7d2) // 1
+ @debug color.opacity(rgb(210, 225, 221, 0.4)) // 0.4
+ @debug alpha(opacity=20) // alpha(opacity=20)
+ <% end %>
+<% end %>
+
+
+<% function 'color.blue($color)', 'blue($color)', returns: 'number' do %>
+ Returns the blue channel of `$color` as a number between 0 and 255.
+
+ See also:
+
+ * [`color.red()`](#red) for getting a color's red channel.
+ * [`color.green()`](#green) for getting a color's green channel.
+ * [`color.hue()`](#hue) for getting a color's hue.
+ * [`color.saturation()`](#saturation) for getting a color's saturation.
+ * [`color.lightness()`](#lightness) for getting a color's lightness.
+ * [`color.alpha()`](#alpha) for getting a color's alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug color.blue(#e1d7d2); // 210
+ @debug color.blue(white); // 255
+ @debug color.blue(black); // 0
+ ===
+ @debug color.blue(#e1d7d2) // 210
+ @debug color.blue(white) // 255
+ @debug color.blue(black) // 0
+ <% end %>
+<% end %>
+
+
+<% function <
+ Sets one or more properties of a color to new values.
+
+ Uses the value passed for each keyword argument in place of the corresponding
+ property of the color, and returns the changed color. It's an error to specify
+ an RGB property (`$red`, `$green`, and/or `$blue`) at the same time as an HSL
+ property (`$hue`, `$saturation`, and/or `$lightness`).
+
+ All optional arguments must be numbers. The `$red`, `$green`, and `$blue`
+ arguments must be [unitless][] and between 0 and 255 (inclusive). The `$hue`
+ argument must have either the unit `deg` or no unit. The `$saturation` and
+ `$lightness` arguments must be between `0%` and `100%` (inclusive), and may be
+ unitless. The `$alpha` argument must be unitless and between -1 and 1
+ (inclusive).
+
+ [unitless]: ../values/numbers#units
+
+ See also:
+
+ * [`color.scale()`](#scale) for fluidly scaling a color's properties.
+ * [`color.adjust()`](#adjust) for adjusting a color's properties by fixed
+ amounts.
+
+ <% example(autogen_css: false) do %>
+ @debug color.change(#6b717f, $red: 100); // #64717f
+ @debug color.change(#d2e1dd, $red: 100, $blue: 50); // #64e132
+ @debug color.change(#998099, $lightness: 30%, $alpha: 0.5); // rgba(85, 68, 85, 0.5)
+ ===
+ @debug color.change(#6b717f, $red: 100) // #64717f
+ @debug color.change(#d2e1dd, $red: 100, $blue: 50) // #64e132
+ @debug color.change(#998099, $lightness: 30%, $alpha: 0.5) // rgba(85, 68, 85, 0.5)
+ <% end %>
+<% end %>
+
+
+<% function 'color.complement($color)',
+ 'complement($color)',
+ returns: 'color' do %>
+ Returns the RGB [complement][] of `$color`.
+
+ This is identical to [`color.adjust($color, $hue: 180deg)`](#adjust).
+
+ [complement]: https://en.wikipedia.org/wiki/Complementary_colors
+
+ <% example(autogen_css: false) do %>
+ // Hue 222deg becomes 42deg.
+ @debug color.complement(#6b717f); // #7f796b
+
+ // Hue 164deg becomes 344deg.
+ @debug color.complement(#d2e1dd); // #e1d2d6
+
+ // Hue 210deg becomes 30deg.
+ @debug color.complement(#036); // #663300
+ ===
+ // Hue 222deg becomes 42deg.
+ @debug color.complement(#6b717f) // #7f796b
+
+ // Hue 164deg becomes 344deg.
+ @debug color.complement(#d2e1dd) // #e1d2d6
+
+ // Hue 210deg becomes 30deg.
+ @debug color.complement(#036) // #663300
+ <% end %>
+<% end %>
+
+
+<% function 'darken($color, $amount)', returns: 'color' do %>
+ Makes `$color` darker.
+
+ The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases
+ the HSL lightness of `$color` by that amount.
+
+ <% heads_up do %>
+ The `darken()` function decreases lightness by a fixed amount, which is often
+ not the desired effect. To make a color a certain percentage darker than it was
+ before, use [`color.scale()`](#scale) instead.
+
+ Because `darken()` is usually not the best way to make a color darker, it's
+ not included directly in the new module system. However, if you have to
+ preserve the existing behavior, `darken($color, $amount)` can be written
+ [`color.adjust($color, $lightness: -$amount)`](#adjust).
+
+ <% example(autogen_css: false) do %>
+ // #036 has lightness 20%, so when darken() subtracts 30% it just returns black.
+ @debug darken(#036, 30%); // black
+
+ // scale() instead makes it 30% darker than it was originally.
+ @debug color.scale(#036, $lightness: -30%); // #002447
+ ===
+ // #036 has lightness 20%, so when darken() subtracts 30% it just returns black.
+ @debug darken(#036, 30%) // black
+
+ // scale() instead makes it 30% darker than it was originally.
+ @debug color.scale(#036, $lightness: -30%) // #002447
+ <% end %>
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ // Lightness 92% becomes 72%.
+ @debug darken(#b37399, 20%); // #7c4465
+
+ // Lightness 85% becomes 45%.
+ @debug darken(#f2ece4, 40%); // #b08b5a
+
+ // Lightness 20% becomes 0%.
+ @debug darken(#036, 30%); // black
+ ===
+ // Lightness 92% becomes 72%.
+ @debug darken(#b37399, 20%) // #7c4465
+
+ // Lightness 85% becomes 45%.
+ @debug darken(#f2ece4, 40%) // #b08b5a
+
+ // Lightness 20% becomes 0%.
+ @debug darken(#036, 30%) // black
+ <% end %>
+<% end %>
+
+
+<% function 'desaturate($color, $amount)', returns: 'color' do %>
+ Makes `$color` less saturated.
+
+ The `$amount` must be a number between `0%` and `100%` (inclusive). Decreases
+ the HSL saturation of `$color` by that amount.
+
+ <% heads_up do %>
+ The `desaturate()` function decreases saturation by a fixed amount, which is
+ often not the desired effect. To make a color a certain percentage less
+ saturated than it was before, use [`color.scale()`](#scale) instead.
+
+ Because `desaturate()` is usually not the best way to make a color less
+ saturated, it's not included directly in the new module system. However, if
+ you have to preserve the existing behavior, `desaturate($color, $amount)`
+ can be written [`color.adjust($color, $saturation: -$amount)`](#adjust).
+
+ <% example(autogen_css: false) do %>
+ // #d2e1dd has saturation 20%, so when desaturate() subtracts 30% it just
+ // returns gray.
+ @debug desaturate(#d2e1dd, 30%); // #dadada
+
+ // scale() instead makes it 30% less saturated than it was originally.
+ @debug color.scale(#6b717f, $saturation: -30%); // #6e727c
+ ===
+ // #6b717f has saturation 20%, so when desaturate() subtracts 30% it just
+ // returns gray.
+ @debug desaturate(#d2e1dd, 30%) // #dadada
+
+ // scale() instead makes it 30% less saturated than it was originally.
+ @debug color.scale(#6b717f, $saturation: -30%) // #6e727c
+ <% end %>
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ // Saturation 100% becomes 80%.
+ @debug desaturate(#036, 20%); // #0a335c
+
+ // Saturation 35% becomes 15%.
+ @debug desaturate(#f2ece4, 20%); // #eeebe8
+
+ // Saturation 20% becomes 0%.
+ @debug desaturate(#d2e1dd, 30%); // #dadada
+ ===
+ // Saturation 100% becomes 80%.
+ @debug desaturate(#036, 20%) // #0a335c
+
+ // Saturation 35% becomes 15%.
+ @debug desaturate(#f2ece4, 20%) // #eeebe8
+
+ // Saturation 20% becomes 0%.
+ @debug desaturate(#d2e1dd, 30%) // #dadada
+ <% end %>
+<% end %>
+
+
+<% function 'color.grayscale($color)',
+ 'grayscale($color)',
+ returns: 'color' do %>
+ Returns a gray color with the same lightness as `$color`.
+
+ This is identical to [`color.change($color, $saturation: 0%)`](#change).
+
+ <% example(autogen_css: false) do %>
+ @debug color.grayscale(#6b717f); // #757575
+ @debug color.grayscale(#d2e1dd); // #dadada
+ @debug color.grayscale(#036); // #333333
+ ===
+ @debug color.grayscale(#6b717f) // #757575
+ @debug color.grayscale(#d2e1dd) // #dadada
+ @debug color.grayscale(#036) // #333333
+ <% end %>
+<% end %>
+
+
+<% function 'color.green($color)', 'green($color)', returns: 'number' do %>
+ Returns the green channel of `$color` as a number between 0 and 255.
+
+ See also:
+
+ * [`color.red()`](#red) for getting a color's red channel.
+ * [`color.blue()`](#blue) for getting a color's blue channel.
+ * [`color.hue()`](#hue) for getting a color's hue.
+ * [`color.saturation()`](#saturation) for getting a color's saturation.
+ * [`color.lightness()`](#lightness) for getting a color's lightness.
+ * [`color.alpha()`](#alpha) for getting a color's alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug color.green(#e1d7d2); // 215
+ @debug color.green(white); // 255
+ @debug color.green(black); // 0
+ ===
+ @debug color.green(#e1d7d2) // 215
+ @debug color.green(white) // 255
+ @debug color.green(black) // 0
+ <% end %>
+<% end %>
+
+
+<% function 'color.hue($color)', 'hue($color)', returns: 'number' do %>
+ Returns the hue of `$color` as a number between `0deg` and `255deg`.
+
+ See also:
+
+ * [`color.red()`](#red) for getting a color's red channel.
+ * [`color.green()`](#green) for getting a color's green channel.
+ * [`color.blue()`](#blue) for getting a color's blue channel.
+ * [`color.saturation()`](#saturation) for getting a color's saturation.
+ * [`color.lightness()`](#lightness) for getting a color's lightness.
+ * [`color.alpha()`](#alpha) for getting a color's alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug color.hue(#e1d7d2); // 20deg
+ @debug color.hue(#f2ece4); // 34.2857142857deg
+ @debug color.hue(#dadbdf); // 228deg
+ ===
+ @debug color.hue(#e1d7d2) // 20deg
+ @debug color.hue(#f2ece4) // 34.2857142857deg
+ @debug color.hue(#dadbdf) // 228deg
+ <% end %>
+<% end %>
+
+
+<% function 'color.ie-hex-str($color)',
+ 'ie-hex-str($color)',
+ returns: 'unquoted string' do %>
+ Returns an unquoted string that represents `$color` in the `#AARRGGBB` format
+ expected by Internet Explorer's [`-ms-filter`][] property.
+
+ [`-ms-filter`]: https://developer.mozilla.org/en-US/docs/Web/CSS/-ms-filter
+
+ <% example(autogen_css: false) do %>
+ @debug color.ie-hex-str(#b37399); // #FFB37399
+ @debug color.ie-hex-str(#808c99); // #FF808C99
+ @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4
+ ===
+ @debug color.ie-hex-str(#b37399); // #FFB37399
+ @debug color.ie-hex-str(#808c99); // #FF808C99
+ @debug color.ie-hex-str(rgba(242, 236, 228, 0.6)); // #99F2ECE4
+ <% end %>
+<% end %>
+
+
+<% function 'color.invert($color, $weight: 100%)',
+ 'invert($color, $weight: 100%)',
+ returns: 'color' do %>
+ Returns the inverse or [negative][] of `$color`.
+
+ [negative]: https://en.wikipedia.org/wiki/Negative_(photography)
+
+ The `$weight` must be a number between `0%` and `100%` (inclusive). A higher
+ weight means the result will be closer to the negative, and a lower weight means
+ it will be closer to `$color`. Weight `50%` will always produce `#808080`.
+
+ <% example(autogen_css: false) do %>
+ @debug color.invert(#b37399); // #4c8c66
+ @debug color.invert(black); // white
+ @debug color.invert(#550e0c, 20%); // #663b3a
+ ===
+ @debug color.invert(#b37399) // #4c8c66
+ @debug color.invert(black) // white
+ @debug color.invert(#550e0c, 20%) // #663b3a
+ <% end %>
+<% end %>
+
+
+<% function 'lighten($color, $amount)', returns: 'color' do %>
+ Makes `$color` lighter.
+
+ The `$amount` must be a number between `0%` and `100%` (inclusive). Increases
+ the HSL lightness of `$color` by that amount.
+
+ <% heads_up do %>
+ The `lighten()` function increases lightness by a fixed amount, which is often
+ not the desired effect. To make a color a certain percentage lighter than it was
+ before, use [`scale()`](#scale) instead.
+
+ Because `lighten()` is usually not the best way to make a color lighter,
+ it's not included directly in the new module system. However, if you have to
+ preserve the existing behavior, `lighten($color, $amount)` can be written
+ [`adjust($color, $lightness: $amount)`](#adjust).
+
+ <% example(autogen_css: false) do %>
+ // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white.
+ @debug lighten(#e1d7d2, 30%); // white
+
+ // scale() instead makes it 30% lighter than it was originally.
+ @debug color.scale(#e1d7d2, $lightness: 30%); // #eae3e0
+ ===
+ // #e1d7d2 has lightness 85%, so when lighten() adds 30% it just returns white.
+ @debug lighten(#e1d7d2, 30%) // white
+
+ // scale() instead makes it 30% lighter than it was originally.
+ @debug color.scale(#e1d7d2, $lightness: 30%) // #eae3e0
+ <% end %>
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ // Lightness 46% becomes 66%.
+ @debug lighten(#6b717f, 20%); // #a1a5af
+
+ // Lightness 20% becomes 80%.
+ @debug lighten(#036, 60%); // #99ccff
+
+ // Lightness 85% becomes 100%.
+ @debug lighten(#e1d7d2, 30%); // white
+ ===
+ // Lightness 46% becomes 66%.
+ @debug lighten(#6b717f, 20%) // #a1a5af
+
+ // Lightness 20% becomes 80%.
+ @debug lighten(#036, 60%) // #99ccff
+
+ // Lightness 85% becomes 100%.
+ @debug lighten(#e1d7d2, 30%) // white
+ <% end %>
+<% end %>
+
+
+<% function 'color.lightness($color)',
+ 'lightness($color)',
+ returns: 'number' do %>
+ Returns the HSL lightness of `$color` as a number between `0%` and `100%`.
+
+ See also:
+
+ * [`color.red()`](#red) for getting a color's red channel.
+ * [`color.green()`](#green) for getting a color's green channel.
+ * [`color.blue()`](#blue) for getting a color's blue channel.
+ * [`color.hue()`](#hue) for getting a color's hue.
+ * [`color.saturation()`](#saturation) for getting a color's saturation.
+ * [`color.alpha()`](#alpha) for getting a color's alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug color.lightness(#e1d7d2); // 85.2941176471%
+ @debug color.lightness(#f2ece4); // 92.1568627451%
+ @debug color.lightness(#dadbdf); // 86.4705882353%
+ ===
+ @debug color.lightness(#e1d7d2) // 85.2941176471%
+ @debug color.lightness(#f2ece4) // 92.1568627451%
+ @debug color.lightness(#dadbdf) // 86.4705882353%
+ <% end %>
+<% end %>
+
+
+<% function 'color.mix($color1, $color2, $weight: 50%)',
+ 'mix($color1, $color2, $weight: 50%)',
+ returns: 'color' do %>
+ Returns a number that's a mixture of `$color1` and `$color2`.
+
+ Both the `$weight` and the relative opacity of each color determines how much of
+ each color is in the result. The `$weight` must be a number between `0%` and
+ `100%` (inclusive). A larger weight indicates that more of `$color1` should be
+ used, and a smaller weight indicates that more of `$color2` should be used.
+
+ <% example(autogen_css: false) do %>
+ @debug color.mix(#036, #d2e1dd); // #698aa2
+ @debug color.mix(#036, #d2e1dd, 75%); // #355f84
+ @debug color.mix(#036, #d2e1dd, 25%); // #9eb6bf
+ @debug color.mix(rgba(242, 236, 228, 0.5), #6b717f); // rgba(141, 144, 152, 0.75)
+ ===
+ @debug color.mix(#036, #d2e1dd) // #698aa2
+ @debug color.mix(#036, #d2e1dd, 75%) // #355f84
+ @debug color.mix(#036, #d2e1dd, 25%) // #9eb6bf
+ @debug color.mix(rgba(242, 236, 228, 0.5), #6b717f) // rgba(141, 144, 152, 0.75)
+ <% end %>
+<% end %>
+
+
+<% function 'opacify($color, $amount)', 'fade-in($color, $amount)', returns: 'color' do %>
+ Makes `$color` more opaque.
+
+ The `$amount` must be a number between `0` and `1` (inclusive). Increases the
+ alpha channel of `$color` by that amount.
+
+ <% heads_up do %>
+ The `opacify()` function increases the alpha channel by a fixed amount, which is often
+ not the desired effect. To make a color a certain percentage more opaque than it was
+ before, use [`scale()`](#scale) instead.
+
+ Because `opacify()` is usually not the best way to make a color more opaque,
+ it's not included directly in the new module system. However, if you have to
+ preserve the existing behavior, `opacify($color, $amount)` can be written
+ [`adjust($color, $alpha: -$amount)`](#adjust).
+
+ <% example(autogen_css: false) do %>
+ // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully
+ // opaque color.
+ @debug opacify(rgba(#036, 0.7), 0.3); // #036
+
+ // scale() instead makes it 30% more opaque than it was originally.
+ @debug color.scale(rgba(#036, 0.7), $alpha: 30%); // rgba(0, 51, 102, 0.79)
+ ===
+ // rgba(#036, 0.7) has alpha 0.7, so when opacify() adds 0.3 it returns a fully
+ // opaque color.
+ @debug opacify(rgba(#036, 0.7), 0.3) // #036
+
+ // scale() instead makes it 30% more opaque than it was originally.
+ @debug color.scale(rgba(#036, 0.7), $alpha: 30%) // rgba(0, 51, 102, 0.79)
+ <% end %>
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug opacify(rgba(#6b717f, 0.5), 0.2); // rgba(107, 113, 127, 0.7)
+ @debug fade-in(rgba(#e1d7d2, 0.5), 0.4); // rgba(225, 215, 210, 0.9)
+ @debug opacify(rgba(#036, 0.7), 0.3); // #036
+ ===
+ @debug opacify(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.7)
+ @debug fade-in(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.9)
+ @debug opacify(rgba(#036, 0.7), 0.3) // #036
+ <% end %>
+<% end %>
+
+
+<% function 'color.red($color)', 'red($color)', returns: 'number' do %>
+ Returns the red channel of `$color` as a number between 0 and 255.
+
+ See also:
+
+ * [`color.green()`](#green) for getting a color's green channel.
+ * [`color.blue()`](#blue) for getting a color's blue channel.
+ * [`color.hue()`](#hue) for getting a color's hue.
+ * [`color.saturation()`](#saturation) for getting a color's saturation.
+ * [`color.lightness()`](#lightness) for getting a color's lightness.
+ * [`color.alpha()`](#alpha) for getting a color's alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug color.red(#e1d7d2); // 225
+ @debug color.red(white); // 255
+ @debug color.red(black); // 0
+ ===
+ @debug color.red(#e1d7d2) // 225
+ @debug color.red(white) // 255
+ @debug color.red(black) // 0
+ <% end %>
+<% end %>
+
+
+<% function 'saturate($color, $amount)', 'saturate($color, $amount)', returns: 'color' do %>
+ Makes `$color` more saturated.
+
+ The `$amount` must be a number between `0%` and `100%` (inclusive). Increases
+ the HSL saturation of `$color` by that amount.
+
+ <% heads_up do %>
+ The `saturate()` function increases saturation by a fixed amount, which is often
+ not the desired effect. To make a color a certain percentage more saturated than
+ it was before, use [`scale()`](#scale) instead.
+
+ Because `saturate()` is usually not the best way to make a color more
+ saturated, it's not included directly in the new module system. However, if
+ you have to preserve the existing behavior, `saturate($color, $amount)` can
+ be written [`adjust($color, $saturation: $amount)`](#adjust).
+
+ <% example(autogen_css: false) do %>
+ // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes
+ // fully saturated.
+ @debug saturate(#0e4982, 30%); // #004990
+
+ // scale() instead makes it 30% more saturated than it was originally.
+ @debug color.scale(#0e4982, $saturation: 30%); // #0a4986
+ ===
+ // #0e4982 has saturation 80%, so when saturate() adds 30% it just becomes
+ // fully saturated.
+ @debug saturate(#0e4982, 30%) // #004990
+
+ // scale() instead makes it 30% more saturated than it was originally.
+ @debug color.scale(#0e4982, $saturation: 30%) // #0a4986
+ <% end %>
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ // Saturation 50% becomes 70%.
+ @debug saturate(#c69, 20%); // #e05299
+
+ // Saturation 35% becomes 85%.
+ @debug desaturate(#f2ece4, 50%); // #ebebeb
+
+ // Saturation 80% becomes 100%.
+ @debug saturate(#0e4982, 30%) // #004990
+ ===
+ // Saturation 50% becomes 70%.
+ @debug saturate(#c69, 20%); // #e05299
+
+ // Saturation 35% becomes 85%.
+ @debug desaturate(#f2ece4, 50%); // #ebebeb
+
+ // Saturation 80% becomes 100%.
+ @debug saturate(#0e4982, 30%) // #004990
+ <% end %>
+<% end %>
+
+
+<% function 'color.saturation($color)',
+ 'saturation($color)',
+ returns: 'number' do %>
+ Returns the HSL saturation of `$color` as a number between `0%` and `100%`.
+
+ See also:
+
+ * [`color.red()`](#red) for getting a color's red channel.
+ * [`color.green()`](#green) for getting a color's green channel.
+ * [`color.blue()`](#blue) for getting a color's blue channel.
+ * [`color.hue()`](#hue) for getting a color's hue.
+ * [`color.lightness()`](#lightness) for getting a color's lightness.
+ * [`color.alpha()`](#alpha) for getting a color's alpha channel.
+
+ <% example(autogen_css: false) do %>
+ @debug color.saturation(#e1d7d2); // 20%
+ @debug color.saturation(#f2ece4); // 30%
+ @debug color.saturation(#dadbdf); // 7.2463768116%
+ ===
+ @debug color.saturation(#e1d7d2) // 20%
+ @debug color.saturation(#f2ece4) // 30%
+ @debug color.saturation(#dadbdf) // 7.2463768116%
+ <% end %>
+<% end %>
+
+
+<% function <
+ Fluidly scales one or more properties of `$color`.
+
+ Each keyword argument must be a number between `-100%` and `100%` (inclusive).
+ This indicates how far the corresponding property should be moved from its
+ original position towards the maximum (if the argument is positive) or the
+ minimum (if the argument is negative). This means that, for example,
+ `$lightness: 50%` will make all colors `50%` closer to maximum lightness
+ without making them fully white.
+
+ It's an error to specify an RGB property (`$red`, `$green`, and/or `$blue`) at
+ the same time as an HSL property (`$saturation`, and/or `$lightness`).
+
+ See also:
+
+ * [`color.adjust()`](#adjust) for changing a color's properties by fixed
+ amounts.
+ * [`color.change()`](#change) for setting a color's properties.
+
+ <% example(autogen_css: false) do %>
+ @debug color.scale(#6b717f, $red: 15%); // #81717f
+ @debug color.scale(#d2e1dd, $lightness: -10%, $saturation: 10%); // #b3d4cb
+ @debug color.scale(#998099, $alpha: -40%); // rgba(153, 128, 153, 0.6)
+ ===
+ @debug color.scale(#6b717f, $red: 15%) // #81717f
+ @debug color.scale(#d2e1dd, $lightness: -10%, $saturation: 10%) // #b3d4cb
+ @debug color.scale(#998099, $alpha: -40%) // rgba(153, 128, 153, 0.6)
+ <% end %>
+<% end %>
+
+
+<% function 'transparentize($color, $amount)', 'fade-out($color, $amount)', returns: 'color' do %>
+ Makes `$color` more transparent.
+
+ The `$amount` must be a number between `0` and `1` (inclusive). Decreases the
+ alpha channel of `$color` by that amount.
+
+ <% heads_up do %>
+ The `transparentize()` function decreases the alpha channel by a fixed amount,
+ which is often not the desired effect. To make a color a certain percentage more
+ transparent than it was before, use [`color.scale()`](#scale) instead.
+
+ Because `transparentize()` is usually not the best way to make a color more
+ transparent, it's not included directly in the new module system. However,
+ if you have to preserve the existing behavior,
+ `transparentize($color, $amount)` can be written
+ [`color.adjust($color, $alpha: -$amount)`](#adjust).
+
+ <% example(autogen_css: false) do %>
+ // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it
+ // returns a fully transparent color.
+ @debug transparentize(rgba(#036, 0.3), 0.3); // rgba(0, 51, 102, 0)
+
+ // scale() instead makes it 30% more transparent than it was originally.
+ @debug color.scale(rgba(#036, 0.3), $alpha: -30%); // rgba(0, 51, 102, 0.21)
+ ===
+ // rgba(#036, 0.3) has alpha 0.3, so when transparentize() subtracts 0.3 it
+ // returns a fully transparent color.
+ @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0)
+
+ // scale() instead makes it 30% more transparent than it was originally.
+ @debug color.scale(rgba(#036, 0.3), $alpha: -30%) // rgba(0, 51, 102, 0.21)
+ <% end %>
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3)
+ @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1)
+ @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0)
+ ===
+ @debug transparentize(rgba(#6b717f, 0.5), 0.2) // rgba(107, 113, 127, 0.3)
+ @debug fade-out(rgba(#e1d7d2, 0.5), 0.4) // rgba(225, 215, 210, 0.1)
+ @debug transparentize(rgba(#036, 0.3), 0.3) // rgba(0, 51, 102, 0)
+ <% end %>
+<% end %>
diff --git a/source/documentation/modules/list.html.md.erb b/source/documentation/modules/list.html.md.erb
new file mode 100644
index 000000000..d63cc0229
--- /dev/null
+++ b/source/documentation/modules/list.html.md.erb
@@ -0,0 +1,218 @@
+---
+title: sass:list
+---
+
+<%= partial '../snippets/built-in-module-status' %>
+
+<% fun_fact do %>
+ In Sass, every [map][] counts as a list that contains a two-element list for
+ each key/value pair. For example, `(1: 2, 3: 4)` counts as `(1 2, 3 4)`. So
+ all these functions work for maps as well!
+
+ [map]: ../values/maps
+
+ Individual values also count as lists. All these functions treat `1px` as a
+ list that contains the value `1px`.
+<% end %>
+
+
+<% function 'list.append($list, $val, $separator: auto)',
+ 'append($list, $val, $separator: auto)',
+ returns: 'list' do %>
+ Returns a copy of `$list` with `$val` added to the end.
+
+ If `$separator` is `comma`, the returned list is comma-separted. If it's
+ `space`, the returned list is space-separated. If it's `auto` (the default), the
+ returned list will use the same separator as `$list` (or `space` if `$list`
+ doesn't have a separator). Other values aren't allowed.
+
+ [separator]: ../values/lists
+
+ Note that unlike [`list.join()`](#join), if `$val` is a list it's nested
+ within the returned list rather than having all its elements added to the
+ returned list.
+
+ <% example(autogen_css: false) do %>
+ @debug list.append(10px 20px, 30px); // 10px 20px 30px
+ @debug list.append((blue, red), green); // blue, red, green
+ @debug list.append(10px 20px, 30px 40px); // 10px 20px (30px 40px)
+ @debug list.append(10px, 20px, $separator: comma); // 10px, 20px
+ @debug list.append((blue, red), green, $separator: space); // blue red green
+ ===
+ @debug list.append(10px 20px, 30px) // 10px 20px 30px
+ @debug list.append((blue, red), green) // blue, red, green
+ @debug list.append(10px 20px, 30px 40px) // 10px 20px (30px 40px)
+ @debug list.append(10px, 20px, $separator: comma) // 10px, 20px
+ @debug list.append((blue, red), green, $separator: space) // blue red green
+ <% end %>
+<% end %>
+
+
+<% function 'list.index($list, $value)',
+ 'index($list, $value)',
+ returns: 'number | null' do %>
+ Returns the [index][] of `$value` in `$list`.
+
+ [index]: ../values/lists#indexes
+
+ If `$value` doesn't appear in `$list`, this returns [`null`][]. If `$value`
+ appears multiple times in `$list`, this returns the index of its first
+ appearance.
+
+ [`null`]: ../values/null
+
+ <%= partial 'code-snippets/example-list-index' %>
+<% end %>
+
+
+<% function 'list.is-bracketed($list)',
+ 'is-bracketed($list)',
+ returns: 'boolean' do %>
+ Returns whether `$list` has square brackets.
+
+ <% example(autogen_css: false) do %>
+ @debug list.is-bracketed(1px 2px 3px); // false
+ @debug list.is-bracketed([1px, 2px, 3px]); // true
+ ===
+ @debug list.is-bracketed(1px 2px 3px) // false
+ @debug list.is-bracketed([1px, 2px, 3px]) // true
+ <% end %>
+<% end %>
+
+
+<% function 'list.join($list1, $list2, $separator: auto, $bracketed: auto)',
+ 'join($list1, $list2, $separator: auto, $bracketed: auto)',
+ returns: 'list' do %>
+ Returns a new list containing the elements of `$list1` followed by the elements
+ of `$list2`.
+
+ <% heads_up do %>
+ Because individual values count as single-element lists, it's possible to
+ use `list.join()` to add a value to the end of a list. However, *this is not
+ recommended*, since if that value is a list it will be concatenated, which
+ is probably not what you're expecting.
+
+ Use [`list.append()`](#append) instead to add a single value to a list. Only
+ use `list.join()` to combine two lists together into one.
+ <% end %>
+
+ If `$separator` is `comma`, the returned list is comma-separted. If it's
+ `space`, the returned list is space-separated. If it's `auto` (the default),
+ the returned list will use the same separator as `$list1` if it has a
+ separator, or else `$list2` if it has a separator, or else `space`. Other
+ values aren't allowed.
+
+ If `$bracketed` is `true`, the returned list has square brackets. If it's
+ `false`, the returned list has no brackets. If it's `auto` (the default), the
+ returned list will be bracketed if `$list1` is. Other values aren't allowed.
+
+ <% example(autogen_css: false) do %>
+ @debug list.join(10px 20px, 30px 40px); // 10px 20px 30px 40px
+ @debug list.join((blue, red), (#abc, #def)); // blue, red, #abc, #def
+ @debug list.join(10px, 20px); // 10px 20px
+ @debug list.join(10px, 20px, $separator: comma); // 10px, 20px
+ @debug list.join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def
+ @debug list.join([10px], 20px); // [10px 20px]
+ @debug list.join(10px, 20px, $bracketed: true); // [10px 20px]
+ ===
+ @debug list.join(10px 20px, 30px 40px) // 10px 20px 30px 40px
+ @debug list.join((blue, red), (#abc, #def)) // blue, red, #abc, #def
+ @debug list.join(10px, 20px) // 10px 20px
+ @debug list.join(10px, 20px, comma) // 10px, 20px
+ @debug list.join((blue, red), (#abc, #def), space) // blue red #abc #def
+ @debug list.join([10px], 20px) // [10px 20px]
+ @debug list.join(10px, 20px, $bracketed: true) // [10px 20px]
+ <% end %>
+<% end %>
+
+
+<% function 'list.length($list)', 'length($list)', returns: 'number' do %>
+ Returns the length of `$list`.
+
+ This can also return the number of pairs in a map.
+
+ <% example(autogen_css: false) do %>
+ @debug list.length(10px); // 1
+ @debug list.length(10px 20px 30px); // 3
+ @debug list.length((width: 10px, height: 20px)); // 2
+ ===
+ @debug list.length(10px) // 1
+ @debug list.length(10px 20px 30px) // 3
+ @debug list.length((width: 10px, height: 20px)) // 2
+ <% end %>
+<% end %>
+
+
+<% function 'list.separator($list)',
+ 'list-separator($list)',
+ returns: 'unquoted string' do %>
+ Returns the name of the separator used by `$list`, either `space` or `comma`.
+
+ If `$list` doesn't have a separator, returns `space`.
+
+ <% example(autogen_css: false) do %>
+ @debug list.separator(1px 2px 3px); // space
+ @debug list.separator(1px, 2px, 3px); // comma
+ @debug list.separator('Helvetica'); // space
+ @debug list.separator(()); // space
+ ===
+ @debug list.separator(1px 2px 3px) // space
+ @debug list.separator(1px, 2px, 3px) // comma
+ @debug list.separator('Helvetica') // space
+ @debug list.separator(()) // space
+ <% end %>
+<% end %>
+
+
+<% function 'list.nth($list, $n)', 'nth($list, $n)' do %>
+ Returns the element of `$list` at [index][] `$n`.
+
+ [index]: ../values/lists#indexes
+
+ If `$n` is negative, it counts from the end of `$list`. Throws an error if
+ there is no element at index `$n`.
+
+ <%= partial 'code-snippets/example-list-nth' %>
+<% end %>
+
+
+<% function 'list.set-nth($list, $n, $value)',
+ 'set-nth($list, $n, $value)',
+ returns: 'list' do %>
+ Returns a copy of `$list` with the element at [index][] `$n` replaced with
+ `$value`.
+
+ [index]: ../values/lists#indexes
+
+ If `$n` is negative, it counts from the end of `$list`. Throws an error if
+ there is no existing element at index `$n`.
+
+ <% example(autogen_css: false) do %>
+ @debug list.set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px
+ @debug list.set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em
+ @debug list.set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto
+ ===
+ @debug list.set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px
+ @debug list.set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em
+ @debug list.set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto
+ <% end %>
+<% end %>
+
+
+<% function 'list.zip($lists...)', 'zip($lists...)', returns: 'list' do %>
+ Combines every list in `$lists` into a single list of sub-lists.
+
+ Each element in the returned list contains all the elements at that position
+ in `$lists`. The returned list is as long as the shortest list in `$lists`.
+
+ The returned list is always comma-separated and the sub-lists are always
+ space-separated.
+
+ <% example(autogen_css: false) do %>
+ @debug list.zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long
+ @debug list.zip(10px 50px 100px, short mid); // 10px short, 50px mid
+ ===
+ @debug list.zip(10px 50px 100px, short mid long) // 10px short, 50px mid, 100px long
+ @debug list.zip(10px 50px 100px, short mid) // 10px short, 50px mid
+ <% end %>
+<% end %>
diff --git a/source/documentation/functions/map.html.md.erb b/source/documentation/modules/map.html.md.erb
similarity index 56%
rename from source/documentation/functions/map.html.md.erb
rename to source/documentation/modules/map.html.md.erb
index d3e86981d..d40c921bd 100644
--- a/source/documentation/functions/map.html.md.erb
+++ b/source/documentation/modules/map.html.md.erb
@@ -1,22 +1,10 @@
---
-title: Map Functions
+title: sass:map
---
-<% function 'keywords($args)', returns: 'map' do %>
- Returns the keywords passed to a mixin or function that takes [arbitrary
- arguments][]. The `$args` argument must be an [argument list][].
+<%= partial '../snippets/built-in-module-status' %>
- [arbitrary arguments]: ../at-rules/mixin#taking-arbitrary-arguments
- [argument list]: ../values/lists#argument-lists
-
- The keywords are returned as a map from argument names as unquoted strings (not
- including `$`) to the values of those arguments.
-
- <%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %>
-<% end %>
-
-
-<% function 'map-get($map, $key)' do %>
+<% function 'map.get($map, $key)', 'map-get($map, $key)' do %>
Returns the value in `$map` associated with `$key`.
If `$map` doesn't have a value associated with `$key`, returns [`null`][].
@@ -27,39 +15,43 @@ title: Map Functions
<% end %>
-<% function 'map-has-key($map, $key)', returns: 'boolean' do %>
+<% function 'map.has-key($map, $key)',
+ 'map-has-key($map, $key)',
+ returns: 'boolean' do %>
Returns whether `$map` contains a value associated with `$key`.
<% example(autogen_css: false) do %>
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-has-key($font-weights, "regular"); // true
- @debug map-has-key($font-weights, "bolder"); // false
+ @debug map.has-key($font-weights, "regular"); // true
+ @debug map.has-key($font-weights, "bolder"); // false
===
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-has-key($font-weights, "regular") // true
- @debug map-has-key($font-weights, "bolder") // false
+ @debug map.has-key($font-weights, "regular") // true
+ @debug map.has-key($font-weights, "bolder") // false
<% end %>
<% end %>
-<% function 'map-keys($map)', returns: 'list' do %>
+<% function 'map.keys($map)', 'map-keys($map)', returns: 'list' do %>
Returns a comma-separated list of all the keys in `$map`.
<% example(autogen_css: false) do %>
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-keys($font-weights); // "regular", "medium", "bold"
+ @debug map.keys($font-weights); // "regular", "medium", "bold"
===
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-keys($font-weights) // "regular", "medium", "bold"
+ @debug map.keys($font-weights) // "regular", "medium", "bold"
<% end %>
<% end %>
-<% function 'map-merge($map1, $map2)', returns: 'map' do %>
+<% function 'map.merge($map1, $map2)',
+ 'map-merge($map1, $map2)',
+ returns: 'map' do %>
Returns a new map with all the keys and values from both `$map1` and `$map2`.
This can also be used to add a new value or overrwrite a value in `$map1`, by
@@ -74,7 +66,7 @@ title: Map Functions
$light-weights: ("lightest": 100, "light": 300);
$heavy-weights: ("medium": 500, "bold": 700);
- @debug map-merge($light-weights, $heavy-weights);
+ @debug map.merge($light-weights, $heavy-weights);
// (
// "lightest": 100,
// "light": 300,
@@ -82,18 +74,18 @@ title: Map Functions
// "bold": 700
// )
- // map-merge() can be used to add a single key/value pair to a map.
- @debug map-merge($light-weights, ("lighter": 200));
+ // map.merge() can be used to add a single key/value pair to a map.
+ @debug map.merge($light-weights, ("lighter": 200));
// ("lightest": 100, "light": 300, "lighter": 200)
// It can also be used to overwrite a value in a map.
- @debug map-merge($light-weights, ("light": 200));
+ @debug map.merge($light-weights, ("light": 200));
// ("lightest": 100, "light": 200)
===
$light-weights: ("lightest": 100, "light": 300)
$heavy-weights: ("medium": 500, "bold": 700)
- @debug map-merge($light-weights, $heavy-weights)
+ @debug map.merge($light-weights, $heavy-weights)
// (
// "lightest": 100,
// "light": 300,
@@ -101,18 +93,20 @@ title: Map Functions
// "bold": 700
// )
- // map-merge() can be used to add a single key/value pair to a map.
- @debug map-merge($light-weights, ("lighter": 200))
+ // map.merge() can be used to add a single key/value pair to a map.
+ @debug map.merge($light-weights, ("lighter": 200))
// ("lightest": 100, "light": 300, "lighter": 200)
// It can also be used to overwrite a value in a map.
- @debug map-merge($light-weights, ("light": 200))
+ @debug map.merge($light-weights, ("light": 200))
// ("lightest": 100, "light": 200)
<% end %>
<% end %>
-<% function 'map-remove($map, $keys...)', returns: 'map' do %>
+<% function 'map.remove($map, $keys...)',
+ 'map-remove($map, $keys...)',
+ returns: 'map' do %>
Returns a copy of `$map` without any values associated with `$keys`.
If a key in `$keys` doesn't have an associated value in `$map`, it's ignored.
@@ -120,31 +114,31 @@ title: Map Functions
<% example(autogen_css: false) do %>
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-remove($font-weights, "regular"); // ("medium": 500, "bold": 700)
- @debug map-remove($font-weights, "regular", "bold"); // ("medium": 500)
- @debug map-remove($font-weights, "bolder");
+ @debug map.remove($font-weights, "regular"); // ("medium": 500, "bold": 700)
+ @debug map.remove($font-weights, "regular", "bold"); // ("medium": 500)
+ @debug map.remove($font-weights, "bolder");
// ("regular": 400, "medium": 500, "bold": 700)
===
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-remove($font-weights, "regular") // ("medium": 500, "bold": 700)
- @debug map-remove($font-weights, "regular", "bold") // ("medium": 500)
- @debug map-remove($font-weights, "bolder")
+ @debug map.remove($font-weights, "regular") // ("medium": 500, "bold": 700)
+ @debug map.remove($font-weights, "regular", "bold") // ("medium": 500)
+ @debug map.remove($font-weights, "bolder")
// ("regular": 400, "medium": 500, "bold": 700)
<% end %>
<% end %>
-<% function 'map-values($map)', returns: 'list' do %>
+<% function 'map.values($map)', 'map-values($map)', returns: 'list' do %>
Returns a comma-separated list of all the values in `$map`.
<% example(autogen_css: false) do %>
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-values($font-weights); // 400, 500, 700
+ @debug map.values($font-weights); // 400, 500, 700
===
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-values($font-weights) // 400, 500, 700
+ @debug map.values($font-weights) // 400, 500, 700
<% end %>
<% end %>
diff --git a/source/documentation/modules/math.html.erb b/source/documentation/modules/math.html.erb
new file mode 100644
index 000000000..062890492
--- /dev/null
+++ b/source/documentation/modules/math.html.erb
@@ -0,0 +1,225 @@
+---
+title: sass:math
+---
+
+<%= partial '../snippets/built-in-module-status' %>
+
+<% function 'math.abs($number)', 'abs($number)', returns: 'number' do %>
+ Returns the [absolute value][] of `$number`. If `$number` is negative, this
+ returns `-$number`, and if `$number` is positive, it returns `$number` as-is.
+
+ [absolute value]: https://en.wikipedia.org/wiki/Absolute_value
+
+ <% example(autogen_css: false) do %>
+ @debug math.abs(10px); // 10px
+ @debug math.abs(-10px); // 10px
+ ===
+ @debug math.abs(10px) // 10px
+ @debug math.abs(-10px) // 10px
+ <% end %>
+<% end %>
+
+
+<% function 'math.ceil($number)', 'ceil($number)', returns: 'number' do %>
+ Rounds `$number` up to the next highest whole number.
+
+ <% example(autogen_css: false) do %>
+ @debug math.ceil(4); // 4
+ @debug math.ceil(4.2); // 5
+ @debug math.ceil(4.9); // 5
+ ===
+ @debug math.ceil(4) // 4
+ @debug math.ceil(4.2) // 5
+ @debug math.ceil(4.9) // 5
+ <% end %>
+<% end %>
+
+
+<% function 'math.compatible($number1, $number2)',
+ 'comparable($number1, $number2)',
+ returns: 'boolean' do %>
+ Returns whether `$number1` and `$number2` have compatible units.
+
+ If this returns `true`, `$number1` and `$number2` can safely be [added][],
+ [subtracted][], and [compared][]. Otherwise, doing so will produce errors.
+
+ [added]: ../operators/numeric
+ [subtracted]: ../operators/numeric
+ [compared]: ../operators/relational
+
+ <% heads_up do %>
+ The global name of this function
+ is comparable
, but when it was added to the
+ `sass:math` module the name was changed
+ to compatible
to more clearly convey what the
+ function does.
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug math.compatible(2px, 1px); // true
+ @debug math.compatible(100px, 3em); // false
+ @debug math.compatible(10cm, 3mm); // true
+ ===
+ @debug math.compatible(2px, 1px) // true
+ @debug math.compatible(100px, 3em) // false
+ @debug math.compatible(10cm, 3mm) // true
+ <% end %>
+<% end %>
+
+
+<% function 'math.floor($number)', 'floor($number)', returns: 'number' do %>
+ Rounds `$number` down to the next lowest whole number.
+
+ <% example(autogen_css: false) do %>
+ @debug math.floor(4); // 4
+ @debug math.floor(4.2); // 4
+ @debug math.floor(4.9); // 4
+ ===
+ @debug math.floor(4) // 4
+ @debug math.floor(4.2) // 4
+ @debug math.floor(4.9) // 4
+ <% end %>
+<% end %>
+
+
+<% function 'math.max($number...)', 'max($number...)', returns: 'number' do %>
+ Returns the highest of one or more numbers. A list of numbers can be passed
+ [using `...`][].
+
+ [using `...`]: ../at-rules/function#passing-arbitrary-arguments
+
+ <% example(autogen_css: false) do %>
+ @debug math.max(1px, 4px); // 4px
+
+ $widths: 50px, 30px, 100px;
+ @debug math.max($widths...); // 100px
+ ===
+ @debug math.max(1px, 4px) // 4px
+
+ $widths: 50px, 30px, 100px
+ @debug math.max($widths...) // 100px
+ <% end %>
+<% end %>
+
+
+<% function 'math.min($number...)', 'min($number...)', returns: 'number' do %>
+ Returns the lowest of one or more numbers. A list of numbers can be passed
+ [using `...`][].
+
+ [using `...`]: ../at-rules/function#passing-arbitrary-arguments
+
+ <% example(autogen_css: false) do %>
+ @debug math.min(1px, 4px); // 1px
+
+ $widths: 50px, 30px, 100px;
+ @debug math.min($widths...); // 30px
+ ===
+ @debug math.min(1px, 4px) // 1px
+
+ $widths: 50px, 30px, 100px
+ @debug math.min($widths...) // 30px
+ <% end %>
+<% end %>
+
+
+<% function 'math.percentage($number)',
+ 'percentage($number)',
+ returns: 'number' do %>
+ Converts a unitless `$number` (usually a decimal between 0 and 1) to a
+ percentage.
+
+ <% fun_fact do %>
+ This function is identical to `$number * 100%`.
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug math.percentage(0.2); // 20%
+ @debug math.percentage(100px / 50px); // 200%
+ ===
+ @debug math.percentage(0.2) // 20%
+ @debug math.percentage(100px / 50px) // 200%
+ <% end %>
+<% end %>
+
+
+<% function 'math.random($limit: null)',
+ 'random($limit: null)',
+ returns: 'number' do %>
+ If `$limit` is [`null`][], returns a random decimal number between 0 and 1.
+
+ [`null`]: ../values/null
+
+ <% example(autogen_css: false) do %>
+ @debug math.random(); // 0.2821251858
+ @debug math.random(); // 0.6221325814
+ ===
+ @debug math.random() // 0.2821251858
+ @debug math.random() // 0.6221325814
+ <% end %>
+
+ * * *
+
+ If `$limit` is a number greater than or equal to 1, returns a random whole
+ number between 1 and `$limit`.
+
+ <% example(autogen_css: false) do %>
+ @debug math.random(10); // 4
+ @debug math.random(10000); // 5373
+ ===
+ @debug math.random(10) // 4
+ @debug math.random(10000) // 5373
+ <% end %>
+<% end %>
+
+
+<% function 'math.round($number)', 'round($number)', returns: 'number' do %>
+ Rounds `$number` to the nearest whole number.
+
+ <% example(autogen_css: false) do %>
+ @debug math.round(4); // 4
+ @debug math.round(4.2); // 4
+ @debug math.round(4.9); // 5
+ ===
+ @debug math.round(4) // 4
+ @debug math.round(4.2) // 4
+ @debug math.round(4.9) // 5
+ <% end %>
+<% end %>
+
+
+<% function 'math.unit($number)',
+ 'unit($number)',
+ returns: 'quoted string' do %>
+ Returns a string representation of `$number`'s units.
+
+ <% heads_up do %>
+ This function is intended for debugging; its output format is not guaranteed
+ to be consistent across Sass versions or implementations.
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug math.unit(100); // ""
+ @debug math.unit(100px); // "px"
+ @debug math.unit(5px * 10px); // "px*px"
+ @debug math.unit(5px / 1s); // "px/s"
+ ===
+ @debug math.unit(100) // ""
+ @debug math.unit(100px) // "px"
+ @debug math.unit(5px * 10px) // "px*px"
+ @debug math.unit(5px / 1s) // "px/s"
+ <% end %>
+<% end %>
+
+<% function 'math.is-unitless($number)',
+ 'unitless($number)',
+ returns: 'boolean' do %>
+ Returns whether `$number` has no units.
+
+ <% example(autogen_css: false) do %>
+ @debug math.is-unitless(100); // true
+ @debug math.is-unitless(100px); // false
+ ===
+ @debug math.is-unitless(100) // true
+ @debug math.is-unitless(100px) // false
+ <% end %>
+<% end %>
diff --git a/source/documentation/modules/meta.html.md.erb b/source/documentation/modules/meta.html.md.erb
new file mode 100644
index 000000000..017d87dd3
--- /dev/null
+++ b/source/documentation/modules/meta.html.md.erb
@@ -0,0 +1,503 @@
+---
+title: sass:meta
+---
+
+<%= partial '../snippets/built-in-module-status' %>
+
+## Mixins
+
+<% function 'meta.load-css($url, $with: null)' do %>
+ <% impl_status dart: '(unreleased)', libsass: false, ruby: false do %>
+ Only Dart Sass currently supports this mixin.
+ <% end %>
+
+ Loads the [module][] at `$url` and includes its CSS as though it were written
+ as the contents of this mixin. The `$with` parameter provides
+ [configuration][] for the modules; if it's passed, it must be a map from
+ variable names (without `$`) to the values of those variables to use in the
+ loaded module.
+
+ [module]: ../at-rules/use
+ [configuration]: ../at-rules/use#configuring-modules
+
+ If `$url` is relative, it's interpreted as relative to the file in which
+ `meta.load-css()` is included.
+
+ **Like the [`@use` rule][]**:
+
+ [`@use` rule]: ../at-rules/use
+
+ * This will only evaluate the given module once, even if it's loaded multiple
+ times in different ways.
+
+ * This cannot provide configuration to a module that's already been loaded,
+ whether or not it was already loaded with configuration.
+
+ **Unlike the [`@use` rule][]**:
+
+ * This doesn't make any members from the loaded module available in the
+ current module.
+
+ * This can be used anywhere in a stylesheet. It can even be nested within
+ style rules to create nested styles!
+
+ * The module URL being loaded can come from a variable and include
+ [interpolation][].
+
+ [interpolation]: ../interpolation
+
+ <% heads_up do %>
+ The `$url` parameter should be a string containing a URL like you'd pass to
+ the `@use` rule. It shouldn't be a CSS `url()`!
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ // dark-theme/_code.scss
+ $border-contrast: false !default;
+
+ code {
+ background-color: #6b717f;
+ color: #d2e1dd;
+ @if $border-contrast {
+ border-color: #dadbdf;
+ }
+ }
+ ---
+ // style.scss
+ @use "sass:meta";
+
+ body.dark {
+ @include meta.load-css("dark-theme/code",
+ $with: ("border-contrast": true));
+ }
+ ===
+ // dark-theme/_code.sass
+ $border-contrast: false !default
+
+ code
+ background-color: #6b717f
+ color: #d2e1dd
+ @if $border-contrast
+ border-color: #dadbdf
+ ---
+ // style.sass
+ @use "sass:meta"
+
+ body.dark
+ $configuration: ("border-contrast": true)
+ @include meta.load-css("dark-theme/code", $with: $configuration)
+ ===
+ body.dark code {
+ background-color: #6b717f;
+ color: #d2e1dd;
+ border-color: #dadbdf;
+ }
+ <% end %>
+<% end %>
+
+## Functions
+
+<% function 'meta.call($function, $args...)', 'call($function, $args...)' do %>
+ <%= partial 'documentation/snippets/call-impl-status' %>
+
+ Invokes `$function` with `$args` and returns the result.
+
+ The `$function` should be a [function][] returned by
+ [`meta.get-function()`][].
+
+ [function]: ../values/functions
+ [`meta.get-function()`]: #get-function
+
+ <%= partial 'code-snippets/example-first-class-function' %>
+<% end %>
+
+
+<% function 'meta.content-exists()',
+ 'content-exists()',
+ returns: 'boolean' do %>
+ Returns whether the current mixin was passed a [`@content` block][].
+
+ [`@content` block]: ../at-rules/mixin#content-blocks
+
+ Throws an error if called outside of a mixin.
+
+ <% example(autogen_css: false) do %>
+ @mixin debug-content-exists {
+ @debug meta.content-exists();
+ @content;
+ }
+
+ @include debug-content-exists; // false
+ @include debug-content-exists { // true
+ // Content!
+ }
+ ===
+ @mixin debug-content-exists
+ @debug meta.content-exists()
+ @content
+
+
+ @include debug-content-exists // false
+ @include debug-content-exists // true
+ // Content!
+ <% end %>
+<% end %>
+
+
+<% function 'meta.feature-exists($feature)',
+ 'feature-exists($feature)',
+ returns: 'boolean' do %>
+ Returns whether the current Sass implementation supports `$feature`.
+
+ The `$feature` must be a string. The currently recognized features are:
+
+ * `global-variable-shadowing`, which means that a local variable will
+ [shadow][] a global variable unless it has the `!global` flag.
+ * `extend-selector-pseudoclass`, which means that the [`@extend` rule][] will
+ affect selectors nested in pseudo-classes like `:not()`.
+ * `units-level3`, which means that [unit arithmetic][] supports units defined
+ in [CSS Values and Units Level 3][].
+ * `at-error`, which means that the [`@error` rule][] is supported.
+ * `custom-property`, which means that [custom property declaration][] values
+ don't support any [expressions][] other than [interpolation][].
+
+ [shadow]: ../variables#shadowing
+ [`@extend` rule]: ../at-rules/extend
+ [unit arithmetic]: ../values/numbers#units
+ [CSS Values and Units Level 3]: http://www.w3.org/TR/css3-values
+ [`@error` rule]: ../at-rules/error
+ [custom property declaration]: ../style-rules/declarations#custom-properties
+ [expressions]: ../syntax/structure#expressions
+ [interpolation]: ../interpolation
+
+ Returns `false` for any unrecognized `$feature`.
+
+ <% example(autogen_css: false) do %>
+ @debug meta.feature-exists("at-error"); // true
+ @debug meta.feature-exists("unrecognized"); // false
+ ===
+ @debug meta.feature-exists("at-error") // true
+ @debug meta.feature-exists("unrecognized") // false
+ <% end %>
+<% end %>
+
+
+<% function 'meta.function-exists($name)',
+ 'function-exists($name)',
+ returns: 'boolean' do %>
+ Returns whether a function named `$name` is defined, either as a built-in
+ function or a user-defined function.
+
+ <% example(autogen_css: false) do %>
+ @debug meta.function-exists("scale-color"); // true
+ @debug meta.function-exists("add"); // false
+
+ @function add($num1, $num2) {
+ @return $num1 + $num2;
+ }
+ @debug meta.function-exists("add"); // true
+ ===
+ @debug meta.function-exists("scale-color") // true
+ @debug meta.function-exists("add") // false
+
+ @function add($num1, $num2)
+ @return $num1 + $num2
+
+ @debug meta.function-exists("add") // true
+ <% end %>
+<% end %>
+
+
+<% function 'meta.get-function($name, $css: false)',
+ 'get-function($name, $css: false)',
+ returns: 'function' do %>
+ Returns the [function][] named `$name`.
+
+ [function]: ../values/functions
+
+ This can access both built-in and [user-defined][] functions. By default, it
+ throws an error if `$name` doesn't refer to either a built-in or user-defined
+ function. However, if `$css` is `true`, it instead returns a
+ [plain CSS function][].
+
+ [user-defined]: ../at-rules/function
+ [plain CSS function]: ../at-rules/function#plain-css-functions
+
+ The returned function can be called using [`meta.call()`](#call).
+
+ <%= partial 'code-snippets/example-first-class-function' %>
+<% end %>
+
+
+<% function 'meta.global-variable-exists($name)',
+ 'global-variable-exists($name)',
+ returns: 'boolean' do %>
+ Returns whether a [global variable][] named `$name` (without the `$`) exists.
+
+ [global variable]: ../variables#scope
+
+ See also [`meta.variable-exists()`](#variable-exists).
+
+ <% example(autogen_css: false) do %>
+ @debug meta.global-variable-exists("var1"); // false
+
+ $var1: value;
+ @debug meta.global-variable-exists("var1"); // true
+
+ h1 {
+ // $var2 is local.
+ $var2: value;
+ @debug meta.global-variable-exists("var2"); // false
+ }
+ ===
+ @debug meta.global-variable-exists("var1") // false
+
+ $var1: value
+ @debug meta.global-variable-exists("var1") // true
+
+ h1
+ // $var2 is local.
+ $var2: value
+ @debug meta.global-variable-exists("var2") // false
+ <% end %>
+<% end %>
+
+
+<% function 'meta.inspect($value)',
+ 'inspect($value)',
+ returns: 'unquoted string' do %>
+ Returns a string representation of `$value`.
+
+ Returns a representation of *any* Sass value, not just those that can be
+ represented in CSS. As such, its return value is not guaranteed to be valid
+ CSS.
+
+ <% heads_up do %>
+ This function is intended for debugging; its output format is not guaranteed
+ to be consistent across Sass versions or implementations.
+ <% end %>
+
+ <% example(autogen_css: false) do %>
+ @debug meta.inspect(10px 20px 30px); // unquote("10px 20px 30px")
+ @debug meta.inspect(("width": 200px)); // unquote('("width": 200px)')
+ @debug meta.inspect(null); // unquote("null")
+ @debug meta.inspect("Helvetica"); // unquote('"Helvetica"')
+ ===
+ @debug meta.inspect(10px 20px 30px) // unquote("10px 20px 30px")
+ @debug meta.inspect(("width": 200px)) // unquote('("width": 200px)')
+ @debug meta.inspect(null) // unquote("null")
+ @debug meta.inspect("Helvetica") // unquote('"Helvetica"')
+ <% end %>
+<% end %>
+
+
+<% function 'meta.keywords($args)', 'keywords($args)', returns: 'map' do %>
+ Returns the keywords passed to a mixin or function that takes [arbitrary
+ arguments][]. The `$args` argument must be an [argument list][].
+
+ [arbitrary arguments]: ../at-rules/mixin#taking-arbitrary-arguments
+ [argument list]: ../values/lists#argument-lists
+
+ The keywords are returned as a map from argument names as unquoted strings (not
+ including `$`) to the values of those arguments.
+
+ <%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %>
+<% end %>
+
+
+<% function 'meta.mixin-exists($name)',
+ 'mixin-exists($name)',
+ returns: 'boolean' do %>
+ Returns whether a [mixin][] named `$name` exists.
+
+ [mixin]: ../at-rules/mixin
+
+ <% example(autogen_css: false) do %>
+ @debug meta.mixin-exists("shadow-none"); // false
+
+ @mixin shadow-none {
+ box-shadow: none;
+ }
+
+ @debug meta.mixin-exists("shadow-none"); // true
+ ===
+ @debug meta.mixin-exists("shadow-none") // false
+
+ @mixin shadow-none
+ box-shadow: none
+
+
+ @debug meta.mixin-exists("shadow-none") // true
+ <% end %>
+<% end %>
+
+
+<% function 'meta.module-functions($module)',
+ returns: 'map' do %>
+ <%= partial '../snippets/module-system-function-status' %>
+
+ Returns all the functions defined in a module, as a map from function names to
+ [function values][].
+
+ [function values]: ../values/functions
+
+ The `$module` parameter must be a string matching the namespace of a [`@use`
+ rule][] in the current file.
+
+ [`@use` rule]: ../at-rules/use
+
+ <% example(autogen_css: false) do %>
+ // _functions.scss
+ @function pow($base, $exponent) {
+ $result: 1;
+ @for $_ from 1 through $exponent {
+ $result: $result * $base;
+ }
+ @return $result;
+ }
+ ---
+ @use "sass:map";
+ @use "sass:meta";
+
+ @use "functions";
+
+ @debug meta.module-functions("functions"); // ("pow": get-function("pow"))
+
+ @debug meta.call(map.get(meta.module-variables("functions"), "pow"), 3, 4); // 16
+ ===
+ // _functions.sass
+ @function pow($base, $exponent)
+ $result: 1
+ @for $_ from 1 through $exponent
+ $result: $result * $base
+
+ @return $result
+ ---
+ @use "sass:map"
+ @use "sass:meta"
+
+ @use "functions"
+
+ @debug meta.module-functions("functions") // ("pow": get-function("pow"))
+
+ @debug meta.call(map.get(meta.module-variables("functions"), "pow"), 3, 4) // 16
+ <% end %>
+<% end %>
+
+
+<% function 'meta.module-variables($module)',
+ returns: 'map' do %>
+ <%= partial '../snippets/module-system-function-status' %>
+
+ Returns all the variables defined in a module, as a map from variable names
+ (without `$`) to the values of those variables.
+
+ The `$module` parameter must be a string matching the namespace of a [`@use`
+ rule][] in the current file.
+
+ [`@use` rule]: ../at-rules/use
+
+ <% example(autogen_css: false) do %>
+ // _variables.scss
+ $hopbush: #c69;
+ $midnight-blue: #036;
+ $wafer: #e1d7d2;
+ ---
+ @use "sass:meta";
+
+ @use "variables";
+
+ @debug meta.module-variables("variables");
+ // (
+ // "hopbush": #c69,
+ // "midnight-blue": #036,
+ // "wafer": #e1d7d2
+ // )
+ ===
+ // _variables.sass
+ $hopbush: #c69
+ $midnight-blue: #036
+ $wafer: #e1d7d2
+ ---
+ @use "sass:meta"
+
+ @use "variables"
+
+ @debug meta.module-variables("variables")
+ // (
+ // "hopbush": #c69,
+ // "midnight-blue": #036,
+ // "wafer": #e1d7d2
+ // )
+ <% end %>
+<% end %>
+
+
+<% function 'meta.type-of($value)',
+ 'type-of($value)',
+ returns: 'unquoted string' do %>
+ Returns the type of `$value`.
+
+ This can return the following values:
+
+ * [`number`](../values/numbers)
+ * [`string`](../values/strings)
+ * [`color`](../values/colors)
+ * [`list`](../values/lists)
+ * [`map`](../values/maps)
+ * [`bool`](../values/booleans)
+ * [`null`](../values/null)
+ * [`function`](../values/functions)
+ * [`arglist`](../values/lists#argument-lists)
+
+ New possible values may be added in the future. It may return either `list` or
+ `map` for `()`, depending on whether or not it was returned by a
+ [map function][].
+
+ [map function]: map
+
+ <% example(autogen_css: false) do %>
+ @debug meta.type-of(10px); // number
+ @debug meta.type-of(10px 20px 30px); // list
+ @debug meta.type-of(()); // list
+ ===
+ @debug meta.type-of(10px) // number
+ @debug meta.type-of(10px 20px 30px) // list
+ @debug meta.type-of(()) // list
+ <% end %>
+<% end %>
+
+
+<% function 'meta.variable-exists($name)',
+ 'variable-exists($name)',
+ returns: 'boolean' do %>
+ Returns whether a variable named `$name` (without the `$`) exists in the
+ current [scope][].
+
+ [scope]: ../variables#scope
+
+ See also [`meta.global-variable-exists()`](#global-variable-exists).
+
+ <% example(autogen_css: false) do %>
+ @debug meta.variable-exists("var1"); // false
+
+ $var1: value;
+ @debug meta.variable-exists("var1"); // true
+
+ h1 {
+ // $var2 is local.
+ $var2: value;
+ @debug meta.variable-exists("var2"); // true
+ }
+ ===
+ @debug meta.variable-exists("var1") // false
+
+ $var1: value
+ @debug meta.variable-exists("var1") // true
+
+ h1
+ // $var2 is local.
+ $var2: value
+ @debug meta.variable-exists("var2") // true
+ <% end %>
+<% end %>
diff --git a/source/documentation/functions/selector.html.md.erb b/source/documentation/modules/selector.html.md.erb
similarity index 52%
rename from source/documentation/functions/selector.html.md.erb
rename to source/documentation/modules/selector.html.md.erb
index fa6d9f7a8..da33aab34 100644
--- a/source/documentation/functions/selector.html.md.erb
+++ b/source/documentation/modules/selector.html.md.erb
@@ -1,20 +1,22 @@
---
-title: Selector Functions
+title: sass:selector
---
+<%= partial '../snippets/built-in-module-status' %>
+
## Selector Values
-These functions inspect and manipulate selectors. Whenever they return a
-selector, it's always a comma-separated [list][] (the selector list) that
-contains space-separated lists (the complex selectors) that contain [unquoted
-strings][] (the compound selectors). For example, the selector `.main
+The functions in this module inspect and manipulate selectors. Whenever they
+return a selector, it's always a comma-separated [list][] (the selector list)
+that contains space-separated lists (the complex selectors) that contain
+[unquoted strings][] (the compound selectors). For example, the selector `.main
aside:hover, .sidebar p` would be returned as:
[list]: ../values/lists
[unquoted strings]: ../values/strings#unquoted
```scss
-@debug ((unquote(".main") unquote("aside:hover")),
+@debug selector.((unquote(".main") unquote("aside:hover")),
(unquote(".sidebar") unquote("p")));
// .main aside:hover, .sidebar p
```
@@ -24,8 +26,9 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
`".main aside:hover, .sidebar p"` is a valid selector argument.
-<% function 'is-superselector($super, $sub)', returns: 'boolean' do %>
-
+<% function 'selector.is-superselector($super, $sub)',
+ 'is-superselector($super, $sub)',
+ returns: 'boolean' do %>
Returns whether the selector `$super` matches all the elements that the
selector `$sub` matches.
@@ -38,22 +41,24 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
[parent selectors]: ../style-rules/parent-selector
<% example(autogen_css: false) do %>
- @debug is-superselector("a", "a.disabled"); // true
- @debug is-superselector("a.disabled", "a"); // false
- @debug is-superselector("a", "sidebar a"); // true
- @debug is-superselector("sidebar a", "a"); // false
- @debug is-superselector("a", "a"); // true
+ @debug selector.is-superselector("a", "a.disabled"); // true
+ @debug selector.is-superselector("a.disabled", "a"); // false
+ @debug selector.is-superselector("a", "sidebar a"); // true
+ @debug selector.is-superselector("sidebar a", "a"); // false
+ @debug selector.is-superselector("a", "a"); // true
===
- @debug is-superselector("a", "a.disabled") // true
- @debug is-superselector("a.disabled", "a") // false
- @debug is-superselector("a", "sidebar a") // true
- @debug is-superselector("sidebar a", "a") // false
- @debug is-superselector("a", "a") // true
+ @debug selector.is-superselector("a", "a.disabled") // true
+ @debug selector.is-superselector("a.disabled", "a") // false
+ @debug selector.is-superselector("a", "sidebar a") // true
+ @debug selector.is-superselector("sidebar a", "a") // false
+ @debug selector.is-superselector("a", "a") // true
<% end %>
<% end %>
-<% function 'selector-append($selectors...)', returns: 'selector' do %>
+<% function 'selector.append($selectors...)',
+ 'selector-append($selectors...)',
+ returns: 'selector' do %>
Combines `$selectors` without [descendant combinators][]—that is, without
whitespace between them.
@@ -68,23 +73,25 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
[placeholder selectors]: ../style-rules/placeholder-selectors
[parent selectors]: ../style-rules/parent-selector
- See also [`selector-nest()`](#selector-nest).
+ See also [`selector.nest()`](#nest).
<% example(autogen_css: false) do %>
- @debug selector-append("a", ".disabled"); // a.disabled
- @debug selector-append(".accordion", "__copy"); // .accordion__copy
- @debug selector-append(".accordion", "__copy, __image");
+ @debug selector.append("a", ".disabled"); // a.disabled
+ @debug selector.append(".accordion", "__copy"); // .accordion__copy
+ @debug selector.append(".accordion", "__copy, __image");
// .accordion__copy, .accordion__image
===
- @debug selector-append("a", ".disabled") // a.disabled
- @debug selector-append(".accordion", "__copy") // .accordion__copy
- @debug selector-append(".accordion", "__copy, __image")
+ @debug selector.append("a", ".disabled") // a.disabled
+ @debug selector.append(".accordion", "__copy") // .accordion__copy
+ @debug selector.append(".accordion", "__copy, __image")
// .accordion__copy, .accordion__image
<% end %>
<% end %>
-<% function 'selector-extend($selector, $extendee, $extender)', returns: 'selector' do %>
+<% function 'selector.extend($selector, $extendee, $extender)',
+ 'selector-extend($selector, $extendee, $extender)',
+ returns: 'selector' do %>
Extends `$selector` as with the [`@extend` rule][].
[`@extend` rule]: ../at-rules/extend
@@ -107,23 +114,25 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
[placeholder selectors]: ../style-rules/placeholder-selectors
[parent selectors]: ../style-rules/parent-selector
- See also [`selector-replace()`](#selector-replace).
+ See also [`selector.replace()`](#replace).
<% example(autogen_css: false) do %>
- @debug selector-extend("a.disabled", "a", ".link"); // a.disabled, .link.disabled
- @debug selector-extend("a.disabled", "h1", "h2"); // a.disabled
- @debug selector-extend(".guide .info", ".info", ".content nav.sidebar");
+ @debug selector.extend("a.disabled", "a", ".link"); // a.disabled, .link.disabled
+ @debug selector.extend("a.disabled", "h1", "h2"); // a.disabled
+ @debug selector.extend(".guide .info", ".info", ".content nav.sidebar");
// .guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar
===
- @debug selector-extend("a.disabled", "a", ".link") // a.disabled, .link.disabled
- @debug selector-extend("a.disabled", "h1", "h2") // a.disabled
- @debug selector-extend(".guide .info", ".info", ".content nav.sidebar")
+ @debug selector.extend("a.disabled", "a", ".link") // a.disabled, .link.disabled
+ @debug selector.extend("a.disabled", "h1", "h2") // a.disabled
+ @debug selector.extend(".guide .info", ".info", ".content nav.sidebar")
// .guide .info, .guide .content nav.sidebar, .content .guide nav.sidebar
<% end %>
<% end %>
-<% function 'selector-nest($selectors...)', returns: 'selector' do %>
+<% function 'selector.nest($selectors...)',
+ 'selector-nest($selectors...)',
+ returns: 'selector' do %>
Combines `$selectors` as though they were nested within one another in the
stylesheet.
@@ -133,38 +142,42 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
[placeholder selectors]: ../style-rules/placeholder-selectors
[parent selectors]: ../style-rules/parent-selector
- See also [`selector-append()`][].
+ See also [`selector.append()`](#append).
<% example(autogen_css: false) do %>
- @debug selector-nest("ul", "li"); // ul li
- @debug selector-nest(".alert, .warning", "p"); // .alert p, .warning p
- @debug selector-nest(".alert", "&:hover"); // .alert:hover
- @debug selector-nest(".accordion", "&__copy"); // .accordion__copy
+ @debug selector.nest("ul", "li"); // ul li
+ @debug selector.nest(".alert, .warning", "p"); // .alert p, .warning p
+ @debug selector.nest(".alert", "&:hover"); // .alert:hover
+ @debug selector.nest(".accordion", "&__copy"); // .accordion__copy
===
- @debug selector-nest("ul", "li") // ul li
- @debug selector-nest(".alert, .warning", "p") // .alert p, .warning p
- @debug selector-nest(".alert", "&:hover") // .alert:hover
- @debug selector-nest(".accordion", "&__copy") // .accordion__copy
+ @debug selector.nest("ul", "li") // ul li
+ @debug selector.nest(".alert, .warning", "p") // .alert p, .warning p
+ @debug selector.nest(".alert", "&:hover") // .alert:hover
+ @debug selector.nest(".accordion", "&__copy") // .accordion__copy
<% end %>
<% end %>
-<% function 'selector-parse($selector)', returns: 'selector' do %>
+<% function 'selector.parse($selector)',
+ 'selector-parse($selector)',
+ returns: 'selector' do %>
Returns `$selector` in the [selector value](#selector-values) format.
<% example(autogen_css: false) do %>
- @debug selector-parse(".main aside:hover, .sidebar p");
+ @debug selector.parse(".main aside:hover, .sidebar p");
// ((unquote(".main") unquote("aside:hover")),
// (unquote(".sidebar") unquote("p")))
===
- @debug selector-parse(".main aside:hover, .sidebar p")
+ @debug selector.parse(".main aside:hover, .sidebar p")
// ((unquote(".main") unquote("aside:hover")),
// (unquote(".sidebar") unquote("p")))
<% end %>
<% end %>
-<% function 'selector-replace($selector, $original, $replacement)', returns: 'selector' do %>
+<% function 'selector.replace($selector, $original, $replacement)',
+ 'selector-replace($selector, $original, $replacement)',
+ returns: 'selector' do %>
Returns a copy of `$selector` with all instances of `$original` replaced by
`$replacement`.
@@ -181,24 +194,25 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
[placeholder selectors]: ../style-rules/placeholder-selectors
[parent selectors]: ../style-rules/parent-selector
- See also [`selector-extend()`](#selector-extend).
+ See also [`selector.extend()`](#extend).
<% example(autogen_css: false) do %>
- @debug selector-replace("a.disabled", "a", ".link"); // .link.disabled
- @debug selector-replace("a.disabled", "h1", "h2"); // a.disabled
- @debug selector-replace(".guide .info", ".info", ".content nav.sidebar");
+ @debug selector.replace("a.disabled", "a", ".link"); // .link.disabled
+ @debug selector.replace("a.disabled", "h1", "h2"); // a.disabled
+ @debug selector.replace(".guide .info", ".info", ".content nav.sidebar");
// .guide .content nav.sidebar, .content .guide nav.sidebar
===
- @debug selector-replace("a.disabled", "a", ".link") // .link.disabled
- @debug selector-replace("a.disabled", "h1", "h2") // a.disabled
- @debug selector-replace(".guide .info", ".info", ".content nav.sidebar")
+ @debug selector.replace("a.disabled", "a", ".link") // .link.disabled
+ @debug selector.replace("a.disabled", "h1", "h2") // a.disabled
+ @debug selector.replace(".guide .info", ".info", ".content nav.sidebar")
// .guide .content nav.sidebar, .content .guide nav.sidebar
<% end %>
<% end %>
-<% function 'selector-unify($selector1, $selector2)', returns: 'selector | null' do %>
-
+<% function 'selector.unify($selector1, $selector2)',
+ 'selector.unify($selector1, $selector2)',
+ returns: 'selector | null' do %>
Returns a selector that matches only elements matched by *both* `$selector1`
and `$selector2`.
@@ -212,21 +226,22 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
[`@extend` rule]: ../at-rules/extend#html-heuristics
<% example(autogen_css: false) do %>
- @debug selector-unify("a", ".disabled"); // a.disabled
- @debug selector-unify("a.disabled", "a.outgoing"); // a.disabled.outgoing
- @debug selector-unify("a", "h1"); // null
- @debug selector-unify(".warning a", "main a"); // .warning main a, main .warning a
+ @debug selector.unify("a", ".disabled"); // a.disabled
+ @debug selector.unify("a.disabled", "a.outgoing"); // a.disabled.outgoing
+ @debug selector.unify("a", "h1"); // null
+ @debug selector.unify(".warning a", "main a"); // .warning main a, main .warning a
===
- @debug selector-unify("a", ".disabled") // a.disabled
- @debug selector-unify("a.disabled", "a.outgoing") // a.disabled.outgoing
- @debug selector-unify("a", "h1") // null
- @debug selector-unify(".warning a", "main a") // .warning main a, main .warning a
+ @debug selector.unify("a", ".disabled") // a.disabled
+ @debug selector.unify("a.disabled", "a.outgoing") // a.disabled.outgoing
+ @debug selector.unify("a", "h1") // null
+ @debug selector.unify(".warning a", "main a") // .warning main a, main .warning a
<% end %>
<% end %>
-<% function 'simple-selectors($selector)', returns: 'list' do %>
-
+<% function 'selector.simple-selectors($selector)',
+ 'simple-selectors($selector)',
+ returns: 'list' do %>
Returns a list of simple selectors in `$selector`.
The `$selector` must be a single string that contains a compound selector.
@@ -236,10 +251,10 @@ also just be normal strings (quoted or unquoted), or a combination. For example,
strings.
<% example(autogen_css: false) do %>
- @debug compound-selectors("a.disabled"); // a, .disabled
- @debug compound-selectors("main.blog:after"); // main, .blog, :after
+ @debug selector.compound-selectors("a.disabled"); // a, .disabled
+ @debug selector.compound-selectors("main.blog:after"); // main, .blog, :after
===
- @debug compound-selectors("a.disabled") // a, .disabled
- @debug compound-selectors("main.blog:after") // main, .blog, :after
+ @debug selector.compound-selectors("a.disabled") // a, .disabled
+ @debug selector.compound-selectors("main.blog:after") // main, .blog, :after
<% end %>
<% end %>
diff --git a/source/documentation/modules/string.html.md.erb b/source/documentation/modules/string.html.md.erb
new file mode 100644
index 000000000..b23bb52b9
--- /dev/null
+++ b/source/documentation/modules/string.html.md.erb
@@ -0,0 +1,163 @@
+---
+title: sass:string
+---
+
+<%= partial '../snippets/built-in-module-status' %>
+
+<% function 'string.quote($string)', 'quote($string)', returns: 'string' do %>
+ Returns `$string` as a quoted string.
+
+ <% example(autogen_css: false) do %>
+ @debug string.quote(Helvetica); // "Helvetica"
+ @debug string.quote("Helvetica"); // "Helvetica"
+ ===
+ @debug string.quote(Helvetica) // "Helvetica"
+ @debug string.quote("Helvetica") // "Helvetica"
+ <% end %>
+<% end %>
+
+
+<% function 'string.index($string, $substring)',
+ 'str-index($string, $substring)',
+ returns: 'number' do %>
+ Returns the first [index][] of `$substring` in `$string`, or `null` if
+ `$string` doesn't contain `$substring`.
+
+ [index]: ../values/strings#string-indexes
+
+ <% example(autogen_css: false) do %>
+ @debug string.index("Helvetica Neue", "Helvetica"); // 1
+ @debug string.index("Helvetica Neue", "Neue"); // 11
+ ===
+ @debug string.index("Helvetica Neue", "Helvetica") // 1
+ @debug string.index("Helvetica Neue", "Neue") // 11
+ <% end %>
+<% end %>
+
+
+<% function 'string.insert($string, $insert, $index)',
+ 'str-insert($string, $insert, $index)',
+ returns: 'string' do %>
+ Returns a copy of `$string` with `$insert` inserted at [`$index`][].
+
+ [`$index`]: ../values/strings#string-indexes
+
+ <% example(autogen_css: false) do %>
+ @debug string.insert("Roboto Bold", " Mono", 7); // "Roboto Mono Bold"
+ @debug string.insert("Roboto Bold", " Mono", -6); // "Roboto Mono Bold"
+ ===
+ @debug string.insert("Roboto Bold", " Mono", 7) // "Roboto Mono Bold"
+ @debug string.insert("Roboto Bold", " Mono", -6) // "Roboto Mono Bold"
+ <% end %>
+
+ If of `$index` is higher than the length of `$string`, `$insert` is added to
+ the end. If `$index` is smaller than the negative length of the string,
+ `$insert` is added to the beginning.
+
+ <% example(autogen_css: false) do %>
+ @debug string.insert("Roboto", " Bold", 100); // "Roboto Bold"
+ @debug string.insert("Bold", "Roboto ", -100); // "Roboto Bold"
+ ===
+ @debug string.insert("Roboto", " Bold", 100) // "Roboto Bold"
+ @debug string.insert("Bold", "Roboto ", -100) // "Roboto Bold"
+ <% end %>
+<% end %>
+
+
+<% function 'string.length($string)',
+ 'str-length($string)',
+ returns: 'number' do %>
+ Returns the number of characters in `$string`.
+
+ <% example(autogen_css: false) do %>
+ @debug string.length("Helvetica Neue"); // 14
+ @debug string.length(bold); // 4
+ @debug string.index(""); // 0
+ ===
+ @debug string.length("Helvetica Neue") // 14
+ @debug string.length(bold) // 4
+ @debug string.index("") // 0
+ <% end %>
+<% end %>
+
+
+<% function 'string.slice($string, $start-at, $end-at: -1)',
+ 'str-slice($string, $start-at, $end-at: -1)',
+ returns: 'string' do %>
+ Returns the slice of `$string` starting at [index][] `$start-at` and ending at
+ index `$end-at` (both inclusive).
+
+ [index]: ../values/strings#string-indexes
+
+ <% example(autogen_css: false) do %>
+ @debug string.slice("Helvetica Neue", 11); // "Neue"
+ @debug string.slice("Helvetica Neue", 1, 3); // "Hel"
+ @debug string.slice("Helvetica Neue", 1, -6); // "Helvetica"
+ ===
+ @debug string.slice("Helvetica Neue", 11) // "Neue"
+ @debug string.slice("Helvetica Neue", 1, 3) // "Hel"
+ @debug string.slice("Helvetica Neue", 1, -6) // "Helvetica"
+ <% end %>
+<% end %>
+
+
+<% function 'string.to-upper-case($string)',
+ 'to-upper-case($string)',
+ returns: 'string' do %>
+ Returns a copy of `$string` with the [ASCII][] letters converted to upper case.
+
+ [ASCII]: https://en.wikipedia.org/wiki/ASCII
+
+ <% example(autogen_css: false) do %>
+ @debug string.to-upper-case("Bold"); // "BOLD"
+ @debug string.to-upper-case(sans-serif); // SANS-SERIF
+ ===
+ @debug string.to-upper-case("Bold") // "BOLD"
+ @debug string.to-upper-case(sans-serif) // SANS-SERIF
+ <% end %>
+<% end %>
+
+
+<% function 'string.to-lower-case($string)',
+ 'to-lower-case($string)',
+ returns: 'string' do %>
+ Returns a copy of `$string` with the [ASCII][] letters converted to lower case.
+
+ [ASCII]: https://en.wikipedia.org/wiki/ASCII
+
+ <% example(autogen_css: false) do %>
+ @debug string.to-lower-case("Bold"); // "bold"
+ @debug string.to-lower-case(SANS-SERIF); // sans-serif
+ ===
+ @debug string.to-lower-case("Bold") // "bold"
+ @debug string.to-lower-case(SANS-SERIF) // sans-serif
+ <% end %>
+<% end %>
+
+
+<% function 'string.unique-id()', 'unique-id()', returns: 'string' do %>
+ Returns a randomly-generated unquoted string that's guaranteed to be a valid
+ CSS identifier and to be unique within the current Sass compilation.
+
+ <% example(autogen_css: false) do %>
+ @debug string.unique-id(); // uabtrnzug
+ @debug string.unique-id(); // u6w1b1def
+ ===
+ @debug string.unique-id(); // uabtrnzug
+ @debug string.unique-id(); // u6w1b1def
+ <% end %>
+<% end %>
+
+
+<% function 'string.unquote()', 'unquote()', returns: 'string' do %>
+ Returns `$string` as an unquoted string. This can produce strings that aren't
+ valid CSS, so use with caution.
+
+ <% example(autogen_css: false) do %>
+ @debug string.unquote("Helvetica"); // Helvetica
+ @debug string.unquote(".widget:hover"); // .widget:hover
+ ===
+ @debug string.unquote("Helvetica") // Helvetica
+ @debug string.unquote(".widget:hover") // .widget:hover
+ <% end %>
+<% end %>
diff --git a/source/documentation/operators.html.md.erb b/source/documentation/operators.html.md.erb
index e09fc83a6..e5b0e8baa 100644
--- a/source/documentation/operators.html.md.erb
+++ b/source/documentation/operators.html.md.erb
@@ -22,7 +22,7 @@ introduction: >
They're still supported in LibSass and Ruby Sass, but they'll produce warnings
and users are strongly encouraged to avoid them.
- [Color functions]: functions/color
+ [Color functions]: modules/color
<% end %>
## Order of Operations
diff --git a/source/documentation/snippets/_built-in-module-status.erb b/source/documentation/snippets/_built-in-module-status.erb
new file mode 100644
index 000000000..657dcfd4d
--- /dev/null
+++ b/source/documentation/snippets/_built-in-module-status.erb
@@ -0,0 +1,4 @@
+<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %>
+ Only Dart Sass currently supports loading built-in modules with `@use`. Users
+ of other implementations must call functions using their global names instead.
+<% end %>
diff --git a/source/documentation/snippets/_call-impl-status.html.erb b/source/documentation/snippets/_call-impl-status.html.erb
index 14d5972b5..ecc2104f0 100644
--- a/source/documentation/snippets/_call-impl-status.html.erb
+++ b/source/documentation/snippets/_call-impl-status.html.erb
@@ -4,7 +4,7 @@
value instead in preparation for a new module system where functions are no
longer global and so a given name may not always refer to the same function.
- [`call()` function]: /documentation/functions/meta#call
+ [`call()` function]: /documentation/modules/meta#call
Passing a string to `call()` still works in all implementations, but it's
deprecated and will be disallowed in future versions.
diff --git a/source/documentation/snippets/_module-system-function-status.erb b/source/documentation/snippets/_module-system-function-status.erb
new file mode 100644
index 000000000..8a462db2c
--- /dev/null
+++ b/source/documentation/snippets/_module-system-function-status.erb
@@ -0,0 +1,3 @@
+<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %>
+ Only Dart Sass currently supports this function.
+<% end %>
diff --git a/source/documentation/snippets/_module-system-status.erb b/source/documentation/snippets/_module-system-status.erb
new file mode 100644
index 000000000..45073ecc2
--- /dev/null
+++ b/source/documentation/snippets/_module-system-status.erb
@@ -0,0 +1,6 @@
+<% impl_status dart: '(unreleased)', libsass: false, ruby: false do %>
+ Only Dart Sass currently supports `@use`. Users of other implementations must
+ use the [`@import` rule][] instead.
+
+ [`@import` rule]: /documentation/at-rules/import
+<% end %>
diff --git a/source/documentation/snippets/_number-units.erb b/source/documentation/snippets/_number-units.erb
index e8146bc8b..615b002e6 100644
--- a/source/documentation/snippets/_number-units.erb
+++ b/source/documentation/snippets/_number-units.erb
@@ -128,7 +128,7 @@ to get the time it should take.
[unquoted string]: /documentation/values/strings#unquoted
[number operations]: /documentation/operators/numeric
- [functions]: /documentation/functions/math
+ [functions]: /documentation/modules/math
<% end %>
<% heads_up do %>
@@ -140,8 +140,8 @@ to get the time it should take.
You can convert between decimals and percentages using unit arithmetic.
`$percentage / 100%` will return the corresponding decimal, and `$decimal *
100%` will return the corresponding percentage. You can also use the
- [`percentage()` function][] as a more explicit way of writing `$decimal *
+ [`math.percentage()` function][] as a more explicit way of writing `$decimal *
100%`.
- [`percentage()` function]: /documentation/functions/math#percentage
+ [`math.percentage()` function]: /documentation/modules/math#percentage
<% end %>
diff --git a/source/documentation/snippets/_truthiness-and-falsiness.erb b/source/documentation/snippets/_truthiness-and-falsiness.erb
index 673329dcc..678dc920b 100644
--- a/source/documentation/snippets/_truthiness-and-falsiness.erb
+++ b/source/documentation/snippets/_truthiness-and-falsiness.erb
@@ -9,10 +9,10 @@ succeed.
[`null`]: /documentation/values/null
For example, if you want to check if a string contains a space, you can just
-write `index($string, " ")`. The [`str-index()` function][] returns `null` if
-the string isn't found and a number otherwise.
+write `string.index($string, " ")`. The [`string.index()` function][] returns
+`null` if the string isn't found and a number otherwise.
-[`str-index()` function]: /documentation/functions/string#str-index
+[`string.index()` function]: /documentation/modules/string#index
<% heads_up do %>
Some languages consider more values falsey than just `false` and `null`. Sass
diff --git a/source/documentation/style-rules.html.md.erb b/source/documentation/style-rules.html.md.erb
index c2236dc68..70814708e 100644
--- a/source/documentation/style-rules.html.md.erb
+++ b/source/documentation/style-rules.html.md.erb
@@ -163,4 +163,4 @@ generating selectors. For more information, see the [parent selector
documentation][].
[`@at-root` rule]: at-rules/at-root
-[selector functions]: functions/selector
+[selector functions]: modules/selector
diff --git a/source/documentation/style-rules/declarations.html.md.erb b/source/documentation/style-rules/declarations.html.md.erb
index 9caa0e8b3..9ede40f35 100644
--- a/source/documentation/style-rules/declarations.html.md.erb
+++ b/source/documentation/style-rules/declarations.html.md.erb
@@ -196,26 +196,35 @@ is the only way to inject dynamic values into a custom property.
<% heads_up do %>
Unfortunately, [interpolation][] removes quotes from strings, which makes it
difficult to use quoted strings as values for custom properties when they come
- from Sass variables. As a workaround, you can use the [`inspect()` function][]
- to preserve the quotes.
+ from Sass variables. As a workaround, you can use the [`meta.inspect()`
+ function][] to preserve the quotes.
[interpolation]: ../interpolation
- [`inspect()` function]: ../functions/meta#inspect
+ [`meta.inspect()` function]: ../modules/meta#inspect
<% example do %>
+ @use "sass:meta";
+
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas;
:root {
- --font-family-sans-serif: #{inspect($font-family-sans-serif)};
- --font-family-monospace: #{inspect($font-family-monospace)};
+ --font-family-sans-serif: #{meta.inspect($font-family-sans-serif)};
+ --font-family-monospace: #{meta.inspect($font-family-monospace)};
}
===
+ @use "sass:meta"
+
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas
:root
- --font-family-sans-serif: #{inspect($font-family-sans-serif)}
- --font-family-monospace: #{inspect($font-family-monospace)}
+ --font-family-sans-serif: #{meta.inspect($font-family-sans-serif)}
+ --font-family-monospace: #{meta.inspect($font-family-monospace)}
+ ===
+ :root {
+ --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto;
+ --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas;
+ }
<% end %>
<% end %>
diff --git a/source/documentation/style-rules/parent-selector.html.md.erb b/source/documentation/style-rules/parent-selector.html.md.erb
index d8105acdc..947b5b1c3 100644
--- a/source/documentation/style-rules/parent-selector.html.md.erb
+++ b/source/documentation/style-rules/parent-selector.html.md.erb
@@ -138,7 +138,7 @@ strings (the compound selectors).
// (unquote(".sidebar") unquote("p")))
<% end %>
-[selector functions]: ../functions/selector#selector-values
+[selector functions]: ../modules/selector#selector-values
If the `&` expression is used outside any style rules, it returns `null`. Since
`null` is [falsey][], this means you can easily use it to determine whether a
diff --git a/source/documentation/syntax.html.md b/source/documentation/syntax.html.md
index 2e686adcc..84540b952 100644
--- a/source/documentation/syntax.html.md
+++ b/source/documentation/syntax.html.md
@@ -1,7 +1,7 @@
---
title: Syntax
introduction: >
- Sass supports two different syntaxes. Each one can import the other, so it's
+ Sass supports two different syntaxes. Each one can load the other, so it's
up to you and your team which one to choose.
---
diff --git a/source/documentation/syntax/special-functions.html.md.erb b/source/documentation/syntax/special-functions.html.md.erb
index 7dc2aa2c6..27d9ba0c7 100644
--- a/source/documentation/syntax/special-functions.html.md.erb
+++ b/source/documentation/syntax/special-functions.html.md.erb
@@ -4,10 +4,10 @@ table_of_contents: true
introduction: >
CSS defines many functions, and most of them work just fine with Sass’s normal
function syntax. They’re parsed as function calls, resolved to [plain CSS
- functions](../functions/css), and compiled as-is to CSS. There are a few
- exceptions, though, which have special syntax that can’t just be parsed as a
- [SassScript expression](structure#expressions). All special function calls
- return [unquoted strings](../values/strings#unquoted).
+ functions](../at-rules/function#plain-css-functions), and compiled as-is to
+ CSS. There are a few exceptions, though, which have special syntax that can’t
+ just be parsed as a [SassScript expression](structure#expressions). All
+ special function calls return [unquoted strings](../values/strings#unquoted).
---
## `url()`
@@ -27,7 +27,7 @@ calls][]—it's parsed as a normal [plain CSS function call][].
[interpolation]: ../interpolation
[variables]: ../variables
[function calls]: ../at-rules/function
-[plain CSS function call]: ../functions/css
+[plain CSS function call]: ../at-rules/function#plain-css-functions
<% example do %>
$roboto-font-path: "../fonts/roboto";
@@ -140,8 +140,8 @@ cleverness.
[`min()` and `max()` functions]: https://drafts.csswg.org/css-values-4/#calc-notation
[to support the iPhoneX]: https://webkit.org/blog/7929/designing-websites-for-iphone-x/
-[`min()`]: ../functions/math#min
-[`max()`]: ../functions/math#max
+[`min()`]: ../modules/math#min
+[`max()`]: ../modules/math#max
If a `min()` or `max()` function call is valid plain CSS, it will be compiled to
a CSS `min()` or `max()` call. "Plain CSS" includes nested calls to
diff --git a/source/documentation/syntax/structure.html.md.erb b/source/documentation/syntax/structure.html.md.erb
index d5810ec46..f92361361 100644
--- a/source/documentation/syntax/structure.html.md.erb
+++ b/source/documentation/syntax/structure.html.md.erb
@@ -43,6 +43,7 @@ These statements produce CSS. They can be used anywhere except within a
These statements can only be used at the top level of a stylesheet, or nested
within a CSS statement at the top level:
+* [Module loads](../at-rules/use), using `@use`.
* [Imports](../at-rules/import), using `@import`.
* [Mixin definitions](../at-rules/mixin) using `@mixin`.
* [Function definitions](../at-rules/function) using `@function`.
diff --git a/source/documentation/values.html.md b/source/documentation/values.html.md
index d432afeeb..f53029399 100644
--- a/source/documentation/values.html.md
+++ b/source/documentation/values.html.md
@@ -33,5 +33,5 @@ A few more are specific to Sass:
* [Function references](values/functions) returned by [`get-function()`][] and
called with [`call()`][].
-[`get-function()`]: functions/meta#get-function
-[`call()`]: functions/meta#call
+[`get-function()`]: modules/meta#get-function
+[`call()`]: modules/meta#call
diff --git a/source/documentation/values/booleans.html.md.erb b/source/documentation/values/booleans.html.md.erb
index b70005760..7dfc041fa 100644
--- a/source/documentation/values/booleans.html.md.erb
+++ b/source/documentation/values/booleans.html.md.erb
@@ -4,20 +4,24 @@ introduction: >
Booleans are the logical values `true` and `false`. In addition their literal
forms, booleans are returned by [equality](../operators/equality) and
[relational](../operators/relational) operators, as well as many built-in
- functions like [`comparable()`](../functions/math#comparable) and
- [`map-has-key()`](../functions/map#map-has-key).
+ functions like [`math.comparable()`](../modules/math#comparable) and
+ [`map.has-key()`](../modules/map#has-key).
---
<% example(autogen_css: false) do %>
+ @use "sass:math";
+
@debug 1px == 2px; // false
@debug 1px == 1px; // true
@debug 10px < 3px; // false
- @debug comparable(100px, 3in); // true
+ @debug math.comparable(100px, 3in); // true
===
+ @use "sass:math";
+
@debug 1px == 2px // false
@debug 1px == 1px // true
@debug 10px < 3px // false
- @debug comparable(100px, 3in) // true
+ @debug math.comparable(100px, 3in) // true
<% end %>
You can work with booleans using [boolean operators][]. The `and` operator
@@ -59,7 +63,7 @@ You can use booleans to choose whether or not to do various things in Sass. The
The [`if()` function][] chooses returns one value if its argument is `true` and
another if its argument is `false`:
-[`if()` function]: ../functions#if
+[`if()` function]: ../modules#if
<% example(autogen_css: false) do %>
@debug if(true, 10px, 30px); // 10px
diff --git a/source/documentation/values/colors.html.md.erb b/source/documentation/values/colors.html.md.erb
index ff4f1cdad..40d4f419c 100644
--- a/source/documentation/values/colors.html.md.erb
+++ b/source/documentation/values/colors.html.md.erb
@@ -17,13 +17,13 @@ codes (`#f2ece4` or `#b37399aa`), [CSS color names][] (`midnightblue`,
[`hsla()`][].
[sRGB color space]: https://en.wikipedia.org/wiki/SRGB
-[color functions]: ../functions/color
+[color functions]: ../modules/color
[HSL color space]: https://en.wikipedia.org/wiki/HSL_and_HSV
[CSS color names]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords
-[`rgb()`]: ../functions/color#rgb
-[`rgba()`]: ../functions/color#rgba
-[`hsl()`]: ../functions/color#hsl
-[`hsla()`]: ../functions/color#hsla
+[`rgb()`]: ../modules#rgb
+[`rgba()`]: ../modules#rgba
+[`hsl()`]: ../modules#hsl
+[`hsla()`]: ../modules#hsla
<% example(autogen_css: false) do %>
@debug #f2ece4; // #f2ece4
@@ -61,8 +61,8 @@ Sass supports many useful [color functions][] that can be used to create new
colors based on existing ones by [mixing colors together][] or [scaling their
hue, saturation, or lightness][].
-[mixing colors together]: ../functions/color#mix
-[scaling their hue, saturation, or lightness]: ../functions/color#scale-color
+[mixing colors together]: ../modules/color#mix
+[scaling their hue, saturation, or lightness]: ../modules/color#scale
<% example(autogen_css: false) do %>
$venus: #998099;
diff --git a/source/documentation/values/functions.html.md.erb b/source/documentation/values/functions.html.md.erb
index 7a27ae1d1..f9f3606c0 100644
--- a/source/documentation/values/functions.html.md.erb
+++ b/source/documentation/values/functions.html.md.erb
@@ -5,13 +5,13 @@ title: Functions
<%= partial 'documentation/snippets/call-impl-status' %>
[Functions][] can be values too! You can't directly write a function as a value,
-but you can pass a function's name to the [`get-function()` function][] to get
-it as a value. Once you have a function value, you can pass it to the [`call()`
-function][] to call it. This is useful for writing *higher-order functions* that
-call other functions.
+but you can pass a function's name to the [`meta.get-function()` function][] to
+get it as a value. Once you have a function value, you can pass it to the
+[`meta.call()` function][] to call it. This is useful for writing *higher-order
+functions* that call other functions.
[Functions]: ../at-rules/function
-[`get-function` function]: ../functions/meta#get-function
-[`call()` function]: ../functions/meta#call
+[`meta.get-function` function]: ../modules/meta#get-function
+[`meta.call()` function]: ../modules/meta#call
<%= partial 'code-snippets/example-first-class-function' %>
diff --git a/source/documentation/values/lists.html.md.erb b/source/documentation/values/lists.html.md.erb
index f984373bf..c8c74ace5 100644
--- a/source/documentation/values/lists.html.md.erb
+++ b/source/documentation/values/lists.html.md.erb
@@ -25,7 +25,7 @@ can be written either `()` or `[]`. Also, all [list functions][] will treat
individual values that aren't in lists as though they're lists containing that
value, which means you rarely need to explicitly create single-element lists.
-[list functions]: ../functions/list
+[list functions]: ../modules/list
<% heads_up do %>
Empty lists without brackets aren't valid CSS, so Sass won't let you use one
@@ -38,7 +38,7 @@ Sass provides a handful of [functions][] that make it possible to use lists to
write powerful style libraries, or to make your app's stylesheet cleaner and
more maintainable.
-[functions]: ../functions/list
+[functions]: ../modules/list
### Indexes
@@ -51,11 +51,11 @@ to the last element in a list, -2 refers to the second-to-last, and so on.
### Access an Element
Lists aren't much use if you can't get values out of them. You can use the
-[`nth($list, $n)` function][] to get the element at a given index in a list. The
-first argument is the list itself, and the second is the index of the value you
-want to get out.
+[`list.nth($list, $n)` function][] to get the element at a given index in a
+list. The first argument is the list itself, and the second is the index of the
+value you want to get out.
-[`nth($list, $n)` function]: ../functions/list#nth
+[`list.nth($list, $n)` function]: ../modules/list#nth
<%= partial 'code-snippets/example-list-nth' %>
@@ -71,12 +71,12 @@ in a list, and assigns that element to a variable.
### Add to a List
-It's also useful to add elements to a list. The [`append($list, $val)`
+It's also useful to add elements to a list. The [`list.append($list, $val)`
function][] takes a list and a value, and returns a copy of the list with the value
added to the end. Note that because Sass lists are [immutable][], it doesn't
modify the original list.
-[`append($list, $val)` function]: ../functions/list#append
+[`list.append($list, $val)` function]: ../modules/list#append
[immutable]: #immutability
<% example(autogen_css: false) do %>
@@ -90,37 +90,41 @@ modify the original list.
### Find an Element in a List
If you need to check if an element is in a list or figure out what index it's
-at, use the [`index($list, $value)` function][]. This takes a list and a value
+at, use the [`list.index($list, $value)` function][]. This takes a list and a value
to locate in that list, and returns the index of that value.
-[`index($list, $value)` function]: ../functions/list#index
+[`list.index($list, $value)` function]: ../modules/list#index
<%= partial 'code-snippets/example-list-index' %>
-If the value isn't in the list at all, `index()` returns [`null`][]. Because
-`null` is [falsey][], you can use `index()` with [`@if`][] or [`if()`][] to
+If the value isn't in the list at all, `list.index()` returns [`null`][]. Because
+`null` is [falsey][], you can use `list.index()` with [`@if`][] or [`if()`][] to
check whether a list does or doesn't contain a given value.
[`null`]: null
[falsey]: ../at-rules/control/if#truthiness-and-falsiness
[`@if`]: ../at-rules/control/if
-[`if()`]: ../functions#if
+[`if()`]: ../modules#if
+
+<% example(autogen_css: false) do %>
+ @use "sass:list";
-<% example do %>
$valid-sides: top, bottom, left, right;
@mixin attach($side) {
- @if not index($valid-sides, $side) {
+ @if not list.index($valid-sides, $side) {
@error "#{$side} is not a valid side. Expected one of #{$sides}.";
}
// ...
}
===
+ @use "sass:list"
+
$valid-sides: top, bottom, left, right
@mixin attach($side)
- @if not index($valid-sides, $side)
+ @if not list.index($valid-sides, $side)
@error "#{$side} is not a valid side. Expected one of #{$sides}."
@@ -138,25 +142,31 @@ You can still update your state over time by assigning new lists to the same
variable, though. This is often used in functions and mixins to collect a bunch
of values into one list.
-<% example do %>
+<% example(autogen_css: false) do %>
+ @use "sass:list";
+ @use "sass:map";
+
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms);
@function prefixes-for-browsers($browsers) {
$prefixes: ();
@each $browser in $browsers {
- $prefixes: append($prefixes, map-get($prefixes-by-browser, $browser));
+ $prefixes: list.append($prefixes, map.get($prefixes-by-browser, $browser));
}
@return $prefixes;
}
@debug prefixes-for-browsers("firefox" "ie"); // moz ms
===
+ @use "sass:list"
+ @use "sass:map"
+
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms)
@function prefixes-for-browsers($browsers)
$prefixes: ()
@each $browser in $browsers
- $prefixes: append($prefixes, map-get($prefixes-by-browser, $browser))
+ $prefixes: list.append($prefixes, map.get($prefixes-by-browser, $browser))
@return $prefixes
@@ -170,9 +180,9 @@ When you declare a mixin or function that takes [arbitrary arguments][], the
value you get is a special list known as an *argument list*. It acts just like a
list that contains all the arguments passed to the mixin or function, with one
extra feature: if the user passed keyword arguments, they can be accessed as a
-map by passing the argument list to the [`keywords()` function][].
+map by passing the argument list to the [`meta.keywords()` function][].
<%= partial 'code-snippets/example-mixin-arbitrary-keyword-arguments' %>
[arbitrary arguments]: ../at-rules/mixin#taking-arbitrary-arguments
-[`keywords()` function]: ../functions/map#keywords
+[`meta.keywords()` function]: ../modules/meta#keywords
diff --git a/source/documentation/values/maps.html.md.erb b/source/documentation/values/maps.html.md.erb
index ca38323a8..80ea60d99 100644
--- a/source/documentation/values/maps.html.md.erb
+++ b/source/documentation/values/maps.html.md.erb
@@ -40,16 +40,16 @@ Since maps aren't valid CSS values, they don't do much of anything on their own.
That's why Sass provides a bunch of [functions][] to create maps and access the
values they contain. With
-[functions]: ../functions/map
+[functions]: ../modules/map
### Look Up a Value
Maps are all about associating keys and values, so naturally there's a way to
-get the value associated with a key: the [`map-get($map, $key)` function][]!
+get the value associated with a key: the [`map.get($map, $key)` function][]!
This function returns the value in the map associated with the given key. It
returns [`null`][] if the map doesn't contain the key.
-[`map-get($map, $key)` function]: ../functions/map#map-get
+[`map.get($map, $key)` function]: ../modules/map#get
[`null`]: null
<%= partial 'code-snippets/example-map-get' %>
@@ -68,16 +68,18 @@ easily be accessed in the block.
### Add to a Map
It's also useful to add new pairs to a map, or to replace the value for an
-existing key. The [`map-merge($map1, $map2)` function][] does this: it returns a
+existing key. The [`map.merge($map1, $map2)` function][] does this: it returns a
new map that contains all the key/value pairs in *both* arguments.
-[`map-merge($map1, $map2)` function]: ../functions/map#map-merge
+[`map.merge($map1, $map2)` function]: ../modules/map#merge
<% example(autogen_css: false) do %>
+ @use "sass:map";
+
$light-weights: ("lightest": 100, "light": 300);
$heavy-weights: ("medium": 500, "bold": 700);
- @debug map-merge($light-weights, $heavy-weights);
+ @debug map.merge($light-weights, $heavy-weights);
// (
// "lightest": 100,
// "light": 300,
@@ -85,10 +87,12 @@ new map that contains all the key/value pairs in *both* arguments.
// "bold": 700
// )
===
+ @use "sass:map"
+
$light-weights: ("lightest": 100, "light": 300)
$heavy-weights: ("medium": 500, "bold": 700)
- @debug map-merge($light-weights, $heavy-weights)
+ @debug map.merge($light-weights, $heavy-weights)
// (
// "lightest": 100,
// "light": 300,
@@ -97,17 +101,21 @@ new map that contains all the key/value pairs in *both* arguments.
// )
<% end %>
-`map-merge()` is often used with an inline map to add a single key/value pair.
+`map.merge()` is often used with an inline map to add a single key/value pair.
<% example(autogen_css: false) do %>
+ @use "sass:map";
+
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-merge($font-weights, ("extra-bold": 900));
+ @debug map.merge($font-weights, ("extra-bold": 900));
// ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
===
+ @use "sass:map"
+
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-merge($font-weights, ("extra-bold": 900))
+ @debug map.merge($font-weights, ("extra-bold": 900))
// ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
<% end %>
@@ -115,18 +123,22 @@ If both maps have the same keys, the second map's values are used in the map
that gets returned.
<% example(autogen_css: false) do %>
+ @use "sass:map";
+
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map-merge($font-weights, ("medium": 600));
+ @debug map.merge($font-weights, ("medium": 600));
// ("regular": 400, "medium": 600, "bold": 700)
===
+ @use "sass:map"
+
$font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map-merge($font-weights, ("medium": 600))
+ @debug map.merge($font-weights, ("medium": 600))
// ("regular": 400, "medium": 600, "bold": 700)
<% end %>
-Note that because Sass maps are [immutable][], `map-merge()` doesn't modify the
+Note that because Sass maps are [immutable][], `map.merge()` doesn't modify the
original list.
[immutable]: #immutability
@@ -143,20 +155,24 @@ variable, though. This is often used in functions and mixins to track
configuration in a map.
<% example(autogen_css: false) do %>
+ @use "sass:map";
+
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms);
@mixin add-browser-prefix($browser, $prefix) {
- $prefixes-by-browser: map-merge($prefixes-by-browser, ($browser: $prefix));
+ $prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix));
}
@include add-browser-prefix("opera", o);
@debug $prefixes-by-browser;
// ("firefox": moz, "safari": webkit, "ie": ms, "opera": o)
===
+ @use "sass:map";
+
$prefixes-by-browser: ("firefox": moz, "safari": webkit, "ie": ms)
@mixin add-browser-prefix($browser, $prefix)
- $prefixes-by-browser: map-merge($prefixes-by-browser, ($browser: $prefix))
+ $prefixes-by-browser: map.merge($prefixes-by-browser, ($browser: $prefix))
@include add-browser-prefix("opera", o)
diff --git a/source/documentation/values/null.html.md.erb b/source/documentation/values/null.html.md.erb
index 970a531ea..e4cf1cd1a 100644
--- a/source/documentation/values/null.html.md.erb
+++ b/source/documentation/values/null.html.md.erb
@@ -7,12 +7,18 @@ introduction: >
---
<% example(autogen_css: false) do %>
- @debug str-index("Helvetica Neue", "Roboto"); // null
- @debug map-get(("large": 20px), "small"); // null
+ @use "sass:map";
+ @use "sass:string";
+
+ @debug string.index("Helvetica Neue", "Roboto"); // null
+ @debug map.get(("large": 20px), "small"); // null
@debug &; // null
===
- @debug str-index("Helvetica Neue", "Roboto") // null
- @debug map-get(("large": 20px), "small") // null
+ @use "sass:map";
+ @use "sass:string";
+
+ @debug string.index("Helvetica Neue", "Roboto") // null
+ @debug map.get(("large": 20px), "small") // null
@debug & // null
<% end %>
@@ -62,6 +68,6 @@ If a property value is `null`, that property is omitted entirely.
[*falsey*]: ../at-rules/control/if#truthiness-and-falsiness
[operators]: ../operators/boolean
[`@if`]: ../at-rules/control/if
-[`if()`]: ../functions#if
+[`if()`]: ../modules#if
<%= partial 'code-snippets/example-if-parent-selector' %>
diff --git a/source/documentation/values/numbers.html.md.erb b/source/documentation/values/numbers.html.md.erb
index bc945f75e..2bbdcd793 100644
--- a/source/documentation/values/numbers.html.md.erb
+++ b/source/documentation/values/numbers.html.md.erb
@@ -61,12 +61,12 @@ means a few different things:
they're the same up to the tenth digit after the decimal point.
* If a number is less than `0.0000000001` away from an integer, it's considered
- to be an integer for the purposes of functions like [`nth()`][] that require
+ to be an integer for the purposes of functions like [`list.nth()`][] that require
integer arguments.
[`==`]: ../operators/equality
[`>=`]: ../operators/relational
-[`nth()`]: ../functions/list#nth
+[`list.nth()`]: ../modules/list#nth
<% example(autogen_css: false) do %>
@debug 0.012345678912345; // 0.0123456789
diff --git a/source/documentation/values/strings.html.md.erb b/source/documentation/values/strings.html.md.erb
index 8b794f387..a925486ca 100644
--- a/source/documentation/values/strings.html.md.erb
+++ b/source/documentation/values/strings.html.md.erb
@@ -11,19 +11,23 @@ introduction: >
---
<% fun_fact do %>
- You can convert a quoted string to an unquoted string using the [`unquote()`
- function][], and you can convert an unquoted string to a quoted string using
- the [`quote()` function][].
+ You can convert a quoted string to an unquoted string using the
+ [`string.unquote()` function][], and you can convert an unquoted string to a
+ quoted string using the [`string.quote()` function][].
- [`unquote()` function]: ../functions/string#unquote
- [`quote()` function]: ../functions/string#quote
+ [`string.unquote()` function]: ../modules/string#unquote
+ [`string.quote()` function]: ../modules/string#quote
<% example(autogen_css: false) do %>
- @debug unquote(".widget:hover"); // .widget:hover
- @debug quote(bold); // "bold"
+ @use "sass:string";
+
+ @debug string.unquote(".widget:hover"); // .widget:hover
+ @debug string.quote(bold); // "bold"
===
- @debug unquote(".widget:hover") // .widget:hover
- @debug quote(bold) // "bold"
+ @use "sass:string"
+
+ @debug string.unquote(".widget:hover") // .widget:hover
+ @debug string.quote(bold) // "bold"
<% end %>
<% end %>
@@ -182,16 +186,20 @@ code point, whether it's escaped or unescaped:
* Otherwise, the lowercase Unicode escape is included with a trailing space. For
example, `\7Fx` returns the unquoted string `\7f x`.
-<% example do %>
+<% example(autogen_css: false) do %>
+ @use "sass:string";
+
@debug \1F46D; // 👭
@debug \21; // \!
@debug \7Fx; // \7f x
- @debug str-length(\7Fx); // 5
+ @debug string.length(\7Fx); // 5
===
+ @use "sass:string"
+
@debug \1F46D // 👭
@debug \21 // \!
@debug \7Fx // \7f x
- @debug str-length(\7Fx) // 5
+ @debug string.length(\7Fx) // 5
<% end %>
## String Indexes
@@ -203,14 +211,18 @@ languages where indexes start at 0! Sass also makes it easy to refer to the end
of a string. The index -1 refers to the last character in a string, -2 refers to
the second-to-last, and so on.
-[string functions]: ../functions/string
+[string functions]: ../modules/string
-<% example do %>
- @debug str-index("Helvetica Neue", "Helvetica"); // 1
- @debug str-index("Helvetica Neue", "Neue"); // 11
- @debug str-slice("Roboto Mono", -4); // "Mono"
+<% example(autogen_css: false) do %>
+ @use "sass:string";
+
+ @debug string.index("Helvetica Neue", "Helvetica"); // 1
+ @debug string.index("Helvetica Neue", "Neue"); // 11
+ @debug string.slice("Roboto Mono", -4); // "Mono"
===
- @debug str-index("Helvetica Neue", "Helvetica") // 1
- @debug str-index("Helvetica Neue", "Neue") // 11
- @debug str-slice("Roboto Mono", -4) // "Mono"
+ @use "sass:string"
+
+ @debug string.index("Helvetica Neue", "Helvetica") // 1
+ @debug string.index("Helvetica Neue", "Neue") // 11
+ @debug string.slice("Roboto Mono", -4) // "Mono"
<% end %>
diff --git a/source/documentation/variables.html.md.erb b/source/documentation/variables.html.md.erb
index bf0e2ee91..922c1a478 100644
--- a/source/documentation/variables.html.md.erb
+++ b/source/documentation/variables.html.md.erb
@@ -83,61 +83,39 @@ variable, just include it in a value.
Normally when you assign a value to a variable, if that variable already had a
value, its old value is overwritten. But if you're writing a Sass library, you
-might want to allow your users to customize your library's variables before you
+might want to allow your users to configure your library's variables before you
use them to generate CSS.
To make this possible, Sass provides the `!default` flag. This assigns a value
to a variable *only if* that variable isn't defined or its value is [`null`][].
-Otherwise, the existing value will be used. This way, users can set variables
-before they import your library to customize its behavior.
+Otherwise, the existing value will be used.
[`null`]: values/null
-<% example do %>
- // _library.scss
- $black: #000 !default;
- $border-radius: 0.25rem !default;
- $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;
-
- code {
- border-radius: $border-radius;
- box-shadow: $box-shadow;
- }
- ---
- // style.scss
- $black: #222;
- $border-radius: 0.1rem;
+### Configuring Modules
- @import 'library';
- ===
- // _library.sass
- $black: #000 !default
- $border-radius: 0.25rem !default
- $box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default
-
- code
- border-radius: $border-radius
- box-shadow: $box-shadow
- ---
- // style.sass
- $black: #222
- $border-radius: 0.1rem
-
- @import 'library'
- ===
- code {
- border-radius: 0.1rem;
- box-shadow: 0 0.5rem 1rem rgba(#222, 0.15);
- }
-<% end %>
+<%= partial 'snippets/module-system-status' %>
+
+Variables defined with `!default` can be configured when loading a module with
+the [`@use` rule][]. Sass libraries often use `!default` variables to allow
+their users to configure the library's CSS.
+
+[`@use` rule]: at-rules/use
+
+To load a module with configuration, write `@use with (:
+, : )`. The configured values will override the
+variables' default values. Only variables written at the top level of the
+stylesheet with a `!default` flag can be configured.
+
+<%= partial '../code-snippets/example-use-with' %>
## Scope
Variables declared at the top level of a stylesheet are *global*. This means
-that they can be accessed anywhere after they've been declared—even in another
-stylesheet! But that's not true for all variables. Those declared in blocks
-(curly braces in SCSS or indented code in Sass) are usually *local*, and can
-only be accessed within the block they were declared.
+that they can be accessed anywhere in their module after they've been declared.
+But that's not true for all variables. Those declared in blocks (curly braces in
+SCSS or indented code in Sass) are usually *local*, and can only be accessed
+within the block they were declared.
<% example do %>
$global-variable: global value;
@@ -291,12 +269,13 @@ assign a value to a variable, or build up a value as part of a loop.
## Advanced Variable Functions
The Sass core library provides a couple advanced functions for working with
-variables. The [`variable-exists()` function][] returns whether a variable with
-the given name exists in the current scope, and the [`global-variable-exists()`
-function][] does the same but only for the global scope.
+variables. The [`meta.variable-exists()` function][] returns whether a variable
+with the given name exists in the current scope, and the
+[`meta.global-variable-exists()` function][] does the same but only for the
+global scope.
-[`variable-exists()` function]: functions/meta#variable-exists
-[`global-variable-exists()` function]: functions/meta#global-variable-exists
+[`meta.variable-exists()` function]: modules/meta#variable-exists
+[`meta.global-variable-exists()` function]: modules/meta#global-variable-exists
<% heads_up do %>
Users occasionally want to use interpolation to define a variable name based
@@ -308,6 +287,8 @@ function][] does the same but only for the global scope.
[map]: values/maps
<% example do %>
+ @use "sass:map";
+
$theme-colors: (
"success": #28a745,
"info": #17a2b8,
@@ -316,13 +297,19 @@ function][] does the same but only for the global scope.
.alert {
// Instead of $theme-color-#{warning}
- background-color: map-get($theme-colors, "warning");
+ background-color: map.get($theme-colors, "warning");
}
===
+ @use "sass:map"
+
$theme-colors: ("success": #28a745, "info": #17a2b8, "warning": #ffc107)
.alert
// Instead of $theme-color-#{warning}
- background-color: map-get($theme-colors, "warning")
+ background-color: map.get($theme-colors, "warning")
+ ===
+ .alert {
+ background-color: #ffc107;
+ }
<% end %>
<% end %>
diff --git a/source/guide.html.haml b/source/guide.html.haml
index 2eda441c3..3a5e1b86d 100644
--- a/source/guide.html.haml
+++ b/source/guide.html.haml
@@ -15,7 +15,7 @@ introduction: >
- [Variables](#topic-2)
- [Nesting](#topic-3)
- [Partials](#topic-4)
- - [Import](#topic-5)
+ - [Modules](#topic-5)
- [Mixins](#topic-6)
- [Inheritance](#topic-7)
- [Operators](#topic-8)
@@ -158,72 +158,72 @@ introduction: >
Sass file named with a leading underscore. You might name it something
like `_partial.scss`. The underscore lets Sass know that the file is only
a partial file and that it should not be generated into a CSS file. Sass
- partials are used with the `@import` directive.
+ partials are used with the `@use` rule.
---
%section#topic-5
- :markdown
- ## Import
+ %h2 Modules
+ = partial 'documentation/snippets/module-system-status'
- CSS has an import option that lets you split your CSS into smaller, more
- maintainable portions. The only drawback is that each time you use
- `@import` in CSS it creates another HTTP request. Sass builds on top of
- the current CSS `@import` but instead of requiring an HTTP request, Sass
- will take the file that you want to import and combine it with the file
- you're importing into so you can serve a single CSS file to the web browser.
+ :markdown
+ You don't have to write all your Sass in a single file. You can split it up
+ however you want with the `@use` rule. This rule loads another Sass file as
+ a *module*, which means you can refer to its variables, [mixins][], and
+ [functions][] in your Sass file with a namespace based on the filename.
+ Using a file will also include the CSS it generates in your compiled output!
- Let's say you have a couple of Sass files, `_reset.scss` and `base.scss`.
- We want to import `_reset.scss` into `base.scss`.
+ [mixins]: #topic-6
+ [functions]: documentation/at-rules/function
- example do
:plain
- // _reset.scss
- html,
- body,
- ul,
- ol {
- margin: 0;
- padding: 0;
+ // _base.scss
+ $font-stack: Helvetica, sans-serif;
+ $primary-color: #333;
+
+ body {
+ font: 100% $font-stack;
+ color: $primary-color;
}
---
- // base.scss
- @import 'reset';
- body {
- font: 100% Helvetica, sans-serif;
- background-color: #efefef;
+ // styles.scss
+ @use 'base';
+
+ .inverse {
+ background-color: base.$primary-color;
+ color: white;
}
===
- // _reset.sass
- html,
- body,
- ul,
- ol
- margin: 0
- padding: 0
- ---
- // base.sass
- @import reset
+ // _base.sass
+ $font-stack: Helvetica, sans-serif
+ $primary-color: #333
+
body
- font: 100% Helvetica, sans-serif
- background-color: #efefef
+ font: 100% $font-stack
+ color: $primary-color
+ ---
+ // styles.sass
+ @use 'base'
+
+ .inverse
+ background-color: base.$primary-color
+ color: white
===
- html,
- body,
- ul,
- ol {
- margin: 0;
- padding: 0;
- }
body {
font: 100% Helvetica, sans-serif;
- background-color: #efefef;
+ color: #333;
+ }
+
+ .inverse {
+ background-color: #333;
+ color: white;
}
:markdown
- Notice we're using `@import 'reset';` in the `base.scss` file. When you
- import a file you don't need to include the file extension `.scss`. Sass
- is smart and will figure it out for you.
+ Notice we're using `@use 'reset';` in the `base.scss` file. When you use a
+ file you don't need to include the file extension. Sass is smart and will
+ figure it out for you.
---
diff --git a/source/layouts/has_both_sidebars.haml b/source/layouts/has_both_sidebars.haml
index 9afb64fb7..de6ef2a45 100644
--- a/source/layouts/has_both_sidebars.haml
+++ b/source/layouts/has_both_sidebars.haml
@@ -16,6 +16,7 @@
- container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small'
- container << ' sl-l-container--overview' if current_page.data.intro
%div{class: container}
+ = yield_content :before_introduction
- if current_page.data.introduction
- center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : ''
.sl-c-introduction{class: center_introduction}
diff --git a/source/layouts/has_complementary.haml b/source/layouts/has_complementary.haml
index c6250f3d1..2da3c0888 100644
--- a/source/layouts/has_complementary.haml
+++ b/source/layouts/has_complementary.haml
@@ -4,6 +4,7 @@
.sl-l-large-holy-grail__main
- container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small'
%div{class: container}
+ = yield_content :before_introduction
- if current_page.data.introduction
- center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : ''
.sl-c-introduction{class: center_introduction}
diff --git a/source/layouts/has_navigation.haml b/source/layouts/has_navigation.haml
index a2077668b..913878972 100644
--- a/source/layouts/has_navigation.haml
+++ b/source/layouts/has_navigation.haml
@@ -7,6 +7,7 @@
.sl-l-medium-holy-grail__main
- container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small'
%div{class: container}
+ = yield_content :before_introduction
- if current_page.data.introduction
- center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : ''
.sl-c-introduction{class: center_introduction}
diff --git a/source/layouts/has_no_sidebars.haml b/source/layouts/has_no_sidebars.haml
index 68c196a95..c508bd08d 100644
--- a/source/layouts/has_no_sidebars.haml
+++ b/source/layouts/has_no_sidebars.haml
@@ -1,6 +1,7 @@
= wrap_layout :layout do
- container = current_page.data.no_container ? '' : 'sl-l-container sl-l-container--small'
.docSearch-content{class: container}
+ = yield_content :before_introduction
- if current_page.data.introduction
- center_introduction = current_page.data.center_introduction ? 'sl-c-introduction--center' : ''
.sl-c-introduction{class: center_introduction}
diff --git a/source/layouts/layout.haml b/source/layouts/layout.haml
index 9f19c685b..c9062cfa6 100644
--- a/source/layouts/layout.haml
+++ b/source/layouts/layout.haml
@@ -49,10 +49,10 @@
.sl-c-alert.sl-c-alert--info
.sl-l-container
%p
- %strong Your laptop needs more Sass.
- = succeed '.' do
- = link_to 'http://devswag.com/products/sass-stickers-4' do
- Grab a set of Sass stickers now
+ %strong Sass just launched a brand new module system.
+ = succeed '!' do
+ = link_to '/blog/7858341-the-module-system-is-launched' do
+ Learn all about it on the Sass blog
.sl-c-pop-stripe