diff --git a/source/documentation/modules/map.html.md.erb b/source/documentation/modules/map.html.md.erb
index d40c921bd..eca404c83 100644
--- a/source/documentation/modules/map.html.md.erb
+++ b/source/documentation/modules/map.html.md.erb
@@ -4,21 +4,194 @@ title: sass:map
<%= partial '../snippets/built-in-module-status' %>
-<% function 'map.get($map, $key)', 'map-get($map, $key)' do %>
- Returns the value in `$map` associated with `$key`.
+<% fun_fact do %>
+ Sass libraries and design systems tend to share and override configurations
+ that are represented as nested maps (maps that contain maps that contain
+ maps).
- If `$map` doesn't have a value associated with `$key`, returns [`null`][].
+ To help you work with nested maps, some map functions support deep
+ operations. For example, if you pass multiple keys to `map.get()`, it will
+ follow those keys to find the desired nested map:
- [`null`]: ../values/null
+ <% example(autogen_css: false) do %>
+ $config: (a: (b: (c: d)));
+ @debug map.get($config, a, b, c)); // d
+ ===
+ $config: (a: (b: (c: d)))
+ @debug map.get($config, a, b, c)) // d
+ <% end %>
+<% end %>
+
+
+<% function 'map.deep-merge($map1, $map2)', returns: 'map' do %>
+ Identical to [`map.merge()`](#merge), except that nested map values are *also*
+ recursively merged.
+
+ <% example(autogen_css: false) do %>
+ $helvetica-light: (
+ "weights": (
+ "lightest": 100,
+ "light": 300
+ )
+ );
+ $helvetica-heavy: (
+ "weights": (
+ "medium": 500,
+ "bold": 700
+ )
+ );
+
+ @debug map.deep-merge($helvetica-light, $helvetica-heavy);
+ // (
+ // "weights": (
+ // "lightest": 100,
+ // "light": 300,
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ @debug map.merge($helvetica-light, $helvetica-heavy);
+ // (
+ // "weights": (
+ // "medium: 500,
+ // "bold": 700
+ // )
+ // )
+ ===
+ $helvetica-light: ("weights": ("lightest": 100, "light": 300))
+ $helvetica-heavy: ("weights": ("medium": 500, "bold": 700))
+
+ @debug map.deep-merge($helvetica-light, $helvetica-heavy)
+ // (
+ // "weights": (
+ // "lightest": 100,
+ // "light": 300,
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ @debug map.merge($helvetica-light, $helvetica-heavy);
+ // (
+ // "weights": (
+ // "medium: 500,
+ // "bold": 700
+ // )
+ // )
+ <% end %>
+<% end %>
+
+
+<% function 'map.deep-remove($map, $key, $keys...)',
+ returns: 'map' do %>
+ If `$keys` is empty, returns a copy of `$map` without a value associated with
+ `$key`.
+
+ <% example(autogen_css: false) do %>
+ $font-weights: ("regular": 400, "medium": 500, "bold": 700);
+
+ @debug map.deep-remove($font-weights, "regular");
+ // ("medium": 500, "bold": 700)
+ ===
+ $font-weights: ("regular": 400, "medium": 500, "bold": 700)
+
+ @debug map.deep-remove($font-weights, "regular")
+ // ("medium": 500, "bold": 700)
+ <% end %>
+
+ ---
+
+ If `$keys` is not empty, follows the set of keys including `$key` and
+ excluding the last key in `$keys`, from left to right, to find the nested map
+ targeted for updating.
+
+ Returns a copy of `$map` where the targeted map does not have a value
+ associated with the last key in `$keys`.
+
+ <% example(autogen_css: false) do %>
+ $fonts: (
+ "Helvetica": (
+ "weights": (
+ "regular": 400,
+ "medium": 500,
+ "bold": 700
+ )
+ )
+ );
+
+ @debug map.deep-remove($fonts, "Helvetica", "weights", "regular");
+ // (
+ // "Helvetica": (
+ // "weights: (
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ // )
+ ===
+ $fonts: ("Helvetica": ("weights": ("regular": 400, "medium": 500, "bold": 700)))
+
+ @debug map.deep-remove($fonts, "Helvetica", "weights", "regular")
+ // (
+ // "Helvetica": (
+ // "weights: (
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ // )
+ <% end %>
+<% end %>
+
+
+<% function 'map.get($map, $key, $keys...)',
+ 'map-get($map, $key, $keys...)' do %>
+ If `$keys` is empty, returns the value in `$map` associated with `$key`.
+
+ If `$map` doesn't have a value associated with `$key`, returns [`null`][].
<%= partial 'code-snippets/example-map-get' %>
+
+ ---
+
+ If `$keys` is not empty, follows the set of keys including `$key` and
+ excluding the last key in `$keys`, from left to right, to find the nested map
+ targeted for searching.
+
+ Returns the value in the targeted map associated with the last key in `$keys`.
+
+ Returns [`null`][] if the map does not have a value associated with the key,
+ or if any key in `$keys` is missing from a map or references a value that is
+ not a map.
+
+ <% example(autogen_css: false) do %>
+ $fonts: (
+ "Helvetica": (
+ "weights": (
+ "regular": 400,
+ "medium": 500,
+ "bold": 700
+ )
+ )
+ );
+
+ @debug map.get($fonts, "Helvetica", "weights", "regular"); // 400
+ @debug map.get($fonts, "Helvetica", "colors"); // null
+ ===
+ $fonts: ("Helvetica": ("weights": ("regular": 400, "medium": 500, "bold": 700)))
+
+ @debug map.get($fonts, "Helvetica", "weights", "regular") // 400
+ @debug map.get($fonts, "Helvetica", "colors") // null
+ <% end %>
+
+ [`null`]: ../values/null
<% end %>
-<% function 'map.has-key($map, $key)',
- 'map-has-key($map, $key)',
+<% function 'map.has-key($map, $key, $keys...)',
+ 'map-has-key($map, $key, $keys...)',
returns: 'boolean' do %>
- Returns whether `$map` contains a value associated with `$key`.
+ If `$keys` is empty, returns whether `$map` contains a value associated with
+ `$key`.
<% example(autogen_css: false) do %>
$font-weights: ("regular": 400, "medium": 500, "bold": 700);
@@ -28,8 +201,40 @@ title: sass:map
===
$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 %>
+
+ ---
+
+ If `$keys` is not empty, follows the set of keys including `$key` and
+ excluding the last key in `$keys`, from left to right, to find the nested map
+ targeted for searching.
+
+ Returns true if the targeted map contains a value associated with the last key
+ in `$keys`.
+
+ Returns false if it does not, or if any key in `$keys` is missing from a map
+ or references a value that is not a map.
+
+ <% example(autogen_css: false) do %>
+ $fonts: (
+ "Helvetica": (
+ "weights": (
+ "regular": 400,
+ "medium": 500,
+ "bold": 700
+ )
+ )
+ );
+
+ @debug map.has-key($fonts, "Helvetica", "weights", "regular"); // true
+ @debug map.has-key($fonts, "Helvetica", "colors"); // false
+ ===
+ $fonts: ("Helvetica": ("weights": ("regular": 400, "medium": 500, "bold": 700)))
+
+ @debug map.has-key($fonts, "Helvetica", "weights", "regular") // true
+ @debug map.has-key($fonts, "Helvetica", "colors") // false
<% end %>
<% end %>
@@ -51,55 +256,84 @@ title: sass:map
<% function 'map.merge($map1, $map2)',
'map-merge($map1, $map2)',
+ 'map.merge($map1, $keys..., $map2)',
+ 'map-merge($map1, $keys..., $map2)',
returns: 'map' do %>
- Returns a new map with all the keys and values from both `$map1` and `$map2`.
+ <% heads_up do %>
+ In practice, the actual arguments to `map.merge($map1, $keys..., $map2)`
+ are passed as `map.set($map1, $args...). They are described here as `$map1,
+ $keys..., $map2` for explanation purposes only.
+ <% end %>
- This can also be used to add a new value or overrwrite a value in `$map1`, by
- passing a single key/value pair as `$map2`.
+ If no `$keys` are passed, returns a new map with all the keys and values from
+ both `$map1` and `$map2`.
- If both `$map1` and `$map2` have the same key, `$map2`'s value takes precedence.
+ If both `$map1` and `$map2` have the same key, `$map2`'s value takes
+ precedence.
- All keys in the returned map that also appear in `$map1` have the same order as
- in `$map1`. New keys from `$map2` appear at the end of the map.
+ All keys in the returned map that also appear in `$map1` have the same order
+ as in `$map1`. New keys from `$map2` appear at the end of the map.
<% example(autogen_css: false) do %>
$light-weights: ("lightest": 100, "light": 300);
$heavy-weights: ("medium": 500, "bold": 700);
@debug map.merge($light-weights, $heavy-weights);
- // (
- // "lightest": 100,
- // "light": 300,
- // "medium": 500,
- // "bold": 700
- // )
-
- // 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));
- // ("lightest": 100, "light": 200)
+ // ("lightest": 100, "light": 300, "medium": 500, "bold": 700)
===
$light-weights: ("lightest": 100, "light": 300)
$heavy-weights: ("medium": 500, "bold": 700)
@debug map.merge($light-weights, $heavy-weights)
+ // ("lightest": 100, "light": 300, "medium": 500, "bold": 700)
+ <% end %>
+
+ ---
+
+ If `$keys` is not empty, follows the `$keys` to find the nested map targeted
+ for merging. If any key in `$keys` is missing from a map or references a value
+ that is not a map, sets the value at that key to an empty map.
+
+ Returns a copy of `$map1` where the targeted map is replaced by a new map that
+ contains all the keys and values from both the targeted map and `$map2`.
+
+ <% example(autogen_css: false) do %>
+ $fonts: (
+ "Helvetica": (
+ "weights": (
+ "lightest": 100,
+ "light": 300
+ )
+ )
+ );
+ $heavy-weights: ("medium": 500, "bold": 700);
+
+ @debug map.merge($fonts, "Helvetica", "weights", $heavy-weights);
// (
- // "lightest": 100,
- // "light": 300,
- // "medium": 500,
- // "bold": 700
+ // "Helvetica": (
+ // "weights": (
+ // "lightest": 100,
+ // "light": 300,
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
// )
+ ===
+ $fonts: ("Helvetica": ("weights": ("lightest": 100, "light": 300)))
+ $heavy-weights: ("medium": 500, "bold": 700)
- // 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))
- // ("lightest": 100, "light": 200)
+ @debug map.merge($fonts, "Helvetica", "weights", $heavy-weights)
+ // (
+ // "Helvetica": (
+ // "weights": (
+ // "lightest": 100,
+ // "light": 300,
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ // )
<% end %>
<% end %>
@@ -129,6 +363,77 @@ title: sass:map
<% end %>
+<% function 'map.set($map, $key, $value)',
+ 'map.set($map, $keys..., $key, $value)',
+ returns: 'map' do %>
+ <% heads_up do %>
+ In practice, the actual arguments to `map.set($map, $keys..., $key, $value)`
+ are passed as `map.set($map, $args...). They are described here as `$map,
+ $keys..., $key, $value` for explanation purposes only.
+ <% end %>
+
+ If `$keys` are not passed, returns a copy of `$map` with the value at `$key`
+ set to `$value`.
+
+ <% example(autogen_css: false) do %>
+ $font-weights: ("regular": 400, "medium": 500, "bold": 700);
+
+ @debug map.set($font-weights, "regular", 300);
+ // ("regular": 300, "medium": 500, "bold": 700)
+ ===
+ $font-weights: ("regular": 400, "medium": 500, "bold": 700)
+
+ @debug map.set($font-weights, "regular", 300)
+ // ("regular": 300, "medium": 500, "bold": 700)
+ <% end %>
+
+ ---
+
+ If `$keys` are passed, follows the `$keys` to find the nested map targeted for
+ updating. If any key in `$keys` is missing from a map or references a value
+ that is not a map, sets the value at that key to an empty map.
+
+ Returns a copy of `$map` with the targeted map's value at `$key` set to
+ `$value`.
+
+ <% example(autogen_css: false) do %>
+ $fonts: (
+ "Helvetica": (
+ "weights": (
+ "regular": 400,
+ "medium": 500,
+ "bold": 700
+ )
+ )
+ );
+
+ @debug map.set($fonts, "Helvetica", "weights", "regular", 300);
+ // (
+ // "Helvetica": (
+ // "weights": (
+ // "regular": 300,
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ // )
+ ===
+ $fonts: ("Helvetica": ("weights": ("regular": 400, "medium": 500, "bold": 700)))
+
+ @debug map.set($fonts, "Helvetica", "weights", "regular", 300)
+ // (
+ // "Helvetica": (
+ // "weights": (
+ // "regular": 300,
+ // "medium": 500,
+ // "bold": 700
+ // )
+ // )
+ // )
+ <% end %>
+<% end %>
+
+
<% function 'map.values($map)', 'map-values($map)', returns: 'list' do %>
Returns a comma-separated list of all the values in `$map`.
diff --git a/source/documentation/values/maps.html.md.erb b/source/documentation/values/maps.html.md.erb
index 0b6a3ac9f..7d089f941 100644
--- a/source/documentation/values/maps.html.md.erb
+++ b/source/documentation/values/maps.html.md.erb
@@ -68,55 +68,52 @@ 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
-new map that contains all the key/value pairs in *both* arguments.
+existing key. The [`map.set($map, $key, $value)` function][] does this: it
+returns a copy of `$map` with the value at `$key` set to `$value`.
-[`map.merge($map1, $map2)` function]: ../modules/map#merge
+[`map.set($map, $key, $value)` function]: ../modules/map#set
<% example(autogen_css: false) do %>
@use "sass:map";
- $light-weights: ("lightest": 100, "light": 300);
- $heavy-weights: ("medium": 500, "bold": 700);
+ $font-weights: ("regular": 400, "medium": 500, "bold": 700);
- @debug map.merge($light-weights, $heavy-weights);
- // (
- // "lightest": 100,
- // "light": 300,
- // "medium": 500,
- // "bold": 700
- // )
+ @debug map.set($font-weights, "extra-bold", 900);
+ // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
+ @debug map.set($font-weights, "bold", 900);
+ // ("regular": 400, "medium": 500, "bold": 900)
===
@use "sass:map"
- $light-weights: ("lightest": 100, "light": 300)
- $heavy-weights: ("medium": 500, "bold": 700)
+ $font-weights: ("regular": 400, "medium": 500, "bold": 700)
- @debug map.merge($light-weights, $heavy-weights)
- // (
- // "lightest": 100,
- // "light": 300,
- // "medium": 500,
- // "bold": 700
- // )
+ @debug map.set($font-weights, "extra-bold": 900)
+ // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
+ @debug map.set($font-weights, "bold", 900)
+ // ("regular": 400, "medium": 500, "bold": 900)
<% end %>
-`map.merge()` is often used with an inline map to add a single key/value pair.
+Instead of setting values one-by-one, you can also merge two existing maps using
+[`map.merge($map1, $map2)`][].
+
+[`map.merge($map1, $map2)` function]: ../modules/map#merge
<% example(autogen_css: false) do %>
@use "sass:map";
- $font-weights: ("regular": 400, "medium": 500, "bold": 700);
+ $light-weights: ("lightest": 100, "light": 300);
+ $heavy-weights: ("medium": 500, "bold": 700);
- @debug map.merge($font-weights, ("extra-bold": 900));
- // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
+ @debug map.merge($light-weights, $heavy-weights);
+ // ("lightest": 100, "light": 300, "medium": 500, "bold": 700)
===
@use "sass:map"
- $font-weights: ("regular": 400, "medium": 500, "bold": 700)
+ $light-weights: ("lightest": 100, "light": 300)
+ $heavy-weights: ("medium": 500, "bold": 700)
- @debug map.merge($font-weights, ("extra-bold": 900))
- // ("regular": 400, "medium": 500, "bold": 700, "extra-bold": 900)
+ @debug map.merge($light-weights, $heavy-weights)
+ // ("lightest": 100, "light": 300, "medium": 500, "bold": 700)
<% end %>
If both maps have the same keys, the second map's values are used in the map
@@ -125,21 +122,21 @@ that gets returned.
<% example(autogen_css: false) do %>
@use "sass:map";
- $font-weights: ("regular": 400, "medium": 500, "bold": 700);
+ $weights: ("light": 300, "medium": 500);
- @debug map.merge($font-weights, ("medium": 600));
- // ("regular": 400, "medium": 600, "bold": 700)
+ @debug map.merge($weights, ("medium": 700));
+ // ("light": 300, "medium": 700)
===
- @use "sass:map"
+ @use "sass:map";
- $font-weights: ("regular": 400, "medium": 500, "bold": 700)
+ $weights: ("light": 300, "medium": 500)
- @debug map.merge($font-weights, ("medium": 600))
- // ("regular": 400, "medium": 600, "bold": 700)
+ @debug map.merge($weights, ("medium": 700))
+ // ("light": 300, "medium": 700)
<% end %>
-Note that because Sass maps are [immutable][], `map.merge()` doesn't modify the
-original list.
+Note that because Sass maps are [immutable][], `map.set()` and `map.merge()` do
+not modify the original list.
[immutable]: #immutability