Repository: facelessuser/coloraide (language: python)

Issue:
Modern RGB, HSL, and HWB syntax should support mixing percentages and numbers
Old style RGB (comma delimited syntax) requires that you use either all percentages for color channels (alpha excluded) or all numbers. Modern RGB syntax (space delimited syntax) was recently updated to allow both percentages or numbers at the same time. I think this is a good change and will simplify modern syntax detections. We need to update the library to support this though.

Currently, RGB defaults on output to numbers, not percentages. Most people probably expect HSL and HWB to output based on percentages, not numbers. It isn't really supported in browsers yet. Either we make modern syntax default to percent output for compatibility, or we wait until browsers that support modern syntax support mixed percentages and numbers and then update and default to no percent.

Range of HSL and HWB percentage was chosen by CSS to be [0-100] not [0-1].


Discussion / hints:

Fix patch:
diff --git a/coloraide/__meta__.py b/coloraide/__meta__.py
index 2a8fe0959..a94fddcc7 100644
--- a/coloraide/__meta__.py
+++ b/coloraide/__meta__.py
@@ -193,5 +193,5 @@ def parse_version(ver: str) -> Version:
     return Version(major, minor, micro, release, pre, post, dev)
 
 
-__version_info__ = Version(1, 7, 1, "final")
+__version_info__ = Version(1, 8, 0, "final")
 __version__ = __version_info__._get_canonical()
diff --git a/coloraide/css/parse.py b/coloraide/css/parse.py
index e4d04cec0..bca132810 100644
--- a/coloraide/css/parse.py
+++ b/coloraide/css/parse.py
@@ -57,12 +57,8 @@
             \b(rgba?)\(\s*
             (?:
                 # Space separated format
-                (?:
-                    # Float form
-                    (?:{float}{space}){{2}}{float} |
-                    # Percent form
-                    (?:{percent}{space}){{2}}{percent}
-                )({slash}(?:{strict_percent}|{float}))? |
+                (?:{strict_percent}|{float})(?:{space}(?:{strict_percent}|{float})){{2}}
+                ({slash}(?:{strict_percent}|{float}))? |
                 # Comma separated format
                 (?:
                     # Float form
@@ -84,9 +80,9 @@
         \b(hsla?)\(\s*
         (?:
             # Space separated format
-            {angle}{space}{percent}{space}{percent}(?:{slash}(?:{strict_percent}|{float}))? |
+            {angle}(?:{space}(?:{strict_percent}|{float})){{2}}(?:{slash}(?:{strict_percent}|{float}))? |
             # comma separated format
-            {strict_angle}{comma}{strict_percent}{comma}{strict_percent}(?:{comma}(?:{strict_percent}|{strict_float}))?
+            {strict_angle}(?:{comma}{strict_percent}){{2}}(?:{comma}(?:{strict_percent}|{strict_float}))?
         )
         \s*\)
         """.format(**COLOR_PARTS)
@@ -96,7 +92,7 @@
         \b(hwb)\(\s*
         (?:
             # Space separated format
-            {angle}(?:{space}{percent}){{2}}(?:{slash}(?:{strict_percent}|{float}))?
+            {angle}(?:{space}(?:{strict_percent}|{float})){{2}}(?:{slash}(?:{strict_percent}|{float}))?
         )
         \s*\)
         """.format(**COLOR_PARTS)
@@ -180,7 +176,7 @@ def norm_percent_channel(string: str, scale: float = 100, offset: float = 0.0) -
 
 
 def norm_color_channel(string: str, scale: float = 1, offset: float = 0.0) -> float:
-    """Normalize percent channel."""
+    """Normalize percent/number channel."""
 
     if string.endswith('%'):
         return norm_percent_channel(string, scale, offset)
@@ -188,6 +184,16 @@ def norm_color_channel(string: str, scale: float = 1, offset: float = 0.0) -> fl
         return norm_float(string)
 
 
+def norm_scaled_color_channel(string: str, scale: float = 1, offset: float = 0.0) -> float:
+    """Normalize scaled percent/number channel."""
+
+    if string.endswith('%'):
+        return norm_percent_channel(string, scale, offset)
+    else:
+        value = norm_float(string)
+        return (value * scale * 0.01) - offset if scale != 100 else value
+
+
 def norm_rgb_channel(string: str, scale: float = 1) -> float:
     """Normalize RGB channel."""
 
@@ -259,8 +265,8 @@ def parse_rgb_channels(color: str, boundry: tuple[Channel, ...]) -> tuple[Vector
     return channels, alpha
 
 
-def parse_channels(color: str, boundry: tuple[Channel, ...]) -> tuple[Vector, float]:
-    """Parse CSS RGB format."""
+def parse_channels(color: str, boundry: tuple[Channel, ...], scaled: bool = False) -> tuple[Vector, float]:
+    """Parse CSS channel format."""
 
     channels = []
     alpha = 1.0
@@ -271,6 +277,8 @@ def parse_channels(color: str, boundry: tuple[Channel, ...]) -> tuple[Vector, fl
             bound = boundry[i]
             if bound.flags & FLG_ANGLE:
                 channels.append(norm_angle_channel(c))
+            elif scaled:
+                channels.append(norm_scaled_color_channel(c, bound.high))
             else:
                 channels.append(norm_color_channel(c, bound.high))
         elif i == length:
@@ -348,8 +356,9 @@ def parse_css(
                 )
     else:
         m = CSS_MATCH[cspace.NAME].match(string, start)
+        scaled = cspace.NAME in ('hsl', 'hwb')
         if m is not None and (not fullmatch or m.end(0) == len(string)):
-            return parse_channels(string[m.end(1) + 1:m.end(0) - 1], cspace.CHANNELS), m.end(0)
+            return parse_channels(string[m.end(1) + 1:m.end(0) - 1], cspace.CHANNELS, scaled=scaled), m.end(0)
 
     # If we wanted to support per color matching of this format, we could enable this.
     # It is much faster to generically match all `color(space ...)` instances and then
diff --git a/coloraide/css/serialize.py b/coloraide/css/serialize.py
index 33b629ec3..bfae6a5c7 100644
--- a/coloraide/css/serialize.py
+++ b/coloraide/css/serialize.py
@@ -5,7 +5,7 @@
 from .. import algebra as alg
 from . import parse
 from .color_names import to_name
-from ..channels import FLG_PERCENT, FLG_OPT_PERCENT
+from ..channels import FLG_PERCENT, FLG_OPT_PERCENT, FLG_ANGLE
 from ..types import Vector
 from typing import TYPE_CHECKING
 
@@ -52,7 +52,8 @@ def named_color_function(
     for idx, value in enumerate(coords):
         channel = channels[idx]
         use_percent = channel.flags & FLG_PERCENT or (percent and channel.flags & FLG_OPT_PERCENT)
-        if not use_percent:
+        is_angle = channel.flags & FLG_ANGLE
+        if not use_percent and not is_angle:
             value *= scale
         if idx != 0:
             string.append(COMMA if legacy else SPACE)
diff --git a/coloraide/spaces/hsl/__init__.py b/coloraide/spaces/hsl/__init__.py
index 248f832e6..047f92613 100644
--- a/coloraide/spaces/hsl/__init__.py
+++ b/coloraide/spaces/hsl/__init__.py
@@ -2,7 +2,7 @@
 from __future__ import annotations
 from ...spaces import Space, Cylindrical
 from ...cat import WHITES
-from ...channels import Channel, FLG_ANGLE, FLG_PERCENT
+from ...channels import Channel, FLG_ANGLE, FLG_OPT_PERCENT
 from ... import util
 from ... import algebra as alg
 from ...types import Vector
@@ -61,8 +61,8 @@ class HSL(Cylindrical, Space):
     SERIALIZE = ("--hsl",)
     CHANNELS = (
         Channel("h", 0.0, 360.0, bound=True, flags=FLG_ANGLE),
-        Channel("s", 0.0, 1.0, bound=True, flags=FLG_PERCENT),
-        Channel("l", 0.0, 1.0, bound=True, flags=FLG_PERCENT)
+        Channel("s", 0.0, 1.0, bound=True, flags=FLG_OPT_PERCENT),
+        Channel("l", 0.0, 1.0, bound=True, flags=FLG_OPT_PERCENT)
     )
     CHANNEL_ALIASES = {
         "hue": "h",
diff --git a/coloraide/spaces/hsl/css.py b/coloraide/spaces/hsl/css.py
index 861592837..e52aae4f7 100644
--- a/coloraide/spaces/hsl/css.py
+++ b/coloraide/spaces/hsl/css.py
@@ -22,6 +22,7 @@ def to_string(
         fit: str | bool = True,
         none: bool = False,
         color: bool = False,
+        percent: bool = True,
         comma: bool = False,
         **kwargs: Any
     ) -> str:
@@ -35,7 +36,9 @@ def to_string(
             fit=fit,
             none=none,
             color=color,
-            legacy=comma
+            legacy=comma,
+            percent=True if comma else percent,
+            scale=100
         )
 
     def match(
diff --git a/coloraide/spaces/hwb/__init__.py b/coloraide/spaces/hwb/__init__.py
index 82d63d782..025c0e342 100644
--- a/coloraide/spaces/hwb/__init__.py
+++ b/coloraide/spaces/hwb/__init__.py
@@ -2,7 +2,7 @@
 from __future__ import annotations
 from ...spaces import Space, Cylindrical
 from ...cat import WHITES
-from ...channels import Channel, FLG_ANGLE, FLG_PERCENT
+from ...channels import Channel, FLG_ANGLE, FLG_OPT_PERCENT
 from ... import algebra as alg
 from ...types import Vector
 
@@ -42,8 +42,8 @@ class HWB(Cylindrical, Space):
     SERIALIZE = ("--hwb",)
     CHANNELS = (
         Channel("h", 0.0, 360.0, bound=True, flags=FLG_ANGLE),
-        Channel("w", 0.0, 1.0, bound=True, flags=FLG_PERCENT),
-        Channel("b", 0.0, 1.0, bound=True, flags=FLG_PERCENT)
+        Channel("w", 0.0, 1.0, bound=True, flags=FLG_OPT_PERCENT),
+        Channel("b", 0.0, 1.0, bound=True, flags=FLG_OPT_PERCENT)
     )
     CHANNEL_ALIASES = {
         "hue": "h",
diff --git a/coloraide/spaces/hwb/css.py b/coloraide/spaces/hwb/css.py
index f7312d4c8..d781983cb 100644
--- a/coloraide/spaces/hwb/css.py
+++ b/coloraide/spaces/hwb/css.py
@@ -22,6 +22,7 @@ def to_string(
         fit: str | bool = True,
         none: bool = False,
         color: bool = False,
+        percent: bool = True,
         **kwargs: Any
     ) -> str:
         """Convert to CSS."""
@@ -33,7 +34,9 @@ def to_string(
             precision=precision,
             fit=fit,
             none=none,
-            color=color
+            color=color,
+            percent=percent,
+            scale=100
         )
 
     def match(
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 6cd9e2a69..93025e8f8 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -1,5 +1,13 @@
 # Changelog
 
+## 1.8.0
+
+- **NEW**: Modern sRGB, HSL, and HWB should allow mixed percentage and numbers. HSL and HWB percentages in the `hsl()`
+  and `hwb()` formats respectively will resolve to numbers in the range [0, 100]. These changes reflect the latest
+  changes in the CSS Level 4 Color spec.
+- **NEW**: HSL and HWB can serialize to a modern syntax that does not use percentages, but the default still uses
+  percentages.
+
 ## 1.7.1
 
 - **FIX**: Ensure CAM16 spaces mirrors positive and negative percentages for `a` and `b` components.
diff --git a/docs/src/markdown/colors/hsl.md b/docs/src/markdown/colors/hsl.md
index b67f6ccb9..147d2c8fb 100644
--- a/docs/src/markdown/colors/hsl.md
+++ b/docs/src/markdown/colors/hsl.md
@@ -72,6 +72,7 @@ Color("hsl", [0, 1, 0.5])
 Color("hsl", [38.824, 1, 0.5], ).to_string()
 Color("hsl", [60, 1, 0.5]).to_string(comma=True)
 Color("hsl", [120, 1, 0.25098]).to_string(color=True)
+Color("hsl", [240, 1, 0.5]).to_string(percent=False)
 ```
 
 ## Registering
diff --git a/docs/src/markdown/colors/hwb.md b/docs/src/markdown/colors/hwb.md
index f238c5ae8..d64e8e064 100644
--- a/docs/src/markdown/colors/hwb.md
+++ b/docs/src/markdown/colors/hwb.md
@@ -67,6 +67,8 @@ form, but the default string output will be the `#!css-color hwb(h s l / a)` for
 ```playground
 Color("hwb", [0, 0, 0])
 Color("hwb", [38.824, 0, 0]).to_string()
+Color("hwb", [60, 0, 0]).to_string(percent=False)
+Color("hwb", [120, 0, 0]).to_string(color=True)
 ```
 
 ## Registering
diff --git a/docs/src/markdown/strings.md b/docs/src/markdown/strings.md
index bbb13fa89..ba8037777 100644
--- a/docs/src/markdown/strings.md
+++ b/docs/src/markdown/strings.md
@@ -123,12 +123,15 @@ Color("rgb(30 75 100 / 20%)").to_string(comma=True)
 
 ### Percent
 
-RGB, CIELab, CIELCh, Oklab, and OkLCh can receive and output colors with optional percents for certain channels. This
-will output those channels in the range of [0%,100%] instead of their usual numeric value.
+RGB, HSL, HWB, CIELab, CIELCh, Oklab, and OkLCh can receive and output colors with optional percents for certain
+channels. By default, only HSL and HWB output channels with percents by default, and percentages for these color spaces
+can only be turned off when serializing to the modern syntax (space delimited). When percentage is enabled, ranges will
+be output in the range of [0%,100%] instead of their usual numeric value.
 
 ```playground
 Color("rebeccapurple").to_string(percent=True)
 Color("rebeccapurple").convert('lab').to_string(percent=True)
+Color("rebeccapurple").convert('hsl').to_string(percent=False)
 ```
 
 ## sRGB Specific Options
diff --git a/docs/src/mkdocs.yml b/docs/src/mkdocs.yml
index b2cca97bb..bff3c6d89 100644
--- a/docs/src/mkdocs.yml
+++ b/docs/src/mkdocs.yml
@@ -138,9 +138,9 @@ nav:
       - Contributing &amp; Support: about/contributing.md
       - Acknowledgments: about/acknowledgments.md
       - Changelog: about/changelog.md
+      - License: about/license.md
       - Migration Notes:
           - '1.0': about/releases/1.0.md
-      - License: about/license.md
 
 markdown_extensions:
   - markdown.extensions.toc:
@@ -229,7 +229,7 @@ extra_css:
   - assets/coloraide-extras/extra.css
 extra_javascript:
   - https://unpkg.com/mermaid@8.13.3/dist/mermaid.min.js
-  - playground-config-fe55101c.js
+  - playground-config-c68b7434.js
   - https://cdn.jsdelivr.net/pyodide/v0.22.1/full/pyodide.js
   - assets/coloraide-extras/extra-notebook.js
 
@@ -244,6 +244,7 @@ plugins:
   - search
   - git-revision-date-localized:
       fallback_to_build_date: true
+      strict: false
   - mkdocs_pymdownx_material_extras
   - minify:
       minify_html: true
diff --git a/docs/theme/assets/coloraide-extras/extra-notebook-a6f6be1b.js.map b/docs/theme/assets/coloraide-extras/extra-notebook-a6f6be1b.js.map
index 906439292..9b7061b19 100644
--- a/docs/theme/assets/coloraide-extras/extra-notebook-a6f6be1b.js.map
+++ b/docs/theme/assets/coloraide-extras/extra-notebook-a6f6be1b.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"extra-notebook-a6f6be1b.js","sources":["extra-notebook.js"],"sourcesContent":["(() => {\n  let pyodide = null\n  let busy = false\n  let raw = \"\"\n  let gist = \"\"\n  let editTemp = {}\n  const reIdNum = /.*?_(\\d+)$/\n  let initialized = false\n  let lastSearch = \"\"\n  let fake = false\n  const tabStart = /^( {1,4}|\\t)/\n  // This is the Python payload that will be executed when the user\n  // presses the `Run` button. It will execute the code, create a\n  // Python console output, find color references, steps, and interpolation\n  // references and render the appropriate preview.\n  const pycode = `\n{{pycode}}\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback()\n`\n\n  const defContent = window.colorNotebook.defaultPlayground\n\n  const getContent = content => {\n    return `\n!!! new \"This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). \\\nLearn more [here](\\\n?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md\\\n). Preview, convert, interpolate, and explore!\"\n\n\\`\\`\\`\\`\\`\\`\\`\\`playground\n${content}\n\\`\\`\\`\\`\\`\\`\\`\\`\n`\n  }\n\n  let notebookInstalled = false\n  let playgroundInstalled = false\n\n  const fakeDOMContentLoaded = () => {\n    // Send a fake `DOMContentLoaded`\n    fake = true\n    window.document.dispatchEvent(new Event(\"DOMContentLoaded\", {\n      bubbles: true,\n      cancelable: true\n    }))\n    window.document$.next()\n  }\n\n  const textResize = inpt => {\n    // Resize inputs based on text height.\n\n    const scrollLeft = window.pageXOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollLeft\n\n    const scrollTop  = window.pageYOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollTop\n\n    inpt.style.height = \"5px\"\n    inpt.style.height = `${inpt.scrollHeight}px`\n\n    window.scrollTo(scrollLeft, scrollTop)\n  }\n\n  const encodeuri = uri => {\n    // Encode the URI component.\n\n    return encodeURIComponent(uri).replace(/[.!'()*]/g, c => {\n      return `%${c.charCodeAt(0).toString(16)}`\n    })\n  }\n\n  const pyexecute = async currentID => {\n    // Execute Python code inside a playground\n\n    const currentInputs = document.getElementById(`__playground-inputs_${currentID}`)\n    currentInputs.setAttribute(\"readonly\", \"\")\n    pyodide.globals.set(\"id_num\", currentID)\n    pyodide.globals.set(\"action\", \"playground\")\n    await pyodide.runPythonAsync(pycode)\n    currentInputs.removeAttribute(\"readonly\")\n  }\n\n  const pyrender = async text => {\n    // Render an entire notebook page\n\n    pyodide.globals.set(\"content\", text)\n    pyodide.globals.set(\"action\", \"notebook\")\n    await pyodide.runPythonAsync(pycode)\n    const src = document.getElementById(\"__notebook-input\")\n    if (src) {\n      raw = text\n      src.value = text\n    }\n    if (window.location.hash) {\n      // Force jumping to hashes\n      window.location.href = window.location.href // eslint-disable-line no-self-assign\n    }\n  }\n\n  const setupPyodide = async full => {\n    // Load `Pyodide` and the any default packages we can need and can load.\n\n    if (!initialized) {\n      initialized = true\n      pyodide = await loadPyodide({ // eslint-disable-line no-undef\n        indexURL: \"https://cdn.jsdelivr.net/pyodide/v0.22.1/full/\",\n        fullStdLib: false\n      })\n    }\n\n    if ((!notebookInstalled && full) || (!playgroundInstalled && !full)) {\n      const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`\n      const packages = (full) ? window.colorNotebook.notebookWheels : window.colorNotebook.playgroundWheels\n      const installs = []\n      if (full) {\n        notebookInstalled = true\n      } else {\n        playgroundInstalled = true\n      }\n      for (const s of packages) {\n        installs.push(base + s)\n      }\n      await pyodide.loadPackage(installs)\n    }\n  }\n\n  const showBusy = (target, label, relative) => {\n    // Show busy indicator\n\n    const loaderLabel = (typeof label === \"undefined\" || label === null) ? \"Loading...\" : label\n    const classes = relative ? \"loading relative\" : \"loading\"\n    const template = document.createElement(\"template\")\n    template.innerHTML = `<div class=\"${classes}\"><div class=\"loader\"></div><div>${loaderLabel}</div></div>`\n    target.appendChild(template.content.firstChild)\n  }\n\n  const hideBusy = target => {\n    // Hide busy indicator\n\n    const loading = target.querySelector(\".loading\")\n    if (loading) {\n      target.removeChild(target.querySelector(\".loading\"))\n    }\n  }\n\n  const popState = () => {\n    // Handle notebook history\n\n    const base = window.location.pathname.split('/')[1]\n    if (\n      window.location.pathname === `/${base}/playground/`\n    ) {\n      const current = decodeURIComponent(new URLSearchParams(window.location.search).toString())\n      if (current !== lastSearch) {\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const interceptClickEvent = e => {\n    // Catch links to other notebook pages and handle them\n\n    const base = window.location.pathname.split('/')[1]\n    const target = e.target || e.srcElement\n    if (target.tagName === \"A\" && main) { // eslint-disable-line no-use-before-define\n      if (\n        target.getAttribute(\"href\") &&\n        target.host === window.location.host &&\n        window.location.pathname === `/${base}/playground/\"` &&\n        window.location.pathname === target.pathname &&\n        window.location.search !== target.search\n      ) {\n        e.preventDefault()\n        const search = new URLSearchParams(target.search)\n        const state = {}\n        for (const [key, value] of search) {\n          state[key] = value\n        }\n        history.pushState(state, \"\", target.href)\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const handleTab = e => {\n    // Prevent tab from tabbing out.\n\n    if (e.key === 'Tab') {\n      const target = e.target\n\n      if (target.selectionStart !== target.selectionEnd) {\n        e.preventDefault()\n\n        let start = target.selectionStart\n        let end = target.selectionEnd\n\n        const text = target.value\n\n        while (start > 0 && text[start - 1] !== '\\n') {\n          start--\n        }\n        while (end > 0 && text[end - 1] !== '\\n' && end < text.length) {\n          end++\n        }\n\n        let lines = text.substr(start, end - start).split('\\n')\n\n        for (let i = 0; i < lines.length; i++) {\n\n          // Don't indent last line if cursor at start of line\n          if (i === lines.length - 1 && lines[i].length === 0) {\n            continue\n          }\n\n          // Indent or deindent\n          if (e.shiftKey) {\n            lines[i] = lines[i].replace(tabStart, '')\n          } else {\n            lines[i] = `    ${lines[i]}`\n          }\n        }\n        lines = lines.join('\\n')\n\n        // Update the text area\n        target.value = text.substr(0, start) + lines + text.substr(end)\n        target.selectionStart = start\n        target.selectionEnd = start + lines.length\n      }\n    }\n  }\n\n  const init = async first => {\n    // Setup input highlighting and events to run Python code blocks.\n\n    const notebook = document.getElementById(\"__notebook-source\")\n    const playgrounds = document.querySelectorAll(\".playground\")\n    playgrounds.forEach(pg => {\n\n      const currentID = pg.id.replace(reIdNum, \"$1\")\n      const inputs = document.getElementById(`__playground-inputs_${currentID}`)\n      const results = document.getElementById(`__playground-results_${currentID}`)\n      const pgcode = document.getElementById(`__playground-code_${currentID}`)\n      const buttonEdit = document.querySelector(`button#__playground-edit_${currentID}`)\n      const buttonShare = document.querySelector(`button#__playground-share_${currentID}`)\n      const buttonRun = document.querySelector(`button#__playground-run_${currentID}`)\n      const buttonCancel = document.querySelector(`button#__playground-cancel_${currentID}`)\n\n      inputs.addEventListener(\"input\", () => {\n        // Adjust textarea height on text input.\n\n        textResize(inputs)\n      })\n\n      inputs.addEventListener('keydown', handleTab)\n\n      if (notebook && first) {\n        const notebookInput = document.getElementById(\"__notebook-input\")\n\n        notebookInput.addEventListener(\"input\", e => {\n          // Adjust textarea height on text input.\n\n          textResize(e.target)\n        })\n\n        notebookInput.addEventListener('keydown', handleTab)\n\n        const editPage = document.getElementById(\"__notebook-edit\")\n        editPage.addEventListener(\"click\", () => {\n          editTemp[notebookInput.id] = notebookInput.value\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          textResize(document.getElementById(\"__notebook-input\"))\n        })\n\n        document.getElementById(\"__notebook-md-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter link to the Markdown page source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({notebook: uri}, \"\", `?${new URLSearchParams(`notebook=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-py-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter the link to the Python code source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({source: uri}, \"\", `?${new URLSearchParams(`source=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-input\").value = raw\n        document.getElementById(\"__notebook-cancel\").addEventListener(\"click\", () => {\n          notebookInput.value = editTemp[notebookInput.id]\n          delete editTemp[notebookInput.id]\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        })\n\n        document.getElementById(\"__notebook-submit\").addEventListener(\"click\", async() => {\n          const render = document.getElementById(\"__notebook-render\")\n          raw = document.getElementById(\"__notebook-input\").value\n          render.classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          const article = document.querySelector(\"article\")\n          showBusy(article, \"Loading Notebook...\")\n          render.innerHTML = \"\"\n          editTemp = {}\n          await setupPyodide(true)\n          await pyrender(raw)\n          await init()\n          hideBusy(article)\n          fakeDOMContentLoaded()\n        })\n      }\n\n      inputs.addEventListener(\"touchmove\", e => {\n        // Stop propagation on \"touchmove\".\n\n        e.stopPropagation()\n      })\n\n      results.addEventListener(\"click\", e => {\n        // Handle clicks on results and copies color from single color swatch when clicked.\n\n        const el = e.target\n        if (el.matches('span.swatch-color')) {\n          let content = ''\n          const parent = el.parentNode\n          if (!parent.matches('span.swatch-gradient')) {\n            content = parent.getAttribute('title').replace('Copy to clipboard', '')\n            content = content.replace('\\n', '')\n            if (window.clipboardData && window.clipboardData.setData) {\n              // Old `IE`` handling, do we really need this?\n              return window.clipboardData.setData(\"Text\", content)\n            } else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n              const textarea = document.createElement(\"textarea\")\n              textarea.textContent = content\n              textarea.style.position = \"fixed\"\n              document.body.appendChild(textarea)\n              textarea.select()\n              try {\n                return document.execCommand(\"copy\")\n              } catch (ex) {\n                return prompt(\"Copy to clipboard: Ctrl+C, Enter\", content) // eslint-disable-line no-alert\n              } finally {\n                document.body.removeChild(textarea)\n              }\n            }\n          }\n        }\n      })\n\n      buttonEdit.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        editTemp[currentID] = inputs.value\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        textResize(inputs)\n        inputs.focus()\n      })\n\n      buttonShare.addEventListener(\"click\", async() => {\n        // Handle the share click: copy URL with code as parameter.\n\n        const base = window.location.pathname.split('/')[1]\n        const uri = encodeuri(inputs.value)\n        const loc = window.location\n        let pathname = \"/playground/\"\n        if (loc.pathname.startsWith(`/${base}/`)) {\n          pathname = `/${base}/playground/`\n        }\n        const path = `${loc.protocol}//${loc.host}${pathname}?code=${uri}`\n        if (path.length > 2000) {\n          alert( // eslint-disable-line no-alert\n            \"Code must be small enough to generate a shareable URL under 2000 characters!\"\n          )\n        } else {\n          navigator.clipboard.writeText(path).then(async() => {\n            alert(\"Link copied to clipboard :)\") // eslint-disable-line no-alert\n          }, async() => {\n            alert(\"Failed to copy link clipboard!\") // eslint-disable-line no-alert\n          })\n        }\n      })\n\n      buttonRun.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        if (busy) {\n          return\n        }\n\n        busy = true\n        // Load Pyodide and related packages.\n        const form = pgcode.querySelector(\"form\")\n        showBusy(form, null, true)\n        const buttons = document.querySelectorAll(\".playground .playground-run\")\n        if (buttons) {\n          buttons.forEach(b => {\n            b.setAttribute(\"disabled\", \"\")\n          })\n        }\n        await setupPyodide(false)\n        results.querySelector(\"code\").innerHTML = \"\"\n        await pyexecute(currentID)\n        if (buttons) {\n          buttons.forEach(b => {\n            b.removeAttribute(\"disabled\")\n          })\n        }\n        hideBusy(form)\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n\n        delete editTemp[currentID]\n        busy = false\n      })\n\n      buttonCancel.addEventListener(\"click\", () => {\n        // Cancel edit.\n\n        inputs.value = editTemp[currentID]\n        delete editTemp[currentID]\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n      })\n    })\n  }\n\n  const main = async first => {\n    // Load external source to render in a playground.\n    // This can be something like a file on a gist we must read in (?source=)\n    // or raw code (?code=).\n\n    editTemp = {}\n\n    if (window.location.pathname.endsWith(\"/playground/\")) {\n      const params = new URLSearchParams(window.location.search)\n      const loadMsg = \"Loading Pyodide...\"\n      const pageMsg = \"Loading Notebook...\"\n      const uri = params.has(\"source\") ? params.get(\"source\") : params.get(\"notebook\")\n      const article = document.querySelector(\"article\")\n      if (uri !== null && uri.trim()) {\n        // A source was specified, so load it.\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        try {\n          const gistType = params.has(\"source\") ? \"source\" : \"notebook\"\n          lastSearch = decodeURIComponent(params.toString())\n          let value = \"\"\n          const xhr = new XMLHttpRequest()\n          gist = uri\n          xhr.open(\"GET\", uri, true)\n          xhr.onload = async() => {\n            // Try and load the requested content\n            if (xhr.readyState === 4) {\n              if (xhr.status === 200) {\n                value = xhr.responseText\n              }\n            }\n\n            if (gistType === \"source\") {\n              value = getContent(value)\n            }\n            await pyrender(value)\n            await init(first)\n            hideBusy(article)\n            fakeDOMContentLoaded()\n          }\n          xhr.send()\n        } catch (err) {} // eslint-disable-line no-empty\n      } else {\n        gist = \"\"\n        const content = getContent(params.has(\"code\") ? params.get(\"code\") : defContent)\n        lastSearch = decodeURIComponent(params.toString())\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        await pyrender(content)\n        await init(first)\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      }\n    } else {\n      gist = \"\"\n      lastSearch = \"\"\n      init(first)\n    }\n  }\n\n  // Capture links in notebook pages so that we can make playgound links load instantly\n  document.addEventListener(\"click\", interceptClickEvent)\n\n  // Handle history of notebook pages as they are loaded dynamically\n  window.addEventListener(\"popstate\", popState)\n\n  // Before leaving, turn off fake, just in case we navigated away before finished\n  window.addEventListener(\"unload\", () => {\n    fake = false\n  })\n\n  // Attach main via subscribe (subscribes to Materials on page load and instant page loads)\n  window.document$.subscribe(() => {\n    // To get other libraries to reload, we may create a fake `DOMContentLoaded`\n    // No need to process these events.\n    if (fake) {\n      fake = false\n      return\n    }\n    main(true)\n  })\n})()\n"],"names":["pyodide","busy","raw","gist","editTemp","reIdNum","initialized","lastSearch","fake","tabStart","pycode","defContent","getContent","notebookInstalled","playgroundInstalled","fakeDOMContentLoaded","textResize","encodeuri","pyexecute","pyrender","setupPyodide","showBusy","hideBusy","handleTab","init","main","window","colorNotebook","defaultPlayground","content","concat","document","dispatchEvent","Event","bubbles","cancelable","document$","next","inpt","scrollLeft","pageXOffset","documentElement","body","parentNode","scrollTop","pageYOffset","style","height","scrollHeight","scrollTo","uri","encodeURIComponent","replace","c","charCodeAt","toString","_ref","_asyncToGenerator","_regeneratorRuntime","mark","currentID","currentInputs","wrap","_context","prev","getElementById","setAttribute","globals","set","runPythonAsync","removeAttribute","stop","_callee","_x","apply","this","arguments","_ref2","text","src","_context2","value","location","hash","href","_callee2","_x2","_ref3","full","base","packages","installs","_iterator","_step","s","_context3","loadPyodide","indexURL","fullStdLib","sent","origin","pathname","split","notebookWheels","playgroundWheels","_createForOfIteratorHelper","n","done","push","err","e","f","loadPackage","_callee3","_x3","target","label","relative","loaderLabel","classes","template","createElement","innerHTML","appendChild","firstChild","querySelector","removeChild","key","selectionStart","selectionEnd","preventDefault","start","end","length","lines","substr","i","shiftKey","join","_ref4","first","notebook","_context12","querySelectorAll","forEach","pg","id","inputs","results","pgcode","buttonEdit","buttonShare","buttonRun","buttonCancel","addEventListener","notebookInput","classList","toggle","_ref5","_context4","prompt","history","pushState","URLSearchParams","_callee4","_x5","_ref6","_context5","source","_callee5","_x6","_callee6","render","article","_context6","stopPropagation","el","matches","parent","getAttribute","clipboardData","setData","queryCommandSupported","textarea","textContent","position","select","execCommand","ex","_callee7","_context7","focus","_callee10","loc","path","_context10","startsWith","protocol","host","alert","navigator","clipboard","writeText","then","_callee8","_context8","_callee9","_context9","_callee11","form","buttons","_context11","abrupt","b","_callee12","_x4","_ref13","params","loadMsg","pageMsg","gistType","xhr","_context14","endsWith","search","has","get","trim","decodeURIComponent","XMLHttpRequest","open","onload","_callee13","_context13","readyState","status","responseText","send","_callee14","_x7","srcElement","tagName","_step2","state","_iterator2","_step2$value","_slicedToArray","subscribe"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"extra-notebook-a6f6be1b.js","sources":["extra-notebook.js"],"sourcesContent":["(() => {\n  let pyodide = null\n  let busy = false\n  let raw = \"\"\n  let gist = \"\"\n  let editTemp = {}\n  const reIdNum = /.*?_(\\d+)$/\n  let initialized = false\n  let lastSearch = \"\"\n  let fake = false\n  const tabStart = /^( {1,4}|\\t)/\n  // This is the Python payload that will be executed when the user\n  // presses the `Run` button. It will execute the code, create a\n  // Python console output, find color references, steps, and interpolation\n  // references and render the appropriate preview.\n  const pycode = `\n{{pycode}}\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback()\n`\n\n  const defContent = window.colorNotebook.defaultPlayground\n\n  const getContent = content => {\n    return `\n!!! new \"This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). \\\nLearn more [here](\\\n?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md\\\n). Preview, convert, interpolate, and explore!\"\n\n\\`\\`\\`\\`\\`\\`\\`\\`playground\n${content}\n\\`\\`\\`\\`\\`\\`\\`\\`\n`\n  }\n\n  let notebookInstalled = false\n  let playgroundInstalled = false\n\n  const fakeDOMContentLoaded = () => {\n    // Send a fake `DOMContentLoaded`\n    fake = true\n    window.document.dispatchEvent(new Event(\"DOMContentLoaded\", {\n      bubbles: true,\n      cancelable: true\n    }))\n    window.document$.next()\n  }\n\n  const textResize = inpt => {\n    // Resize inputs based on text height.\n\n    const scrollLeft = window.pageXOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollLeft\n\n    const scrollTop  = window.pageYOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollTop\n\n    inpt.style.height = \"5px\"\n    inpt.style.height = `${inpt.scrollHeight}px`\n\n    window.scrollTo(scrollLeft, scrollTop)\n  }\n\n  const encodeuri = uri => {\n    // Encode the URI component.\n\n    return encodeURIComponent(uri).replace(/[.!'()*]/g, c => {\n      return `%${c.charCodeAt(0).toString(16)}`\n    })\n  }\n\n  const pyexecute = async currentID => {\n    // Execute Python code inside a playground\n\n    const currentInputs = document.getElementById(`__playground-inputs_${currentID}`)\n    currentInputs.setAttribute(\"readonly\", \"\")\n    pyodide.globals.set(\"id_num\", currentID)\n    pyodide.globals.set(\"action\", \"playground\")\n    await pyodide.runPythonAsync(pycode)\n    currentInputs.removeAttribute(\"readonly\")\n  }\n\n  const pyrender = async text => {\n    // Render an entire notebook page\n\n    pyodide.globals.set(\"content\", text)\n    pyodide.globals.set(\"action\", \"notebook\")\n    await pyodide.runPythonAsync(pycode)\n    const src = document.getElementById(\"__notebook-input\")\n    if (src) {\n      raw = text\n      src.value = text\n    }\n    if (window.location.hash) {\n      // Force jumping to hashes\n      window.location.href = window.location.href // eslint-disable-line no-self-assign\n    }\n  }\n\n  const setupPyodide = async full => {\n    // Load `Pyodide` and the any default packages we can need and can load.\n\n    if (!initialized) {\n      initialized = true\n      pyodide = await loadPyodide({ // eslint-disable-line no-undef\n        indexURL: \"https://cdn.jsdelivr.net/pyodide/v0.22.1/full/\",\n        fullStdLib: false\n      })\n    }\n\n    if ((!notebookInstalled && full) || (!playgroundInstalled && !full)) {\n      const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`\n      const packages = (full) ? window.colorNotebook.notebookWheels : window.colorNotebook.playgroundWheels\n      const installs = []\n      if (full) {\n        notebookInstalled = true\n      } else {\n        playgroundInstalled = true\n      }\n      for (const s of packages) {\n        installs.push(base + s)\n      }\n      await pyodide.loadPackage(installs)\n    }\n  }\n\n  const showBusy = (target, label, relative) => {\n    // Show busy indicator\n\n    const loaderLabel = (typeof label === \"undefined\" || label === null) ? \"Loading...\" : label\n    const classes = relative ? \"loading relative\" : \"loading\"\n    const template = document.createElement(\"template\")\n    template.innerHTML = `<div class=\"${classes}\"><div class=\"loader\"></div><div>${loaderLabel}</div></div>`\n    target.appendChild(template.content.firstChild)\n  }\n\n  const hideBusy = target => {\n    // Hide busy indicator\n\n    const loading = target.querySelector(\".loading\")\n    if (loading) {\n      target.removeChild(target.querySelector(\".loading\"))\n    }\n  }\n\n  const popState = () => {\n    // Handle notebook history\n\n    const base = window.location.pathname.split('/')[1]\n    if (\n      window.location.pathname === `/${base}/playground/`\n    ) {\n      const current = decodeURIComponent(new URLSearchParams(window.location.search).toString())\n      if (current !== lastSearch) {\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const interceptClickEvent = e => {\n    // Catch links to other notebook pages and handle them\n\n    const base = window.location.pathname.split('/')[1]\n    const target = e.target || e.srcElement\n    if (target.tagName === \"A\" && main) { // eslint-disable-line no-use-before-define\n      if (\n        target.getAttribute(\"href\") &&\n        target.host === window.location.host &&\n        window.location.pathname === `/${base}/playground/\"` &&\n        window.location.pathname === target.pathname &&\n        window.location.search !== target.search\n      ) {\n        e.preventDefault()\n        const search = new URLSearchParams(target.search)\n        const state = {}\n        for (const [key, value] of search) {\n          state[key] = value\n        }\n        history.pushState(state, \"\", target.href)\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const handleTab = e => {\n    // Prevent tab from tabbing out.\n\n    if (e.key === 'Tab') {\n      const target = e.target\n\n      if (target.selectionStart !== target.selectionEnd) {\n        e.preventDefault()\n\n        let start = target.selectionStart\n        let end = target.selectionEnd\n\n        const text = target.value\n\n        while (start > 0 && text[start - 1] !== '\\n') {\n          start--\n        }\n        while (end > 0 && text[end - 1] !== '\\n' && end < text.length) {\n          end++\n        }\n\n        let lines = text.substr(start, end - start).split('\\n')\n\n        for (let i = 0; i < lines.length; i++) {\n\n          // Don't indent last line if cursor at start of line\n          if (i === lines.length - 1 && lines[i].length === 0) {\n            continue\n          }\n\n          // Indent or deindent\n          if (e.shiftKey) {\n            lines[i] = lines[i].replace(tabStart, '')\n          } else {\n            lines[i] = `    ${lines[i]}`\n          }\n        }\n        lines = lines.join('\\n')\n\n        // Update the text area\n        target.value = text.substr(0, start) + lines + text.substr(end)\n        target.selectionStart = start\n        target.selectionEnd = start + lines.length\n      }\n    }\n  }\n\n  const init = async first => {\n    // Setup input highlighting and events to run Python code blocks.\n\n    const notebook = document.getElementById(\"__notebook-source\")\n    const playgrounds = document.querySelectorAll(\".playground\")\n    playgrounds.forEach(pg => {\n\n      const currentID = pg.id.replace(reIdNum, \"$1\")\n      const inputs = document.getElementById(`__playground-inputs_${currentID}`)\n      const results = document.getElementById(`__playground-results_${currentID}`)\n      const pgcode = document.getElementById(`__playground-code_${currentID}`)\n      const buttonEdit = document.querySelector(`button#__playground-edit_${currentID}`)\n      const buttonShare = document.querySelector(`button#__playground-share_${currentID}`)\n      const buttonRun = document.querySelector(`button#__playground-run_${currentID}`)\n      const buttonCancel = document.querySelector(`button#__playground-cancel_${currentID}`)\n\n      inputs.addEventListener(\"input\", () => {\n        // Adjust textarea height on text input.\n\n        textResize(inputs)\n      })\n\n      inputs.addEventListener('keydown', handleTab)\n\n      if (notebook && first) {\n        const notebookInput = document.getElementById(\"__notebook-input\")\n\n        notebookInput.addEventListener(\"input\", e => {\n          // Adjust textarea height on text input.\n\n          textResize(e.target)\n        })\n\n        notebookInput.addEventListener('keydown', handleTab)\n\n        const editPage = document.getElementById(\"__notebook-edit\")\n        editPage.addEventListener(\"click\", () => {\n          editTemp[notebookInput.id] = notebookInput.value\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          textResize(document.getElementById(\"__notebook-input\"))\n        })\n\n        document.getElementById(\"__notebook-md-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter link to the Markdown page source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({notebook: uri}, \"\", `?${new URLSearchParams(`notebook=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-py-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter the link to the Python code source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({source: uri}, \"\", `?${new URLSearchParams(`source=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-input\").value = raw\n        document.getElementById(\"__notebook-cancel\").addEventListener(\"click\", () => {\n          notebookInput.value = editTemp[notebookInput.id]\n          delete editTemp[notebookInput.id]\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        })\n\n        document.getElementById(\"__notebook-submit\").addEventListener(\"click\", async() => {\n          const render = document.getElementById(\"__notebook-render\")\n          raw = document.getElementById(\"__notebook-input\").value\n          render.classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          const article = document.querySelector(\"article\")\n          showBusy(article, \"Loading Notebook...\")\n          render.innerHTML = \"\"\n          editTemp = {}\n          await setupPyodide(true)\n          await pyrender(raw)\n          await init()\n          hideBusy(article)\n          fakeDOMContentLoaded()\n        })\n      }\n\n      inputs.addEventListener(\"touchmove\", e => {\n        // Stop propagation on \"touchmove\".\n\n        e.stopPropagation()\n      })\n\n      results.addEventListener(\"click\", e => {\n        // Handle clicks on results and copies color from single color swatch when clicked.\n\n        const el = e.target\n        if (el.matches('span.swatch-color')) {\n          let content = ''\n          const parent = el.parentNode\n          if (!parent.matches('span.swatch-gradient')) {\n            content = parent.getAttribute('title').replace('Copy to clipboard', '')\n            content = content.replace('\\n', '')\n            if (window.clipboardData && window.clipboardData.setData) {\n              // Old `IE`` handling, do we really need this?\n              return window.clipboardData.setData(\"Text\", content)\n            } else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n              const textarea = document.createElement(\"textarea\")\n              textarea.textContent = content\n              textarea.style.position = \"fixed\"\n              document.body.appendChild(textarea)\n              textarea.select()\n              try {\n                return document.execCommand(\"copy\")\n              } catch (ex) {\n                return prompt(\"Copy to clipboard: Ctrl+C, Enter\", content) // eslint-disable-line no-alert\n              } finally {\n                document.body.removeChild(textarea)\n              }\n            }\n          }\n        }\n      })\n\n      buttonEdit.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        editTemp[currentID] = inputs.value\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        textResize(inputs)\n        inputs.focus()\n      })\n\n      buttonShare.addEventListener(\"click\", async() => {\n        // Handle the share click: copy URL with code as parameter.\n\n        const base = window.location.pathname.split('/')[1]\n        const uri = encodeuri(inputs.value)\n        const loc = window.location\n        let pathname = \"/playground/\"\n        if (loc.pathname.startsWith(`/${base}/`)) {\n          pathname = `/${base}/playground/`\n        }\n        const path = `${loc.protocol}//${loc.host}${pathname}?code=${uri}`\n        if (path.length > 2000) {\n          alert( // eslint-disable-line no-alert\n            \"Code must be small enough to generate a shareable URL under 2000 characters!\"\n          )\n        } else {\n          navigator.clipboard.writeText(path).then(async() => {\n            alert(\"Link copied to clipboard :)\") // eslint-disable-line no-alert\n          }, async() => {\n            alert(\"Failed to copy link clipboard!\") // eslint-disable-line no-alert\n          })\n        }\n      })\n\n      buttonRun.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        if (busy) {\n          return\n        }\n\n        busy = true\n        // Load Pyodide and related packages.\n        const form = pgcode.querySelector(\"form\")\n        showBusy(form, null, true)\n        const buttons = document.querySelectorAll(\".playground .playground-run\")\n        if (buttons) {\n          buttons.forEach(b => {\n            b.setAttribute(\"disabled\", \"\")\n          })\n        }\n        await setupPyodide(false)\n        results.querySelector(\"code\").innerHTML = \"\"\n        await pyexecute(currentID)\n        if (buttons) {\n          buttons.forEach(b => {\n            b.removeAttribute(\"disabled\")\n          })\n        }\n        hideBusy(form)\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n\n        delete editTemp[currentID]\n        busy = false\n      })\n\n      buttonCancel.addEventListener(\"click\", () => {\n        // Cancel edit.\n\n        inputs.value = editTemp[currentID]\n        delete editTemp[currentID]\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n      })\n    })\n  }\n\n  const main = async first => {\n    // Load external source to render in a playground.\n    // This can be something like a file on a gist we must read in (?source=)\n    // or raw code (?code=).\n\n    editTemp = {}\n\n    if (window.location.pathname.endsWith(\"/playground/\")) {\n      const params = new URLSearchParams(window.location.search)\n      const loadMsg = \"Loading Pyodide...\"\n      const pageMsg = \"Loading Notebook...\"\n      const uri = params.has(\"source\") ? params.get(\"source\") : params.get(\"notebook\")\n      const article = document.querySelector(\"article\")\n      if (uri !== null && uri.trim()) {\n        // A source was specified, so load it.\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        try {\n          const gistType = params.has(\"source\") ? \"source\" : \"notebook\"\n          lastSearch = decodeURIComponent(params.toString())\n          let value = \"\"\n          const xhr = new XMLHttpRequest()\n          gist = uri\n          xhr.open(\"GET\", uri, true)\n          xhr.onload = async() => {\n            // Try and load the requested content\n            if (xhr.readyState === 4) {\n              if (xhr.status === 200) {\n                value = xhr.responseText\n              }\n            }\n\n            if (gistType === \"source\") {\n              value = getContent(value)\n            }\n            await pyrender(value)\n            await init(first)\n            hideBusy(article)\n            fakeDOMContentLoaded()\n          }\n          xhr.send()\n        } catch (err) {} // eslint-disable-line no-empty\n      } else {\n        gist = \"\"\n        const content = getContent(params.has(\"code\") ? params.get(\"code\") : defContent)\n        lastSearch = decodeURIComponent(params.toString())\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        await pyrender(content)\n        await init(first)\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      }\n    } else {\n      gist = \"\"\n      lastSearch = \"\"\n      init(first)\n    }\n  }\n\n  // Capture links in notebook pages so that we can make playgound links load instantly\n  document.addEventListener(\"click\", interceptClickEvent)\n\n  // Handle history of notebook pages as they are loaded dynamically\n  window.addEventListener(\"popstate\", popState)\n\n  // Before leaving, turn off fake, just in case we navigated away before finished\n  window.addEventListener(\"unload\", () => {\n    fake = false\n  })\n\n  // Attach main via subscribe (subscribes to Materials on page load and instant page loads)\n  window.document$.subscribe(() => {\n    // To get other libraries to reload, we may create a fake `DOMContentLoaded`\n    // No need to process these events.\n    if (fake) {\n      fake = false\n      return\n    }\n    main(true)\n  })\n})()\n"],"names":["pyodide","busy","raw","gist","editTemp","reIdNum","initialized","lastSearch","fake","tabStart","pycode","defContent","getContent","notebookInstalled","playgroundInstalled","fakeDOMContentLoaded","textResize","encodeuri","pyexecute","pyrender","setupPyodide","showBusy","hideBusy","handleTab","init","main","window","colorNotebook","defaultPlayground","content","concat","document","dispatchEvent","Event","bubbles","cancelable","document$","next","inpt","scrollLeft","pageXOffset","documentElement","body","parentNode","scrollTop","pageYOffset","style","height","scrollHeight","scrollTo","uri","encodeURIComponent","replace","c","charCodeAt","toString","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","currentID","currentInputs","wrap","_context","prev","getElementById","setAttribute","globals","set","runPythonAsync","removeAttribute","stop","_x","apply","this","arguments","_ref2","_callee2","text","src","_context2","value","location","hash","href","_x2","_ref3","_callee3","full","base","packages","installs","_iterator","_step","s","_context3","loadPyodide","indexURL","fullStdLib","sent","origin","pathname","split","notebookWheels","playgroundWheels","_createForOfIteratorHelper","n","done","push","err","e","f","loadPackage","_x3","target","label","relative","loaderLabel","classes","template","createElement","innerHTML","appendChild","firstChild","querySelector","removeChild","key","selectionStart","selectionEnd","preventDefault","start","end","length","lines","substr","i","shiftKey","join","_ref4","_callee12","first","notebook","_context12","querySelectorAll","forEach","pg","id","inputs","results","pgcode","buttonEdit","buttonShare","buttonRun","buttonCancel","addEventListener","notebookInput","classList","toggle","_ref5","_callee4","_context4","prompt","history","pushState","URLSearchParams","_x5","_ref6","_callee5","_context5","source","_x6","_callee6","render","article","_context6","stopPropagation","el","matches","parent","getAttribute","clipboardData","setData","queryCommandSupported","textarea","textContent","position","select","execCommand","ex","_callee7","_context7","focus","_callee10","loc","path","_context10","startsWith","protocol","host","alert","navigator","clipboard","writeText","then","_callee8","_context8","_callee9","_context9","_callee11","form","buttons","_context11","abrupt","b","_x4","_ref13","_callee14","params","loadMsg","pageMsg","gistType","xhr","_context14","endsWith","search","has","get","trim","decodeURIComponent","XMLHttpRequest","open","onload","_callee13","_context13","readyState","status","responseText","send","_x7","srcElement","tagName","_step2","state","_iterator2","_step2$value","_slicedToArray","subscribe"],"mappings":"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"}
\ No newline at end of file
diff --git a/docs/theme/playground-config-fe55101c.js b/docs/theme/playground-config-c68b7434.js
similarity index 78%
rename from docs/theme/playground-config-fe55101c.js
rename to docs/theme/playground-config-c68b7434.js
index dd9836261..3ff939617 100644
--- a/docs/theme/playground-config-fe55101c.js
+++ b/docs/theme/playground-config-c68b7434.js
@@ -1,5 +1,5 @@
 var colorNotebook = {
-    "playgroundWheels": ['Pygments-2.12.0-py3-none-any.whl', 'coloraide-1.7.1-py3-none-any.whl'],
-    "notebookWheels": ['Markdown-3.3.4-py3-none-any.whl', 'pymdown_extensions-9.5-py3-none-any.whl', 'Pygments-2.12.0-py3-none-any.whl', 'coloraide-1.7.1-py3-none-any.whl'],
+    "playgroundWheels": ['Pygments-2.12.0-py3-none-any.whl', 'coloraide-1.8-py3-none-any.whl'],
+    "notebookWheels": ['Markdown-3.3.4-py3-none-any.whl', 'pymdown_extensions-9.5-py3-none-any.whl', 'Pygments-2.12.0-py3-none-any.whl', 'coloraide-1.8-py3-none-any.whl'],
     "defaultPlayground": "import coloraide\ncoloraide.__version__\nColor('red')"
 }
diff --git a/mkdocs.yml b/mkdocs.yml
index 6507ff598..c8ccbbd49 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -138,9 +138,9 @@ nav:
       - Contributing &amp; Support: about/contributing.md
       - Acknowledgments: about/acknowledgments.md
       - Changelog: about/changelog.md
+      - License: about/license.md
       - Migration Notes:
           - '1.0': about/releases/1.0.md
-      - License: about/license.md
 
 markdown_extensions:
   - markdown.extensions.toc:
@@ -229,7 +229,7 @@ extra_css:
   - assets/coloraide-extras/extra-d44d9d3485.css
 extra_javascript:
   - https://unpkg.com/mermaid@8.13.3/dist/mermaid.min.js
-  - playground-config-fe55101c.js
+  - playground-config-c68b7434.js
   - https://cdn.jsdelivr.net/pyodide/v0.22.1/full/pyodide.js
   - assets/coloraide-extras/extra-notebook-a6f6be1b.js
 
@@ -244,6 +244,7 @@ plugins:
   - search
   - git-revision-date-localized:
       fallback_to_build_date: true
+      strict: false
   - mkdocs_pymdownx_material_extras
   - minify:
       minify_html: true
diff --git a/package-lock.json b/package-lock.json
index e3ff688ad..ed68a47fe 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,15 +9,15 @@
       "version": "0.1.0",
       "license": "MIT",
       "devDependencies": {
-        "@babel/cli": "^7.20.7",
-        "@babel/core": "^7.20.12",
+        "@babel/cli": "^7.21.0",
+        "@babel/core": "^7.21.0",
         "@babel/eslint-parser": "^7.19.1",
         "@babel/plugin-external-helpers": "^7.18.6",
         "@babel/preset-env": "^7.20.2",
-        "@babel/register": "^7.18.9",
+        "@babel/register": "^7.21.0",
         "@fortawesome/fontawesome-free": "^6.3.0",
         "@mdi/svg": "^7.1.96",
-        "@primer/octicons": "^17.11.1",
+        "@primer/octicons": "^18.0.0",
         "@rollup/plugin-babel": "^6.0.3",
         "@rollup/plugin-replace": "^5.0.2",
         "@rollup/plugin-terser": "^0.4.0",
@@ -26,7 +26,7 @@
         "clean-css": "^5.3.2",
         "css-mqpacker": "^7.0.0",
         "del": "^7.0.0",
-        "eslint": "^8.33.0",
+        "eslint": "^8.35.0",
         "fast-glob": "^3.2.12",
         "gulp": "^4.0.2",
         "gulp-clean-css": "^4.3.0",
@@ -43,46 +43,60 @@
         "gulp-touch-fd": "github:funkedigital/gulp-touch-fd",
         "material-design-color": "^2.3.2",
         "material-shadows": "^3.0.1",
-        "postcss-inline-svg": "^5.0.0",
+        "postcss-inline-svg": "^6.0.0",
         "postcss-pseudo-classes": "^0.2.1",
         "postcss-svgo": "^5.1.0",
         "promise": "^8.3.0",
-        "rollup": "^3.14.0",
+        "rollup": "^3.18.0",
         "rollup-plugin-output-manifest": "^2.0.0",
         "rollup-plugin-regenerator": "^0.6.0",
-        "sass": "^1.58.0",
-        "stylelint": "^15.0.0",
+        "sass": "^1.58.3",
+        "stylelint": "^15.2.0",
         "stylelint-config-rational-order": "^0.1.2",
         "stylelint-config-standard": "^30.0.1",
         "stylelint-order": "^6.0.2",
-        "stylelint-scss": "^4.3.0",
-        "terser": "^5.16.3",
+        "stylelint-scss": "^4.4.0",
+        "terser": "^5.16.5",
         "vinyl-paths": "^5.0.0",
-        "yargs": "^17.6.2"
+        "yargs": "^17.7.1"
       },
       "engines": {
         "node": ">= 10"
       }
     },
     "node_modules/@ampproject/remapping": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.1.tgz",
-      "integrity": "sha512-Aolwjd7HSC2PyY0fDj/wA/EimQT4HfEnFYNp5s9CQlrdhyvWTtvZ5YzrUPu6R6/1jKiUlxu8bUhkdSnKHNAHMA==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+      "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.1.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+      "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
       "dev": true,
       "dependencies": {
-        "@jridgewell/trace-mapping": "^0.3.0"
+        "@jridgewell/set-array": "^1.0.0",
+        "@jridgewell/sourcemap-codec": "^1.4.10"
       },
       "engines": {
         "node": ">=6.0.0"
       }
     },
     "node_modules/@babel/cli": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.20.7.tgz",
-      "integrity": "sha512-WylgcELHB66WwQqItxNILsMlaTd8/SO6SgTTjMp4uCI7P4QyH1r3nqgFmO3BfM4AtfniHgFMH3EpYFj/zynBkQ==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.21.0.tgz",
+      "integrity": "sha512-xi7CxyS8XjSyiwUGCfwf+brtJxjW1/ZTcBUkP10xawIEXLX5HzLn+3aXkgxozcP2UhRhtKTmQurw9Uaes7jZrA==",
       "dev": true,
       "dependencies": {
-        "@jridgewell/trace-mapping": "^0.3.8",
+        "@jridgewell/trace-mapping": "^0.3.17",
         "commander": "^4.0.1",
         "convert-source-map": "^1.1.0",
         "fs-readdir-recursive": "^1.1.0",
@@ -127,21 +141,21 @@
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.20.12",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
-      "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz",
+      "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==",
       "dev": true,
       "dependencies": {
-        "@ampproject/remapping": "^2.1.0",
+        "@ampproject/remapping": "^2.2.0",
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.20.7",
+        "@babel/generator": "^7.21.0",
         "@babel/helper-compilation-targets": "^7.20.7",
-        "@babel/helper-module-transforms": "^7.20.11",
-        "@babel/helpers": "^7.20.7",
-        "@babel/parser": "^7.20.7",
+        "@babel/helper-module-transforms": "^7.21.0",
+        "@babel/helpers": "^7.21.0",
+        "@babel/parser": "^7.21.0",
         "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.12",
-        "@babel/types": "^7.20.7",
+        "@babel/traverse": "^7.21.0",
+        "@babel/types": "^7.21.0",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -175,13 +189,14 @@
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
-      "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
+      "version": "7.21.1",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz",
+      "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.20.7",
+        "@babel/types": "^7.21.0",
         "@jridgewell/gen-mapping": "^0.3.2",
+        "@jridgewell/trace-mapping": "^0.3.17",
         "jsesc": "^2.5.1"
       },
       "engines": {
@@ -323,13 +338,13 @@
       }
     },
     "node_modules/@babel/helper-function-name": {
-      "version": "7.19.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
-      "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz",
+      "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==",
       "dev": true,
       "dependencies": {
-        "@babel/template": "^7.18.10",
-        "@babel/types": "^7.19.0"
+        "@babel/template": "^7.20.7",
+        "@babel/types": "^7.21.0"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -372,9 +387,9 @@
       }
     },
     "node_modules/@babel/helper-module-transforms": {
-      "version": "7.20.11",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
-      "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz",
+      "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==",
       "dev": true,
       "dependencies": {
         "@babel/helper-environment-visitor": "^7.18.9",
@@ -383,8 +398,8 @@
         "@babel/helper-split-export-declaration": "^7.18.6",
         "@babel/helper-validator-identifier": "^7.19.1",
         "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.10",
-        "@babel/types": "^7.20.7"
+        "@babel/traverse": "^7.21.2",
+        "@babel/types": "^7.21.2"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -524,14 +539,14 @@
       }
     },
     "node_modules/@babel/helpers": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz",
-      "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz",
+      "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==",
       "dev": true,
       "dependencies": {
         "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.7",
-        "@babel/types": "^7.20.7"
+        "@babel/traverse": "^7.21.0",
+        "@babel/types": "^7.21.0"
       },
       "engines": {
         "node": ">=6.9.0"
@@ -552,9 +567,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
-      "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz",
+      "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==",
       "dev": true,
       "bin": {
         "parser": "bin/babel-parser.js"
@@ -1663,9 +1678,9 @@
       }
     },
     "node_modules/@babel/register": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz",
-      "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.21.0.tgz",
+      "integrity": "sha512-9nKsPmYDi5DidAqJaQooxIhsLJiNMkGr8ypQ8Uic7cIox7UCDsM7HuUGxdGT7mSDTYbqzIdsOWzfBton/YJrMw==",
       "dev": true,
       "dependencies": {
         "clone-deep": "^4.0.1",
@@ -1708,19 +1723,19 @@
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.20.12",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
-      "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz",
+      "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==",
       "dev": true,
       "dependencies": {
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.20.7",
+        "@babel/generator": "^7.21.1",
         "@babel/helper-environment-visitor": "^7.18.9",
-        "@babel/helper-function-name": "^7.19.0",
+        "@babel/helper-function-name": "^7.21.0",
         "@babel/helper-hoist-variables": "^7.18.6",
         "@babel/helper-split-export-declaration": "^7.18.6",
-        "@babel/parser": "^7.20.7",
-        "@babel/types": "^7.20.7",
+        "@babel/parser": "^7.21.2",
+        "@babel/types": "^7.21.2",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       },
@@ -1729,9 +1744,9 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
-      "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz",
+      "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==",
       "dev": true,
       "dependencies": {
         "@babel/helper-string-parser": "^7.19.4",
@@ -1806,9 +1821,9 @@
       }
     },
     "node_modules/@eslint/eslintrc": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
-      "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
+      "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
       "dev": true,
       "dependencies": {
         "ajv": "^6.12.4",
@@ -1835,9 +1850,9 @@
       "dev": true
     },
     "node_modules/@eslint/eslintrc/node_modules/globals": {
-      "version": "13.19.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz",
-      "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==",
+      "version": "13.20.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+      "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
       "dev": true,
       "dependencies": {
         "type-fest": "^0.20.2"
@@ -1882,6 +1897,15 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/@eslint/js": {
+      "version": "8.35.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
+      "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
+      "dev": true,
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      }
+    },
     "node_modules/@fortawesome/fontawesome-free": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.3.0.tgz",
@@ -2042,9 +2066,9 @@
       }
     },
     "node_modules/@jridgewell/resolve-uri": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
-      "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
       "dev": true,
       "engines": {
         "node": ">=6.0.0"
@@ -2076,13 +2100,13 @@
       "dev": true
     },
     "node_modules/@jridgewell/trace-mapping": {
-      "version": "0.3.9",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+      "version": "0.3.17",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+      "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
       "dev": true,
       "dependencies": {
-        "@jridgewell/resolve-uri": "^3.0.3",
-        "@jridgewell/sourcemap-codec": "^1.4.10"
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
       }
     },
     "node_modules/@mdi/svg": {
@@ -2156,9 +2180,9 @@
       }
     },
     "node_modules/@primer/octicons": {
-      "version": "17.11.1",
-      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.11.1.tgz",
-      "integrity": "sha512-X9V4QlSdLAR3eeYsqc+rHhmbGb6HufLTx5BVv97uXvt/6/TQzW48Pme66+nWU/XJvTkf06Kjr8H6lZLTlrbVxA==",
+      "version": "18.0.0",
+      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-18.0.0.tgz",
+      "integrity": "sha512-EC2T95Xl9FCt84pVROjGmwfBvDWxnvWxL+RGsWYNxr1qY7UO58WgLScgi7K8p4gSK5V/k9vHi/k1EhunIyRGRw==",
       "dev": true,
       "dependencies": {
         "object-assign": "^4.1.1"
@@ -4459,21 +4483,76 @@
       }
     },
     "node_modules/css-select": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz",
-      "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+      "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
       "dev": true,
       "dependencies": {
         "boolbase": "^1.0.0",
-        "css-what": "^4.0.0",
-        "domhandler": "^4.0.0",
-        "domutils": "^2.4.3",
-        "nth-check": "^2.0.0"
+        "css-what": "^6.1.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
+        "nth-check": "^2.0.1"
       },
       "funding": {
         "url": "https://github.com/sponsors/fb55"
       }
     },
+    "node_modules/css-select/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/css-select/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/css-select/node_modules/domutils": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+      "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+      "dev": true,
+      "dependencies": {
+        "dom-serializer": "^2.0.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/css-select/node_modules/entities": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+      "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
     "node_modules/css-tree": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
@@ -4497,9 +4576,9 @@
       }
     },
     "node_modules/css-what": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz",
-      "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
       "dev": true,
       "engines": {
         "node": ">= 6"
@@ -4860,9 +4939,9 @@
       }
     },
     "node_modules/domelementtype": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
       "dev": true,
       "funding": [
         {
@@ -5068,12 +5147,13 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.33.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz",
-      "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==",
+      "version": "8.35.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
+      "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
       "dev": true,
       "dependencies": {
-        "@eslint/eslintrc": "^1.4.1",
+        "@eslint/eslintrc": "^2.0.0",
+        "@eslint/js": "8.35.0",
         "@humanwhocodes/config-array": "^0.11.8",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -5087,7 +5167,7 @@
         "eslint-utils": "^3.0.0",
         "eslint-visitor-keys": "^3.3.0",
         "espree": "^9.4.0",
-        "esquery": "^1.4.0",
+        "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
         "file-entry-cache": "^6.0.1",
@@ -5461,9 +5541,9 @@
       }
     },
     "node_modules/esquery": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
-      "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
       "dev": true,
       "dependencies": {
         "estraverse": "^5.1.0"
@@ -7761,27 +7841,45 @@
       }
     },
     "node_modules/htmlparser2": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
-      "integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
+      "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
       "dev": true,
+      "funding": [
+        "https://github.com/fb55/htmlparser2?sponsor=1",
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fb55"
+        }
+      ],
       "dependencies": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^3.3.0",
-        "domutils": "^2.4.2",
-        "entities": "^2.0.0"
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
+        "entities": "^4.3.0"
+      }
+    },
+    "node_modules/htmlparser2/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
       },
       "funding": {
-        "url": "https://github.com/fb55/htmlparser2?sponsor=1"
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
       }
     },
     "node_modules/htmlparser2/node_modules/domhandler": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
-      "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
       "dev": true,
       "dependencies": {
-        "domelementtype": "^2.0.1"
+        "domelementtype": "^2.3.0"
       },
       "engines": {
         "node": ">= 4"
@@ -7790,6 +7888,32 @@
         "url": "https://github.com/fb55/domhandler?sponsor=1"
       }
     },
+    "node_modules/htmlparser2/node_modules/domutils": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+      "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+      "dev": true,
+      "dependencies": {
+        "dom-serializer": "^2.0.0",
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domutils?sponsor=1"
+      }
+    },
+    "node_modules/htmlparser2/node_modules/entities": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+      "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
     "node_modules/iconv-lite": {
       "version": "0.4.24",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -10123,20 +10247,61 @@
       }
     },
     "node_modules/postcss-inline-svg": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-inline-svg/-/postcss-inline-svg-5.0.0.tgz",
-      "integrity": "sha512-Agqkrn91Qgi+KAO+cTvUS1IAZbHPD4sryPoG0q5U0ThokL4UGoMcmwvNV6tDoRp69B5tgD1VNkn9P09E+xpQAg==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-inline-svg/-/postcss-inline-svg-6.0.0.tgz",
+      "integrity": "sha512-ok5j0Iqsn8mS/5U1W+Im6qkQjm6nBxdwwJU+BSnBaDhLjC06h1xvy9MA+tefxhfZP/ARTRwARSozzYGf/sqEGg==",
       "dev": true,
       "dependencies": {
-        "css-select": "^3.1.0",
-        "dom-serializer": "^1.1.0",
-        "htmlparser2": "^5.0.1",
-        "postcss-value-parser": "^4.0.0"
+        "css-select": "^5.1.0",
+        "dom-serializer": "^2.0.0",
+        "htmlparser2": "^8.0.1",
+        "postcss-value-parser": "^4.2.0"
       },
       "peerDependencies": {
         "postcss": "^8.1.4"
       }
     },
+    "node_modules/postcss-inline-svg/node_modules/dom-serializer": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "entities": "^4.2.0"
+      },
+      "funding": {
+        "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+      }
+    },
+    "node_modules/postcss-inline-svg/node_modules/domhandler": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+      "dev": true,
+      "dependencies": {
+        "domelementtype": "^2.3.0"
+      },
+      "engines": {
+        "node": ">= 4"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/domhandler?sponsor=1"
+      }
+    },
+    "node_modules/postcss-inline-svg/node_modules/entities": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+      "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
     "node_modules/postcss-jsx": {
       "version": "0.36.4",
       "resolved": "https://registry.npmjs.org/postcss-jsx/-/postcss-jsx-0.36.4.tgz",
@@ -11498,9 +11663,9 @@
       }
     },
     "node_modules/rollup": {
-      "version": "3.14.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.14.0.tgz",
-      "integrity": "sha512-o23sdgCLcLSe3zIplT9nQ1+r97okuaiR+vmAPZPTDYB7/f3tgWIYNyiQveMsZwshBT0is4eGax/HH83Q7CG+/Q==",
+      "version": "3.18.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.18.0.tgz",
+      "integrity": "sha512-J8C6VfEBjkvYPESMQYxKHxNOh4A5a3FlP+0BETGo34HEcE4eTlgCrO2+eWzlu2a/sHs2QUkZco+wscH7jhhgWg==",
       "dev": true,
       "bin": {
         "rollup": "dist/bin/rollup"
@@ -11624,9 +11789,9 @@
       "dev": true
     },
     "node_modules/sass": {
-      "version": "1.58.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz",
-      "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==",
+      "version": "1.58.3",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.3.tgz",
+      "integrity": "sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==",
       "dev": true,
       "dependencies": {
         "chokidar": ">=3.0.0 <4.0.0",
@@ -12439,9 +12604,9 @@
       "dev": true
     },
     "node_modules/stylelint": {
-      "version": "15.0.0",
-      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.0.0.tgz",
-      "integrity": "sha512-K97Jgy0ZYMSs6gXoboXbWvc0KvvGnUftiI1Tiv70mQ/DpeDTHOlqQSk3o65Ien+ddYAJeLjzkYM0O6TWiHdoSg==",
+      "version": "15.2.0",
+      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.2.0.tgz",
+      "integrity": "sha512-wjg5OLn8zQwjlj5cYUgyQpMWKzct42AG5dYlqkHRJQJqsystFFn3onqEc263KH4xfEI0W3lZCnlIhFfS64uwSA==",
       "dev": true,
       "dependencies": {
         "@csstools/css-parser-algorithms": "^2.0.1",
@@ -13413,9 +13578,9 @@
       }
     },
     "node_modules/stylelint-scss": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.3.0.tgz",
-      "integrity": "sha512-GvSaKCA3tipzZHoz+nNO7S02ZqOsdBzMiCx9poSmLlb3tdJlGddEX/8QzCOD8O7GQan9bjsvLMsO5xiw6IhhIQ==",
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.4.0.tgz",
+      "integrity": "sha512-Qy66a+/30aylFhPmUArHhVsHOun1qrO93LGT15uzLuLjWS7hKDfpFm34mYo1ndR4MCo8W4bEZM1+AlJRJORaaw==",
       "dev": true,
       "dependencies": {
         "lodash": "^4.17.21",
@@ -13425,7 +13590,7 @@
         "postcss-value-parser": "^4.1.0"
       },
       "peerDependencies": {
-        "stylelint": "^14.5.1"
+        "stylelint": "^14.5.1 || ^15.0.0"
       }
     },
     "node_modules/stylelint/node_modules/balanced-match": {
@@ -13820,9 +13985,9 @@
       }
     },
     "node_modules/terser": {
-      "version": "5.16.3",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz",
-      "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==",
+      "version": "5.16.5",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz",
+      "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==",
       "dev": true,
       "dependencies": {
         "@jridgewell/source-map": "^0.3.2",
@@ -14851,9 +15016,9 @@
       }
     },
     "node_modules/yargs": {
-      "version": "17.6.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
-      "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
+      "version": "17.7.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz",
+      "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
       "dev": true,
       "dependencies": {
         "cliui": "^8.0.1",
@@ -14901,21 +15066,34 @@
   },
   "dependencies": {
     "@ampproject/remapping": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.1.tgz",
-      "integrity": "sha512-Aolwjd7HSC2PyY0fDj/wA/EimQT4HfEnFYNp5s9CQlrdhyvWTtvZ5YzrUPu6R6/1jKiUlxu8bUhkdSnKHNAHMA==",
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+      "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
       "dev": true,
       "requires": {
-        "@jridgewell/trace-mapping": "^0.3.0"
+        "@jridgewell/gen-mapping": "^0.1.0",
+        "@jridgewell/trace-mapping": "^0.3.9"
+      },
+      "dependencies": {
+        "@jridgewell/gen-mapping": {
+          "version": "0.1.1",
+          "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+          "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+          "dev": true,
+          "requires": {
+            "@jridgewell/set-array": "^1.0.0",
+            "@jridgewell/sourcemap-codec": "^1.4.10"
+          }
+        }
       }
     },
     "@babel/cli": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.20.7.tgz",
-      "integrity": "sha512-WylgcELHB66WwQqItxNILsMlaTd8/SO6SgTTjMp4uCI7P4QyH1r3nqgFmO3BfM4AtfniHgFMH3EpYFj/zynBkQ==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.21.0.tgz",
+      "integrity": "sha512-xi7CxyS8XjSyiwUGCfwf+brtJxjW1/ZTcBUkP10xawIEXLX5HzLn+3aXkgxozcP2UhRhtKTmQurw9Uaes7jZrA==",
       "dev": true,
       "requires": {
-        "@jridgewell/trace-mapping": "^0.3.8",
+        "@jridgewell/trace-mapping": "^0.3.17",
         "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
         "chokidar": "^3.4.0",
         "commander": "^4.0.1",
@@ -14942,21 +15120,21 @@
       "dev": true
     },
     "@babel/core": {
-      "version": "7.20.12",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
-      "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz",
+      "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==",
       "dev": true,
       "requires": {
-        "@ampproject/remapping": "^2.1.0",
+        "@ampproject/remapping": "^2.2.0",
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.20.7",
+        "@babel/generator": "^7.21.0",
         "@babel/helper-compilation-targets": "^7.20.7",
-        "@babel/helper-module-transforms": "^7.20.11",
-        "@babel/helpers": "^7.20.7",
-        "@babel/parser": "^7.20.7",
+        "@babel/helper-module-transforms": "^7.21.0",
+        "@babel/helpers": "^7.21.0",
+        "@babel/parser": "^7.21.0",
         "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.12",
-        "@babel/types": "^7.20.7",
+        "@babel/traverse": "^7.21.0",
+        "@babel/types": "^7.21.0",
         "convert-source-map": "^1.7.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -14976,13 +15154,14 @@
       }
     },
     "@babel/generator": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
-      "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
+      "version": "7.21.1",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz",
+      "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==",
       "dev": true,
       "requires": {
-        "@babel/types": "^7.20.7",
+        "@babel/types": "^7.21.0",
         "@jridgewell/gen-mapping": "^0.3.2",
+        "@jridgewell/trace-mapping": "^0.3.17",
         "jsesc": "^2.5.1"
       }
     },
@@ -15090,13 +15269,13 @@
       }
     },
     "@babel/helper-function-name": {
-      "version": "7.19.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
-      "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz",
+      "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==",
       "dev": true,
       "requires": {
-        "@babel/template": "^7.18.10",
-        "@babel/types": "^7.19.0"
+        "@babel/template": "^7.20.7",
+        "@babel/types": "^7.21.0"
       }
     },
     "@babel/helper-hoist-variables": {
@@ -15127,9 +15306,9 @@
       }
     },
     "@babel/helper-module-transforms": {
-      "version": "7.20.11",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
-      "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz",
+      "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==",
       "dev": true,
       "requires": {
         "@babel/helper-environment-visitor": "^7.18.9",
@@ -15138,8 +15317,8 @@
         "@babel/helper-split-export-declaration": "^7.18.6",
         "@babel/helper-validator-identifier": "^7.19.1",
         "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.10",
-        "@babel/types": "^7.20.7"
+        "@babel/traverse": "^7.21.2",
+        "@babel/types": "^7.21.2"
       }
     },
     "@babel/helper-optimise-call-expression": {
@@ -15240,14 +15419,14 @@
       }
     },
     "@babel/helpers": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz",
-      "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz",
+      "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==",
       "dev": true,
       "requires": {
         "@babel/template": "^7.20.7",
-        "@babel/traverse": "^7.20.7",
-        "@babel/types": "^7.20.7"
+        "@babel/traverse": "^7.21.0",
+        "@babel/types": "^7.21.0"
       }
     },
     "@babel/highlight": {
@@ -15262,9 +15441,9 @@
       }
     },
     "@babel/parser": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
-      "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz",
+      "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==",
       "dev": true
     },
     "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
@@ -16001,9 +16180,9 @@
       }
     },
     "@babel/register": {
-      "version": "7.18.9",
-      "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz",
-      "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==",
+      "version": "7.21.0",
+      "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.21.0.tgz",
+      "integrity": "sha512-9nKsPmYDi5DidAqJaQooxIhsLJiNMkGr8ypQ8Uic7cIox7UCDsM7HuUGxdGT7mSDTYbqzIdsOWzfBton/YJrMw==",
       "dev": true,
       "requires": {
         "clone-deep": "^4.0.1",
@@ -16034,27 +16213,27 @@
       }
     },
     "@babel/traverse": {
-      "version": "7.20.12",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
-      "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz",
+      "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==",
       "dev": true,
       "requires": {
         "@babel/code-frame": "^7.18.6",
-        "@babel/generator": "^7.20.7",
+        "@babel/generator": "^7.21.1",
         "@babel/helper-environment-visitor": "^7.18.9",
-        "@babel/helper-function-name": "^7.19.0",
+        "@babel/helper-function-name": "^7.21.0",
         "@babel/helper-hoist-variables": "^7.18.6",
         "@babel/helper-split-export-declaration": "^7.18.6",
-        "@babel/parser": "^7.20.7",
-        "@babel/types": "^7.20.7",
+        "@babel/parser": "^7.21.2",
+        "@babel/types": "^7.21.2",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       }
     },
     "@babel/types": {
-      "version": "7.20.7",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
-      "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
+      "version": "7.21.2",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz",
+      "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==",
       "dev": true,
       "requires": {
         "@babel/helper-string-parser": "^7.19.4",
@@ -16087,9 +16266,9 @@
       "dev": true
     },
     "@eslint/eslintrc": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
-      "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz",
+      "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==",
       "dev": true,
       "requires": {
         "ajv": "^6.12.4",
@@ -16110,9 +16289,9 @@
           "dev": true
         },
         "globals": {
-          "version": "13.19.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz",
-          "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==",
+          "version": "13.20.0",
+          "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+          "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
           "dev": true,
           "requires": {
             "type-fest": "^0.20.2"
@@ -16141,6 +16320,12 @@
         }
       }
     },
+    "@eslint/js": {
+      "version": "8.35.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
+      "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==",
+      "dev": true
+    },
     "@fortawesome/fontawesome-free": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.3.0.tgz",
@@ -16260,9 +16445,9 @@
       }
     },
     "@jridgewell/resolve-uri": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz",
-      "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==",
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+      "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
       "dev": true
     },
     "@jridgewell/set-array": {
@@ -16288,13 +16473,13 @@
       "dev": true
     },
     "@jridgewell/trace-mapping": {
-      "version": "0.3.9",
-      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
-      "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+      "version": "0.3.17",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
+      "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
       "dev": true,
       "requires": {
-        "@jridgewell/resolve-uri": "^3.0.3",
-        "@jridgewell/sourcemap-codec": "^1.4.10"
+        "@jridgewell/resolve-uri": "3.1.0",
+        "@jridgewell/sourcemap-codec": "1.4.14"
       }
     },
     "@mdi/svg": {
@@ -16356,9 +16541,9 @@
       }
     },
     "@primer/octicons": {
-      "version": "17.11.1",
-      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-17.11.1.tgz",
-      "integrity": "sha512-X9V4QlSdLAR3eeYsqc+rHhmbGb6HufLTx5BVv97uXvt/6/TQzW48Pme66+nWU/XJvTkf06Kjr8H6lZLTlrbVxA==",
+      "version": "18.0.0",
+      "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-18.0.0.tgz",
+      "integrity": "sha512-EC2T95Xl9FCt84pVROjGmwfBvDWxnvWxL+RGsWYNxr1qY7UO58WgLScgi7K8p4gSK5V/k9vHi/k1EhunIyRGRw==",
       "dev": true,
       "requires": {
         "object-assign": "^4.1.1"
@@ -18178,16 +18363,55 @@
       }
     },
     "css-select": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz",
-      "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+      "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
       "dev": true,
       "requires": {
         "boolbase": "^1.0.0",
-        "css-what": "^4.0.0",
-        "domhandler": "^4.0.0",
-        "domutils": "^2.4.3",
-        "nth-check": "^2.0.0"
+        "css-what": "^6.1.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
+        "nth-check": "^2.0.1"
+      },
+      "dependencies": {
+        "dom-serializer": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+          "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.3.0",
+            "domhandler": "^5.0.2",
+            "entities": "^4.2.0"
+          }
+        },
+        "domhandler": {
+          "version": "5.0.3",
+          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+          "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.3.0"
+          }
+        },
+        "domutils": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+          "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+          "dev": true,
+          "requires": {
+            "dom-serializer": "^2.0.0",
+            "domelementtype": "^2.3.0",
+            "domhandler": "^5.0.1"
+          }
+        },
+        "entities": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+          "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+          "dev": true
+        }
       }
     },
     "css-tree": {
@@ -18209,9 +18433,9 @@
       }
     },
     "css-what": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz",
-      "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
       "dev": true
     },
     "cssesc": {
@@ -18475,9 +18699,9 @@
       }
     },
     "domelementtype": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
-      "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+      "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
       "dev": true
     },
     "domhandler": {
@@ -18651,12 +18875,13 @@
       "dev": true
     },
     "eslint": {
-      "version": "8.33.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz",
-      "integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==",
+      "version": "8.35.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz",
+      "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==",
       "dev": true,
       "requires": {
-        "@eslint/eslintrc": "^1.4.1",
+        "@eslint/eslintrc": "^2.0.0",
+        "@eslint/js": "8.35.0",
         "@humanwhocodes/config-array": "^0.11.8",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -18670,7 +18895,7 @@
         "eslint-utils": "^3.0.0",
         "eslint-visitor-keys": "^3.3.0",
         "espree": "^9.4.0",
-        "esquery": "^1.4.0",
+        "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
         "file-entry-cache": "^6.0.1",
@@ -18921,9 +19146,9 @@
       "dev": true
     },
     "esquery": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
-      "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
       "dev": true,
       "requires": {
         "estraverse": "^5.1.0"
@@ -20754,25 +20979,53 @@
       "dev": true
     },
     "htmlparser2": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
-      "integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
+      "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
       "dev": true,
       "requires": {
-        "domelementtype": "^2.0.1",
-        "domhandler": "^3.3.0",
-        "domutils": "^2.4.2",
-        "entities": "^2.0.0"
+        "domelementtype": "^2.3.0",
+        "domhandler": "^5.0.2",
+        "domutils": "^3.0.1",
+        "entities": "^4.3.0"
       },
       "dependencies": {
+        "dom-serializer": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+          "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.3.0",
+            "domhandler": "^5.0.2",
+            "entities": "^4.2.0"
+          }
+        },
         "domhandler": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
-          "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
+          "version": "5.0.3",
+          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+          "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.3.0"
+          }
+        },
+        "domutils": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+          "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
           "dev": true,
           "requires": {
-            "domelementtype": "^2.0.1"
+            "dom-serializer": "^2.0.0",
+            "domelementtype": "^2.3.0",
+            "domhandler": "^5.0.1"
           }
+        },
+        "entities": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+          "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+          "dev": true
         }
       }
     },
@@ -22558,15 +22811,43 @@
       }
     },
     "postcss-inline-svg": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/postcss-inline-svg/-/postcss-inline-svg-5.0.0.tgz",
-      "integrity": "sha512-Agqkrn91Qgi+KAO+cTvUS1IAZbHPD4sryPoG0q5U0ThokL4UGoMcmwvNV6tDoRp69B5tgD1VNkn9P09E+xpQAg==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/postcss-inline-svg/-/postcss-inline-svg-6.0.0.tgz",
+      "integrity": "sha512-ok5j0Iqsn8mS/5U1W+Im6qkQjm6nBxdwwJU+BSnBaDhLjC06h1xvy9MA+tefxhfZP/ARTRwARSozzYGf/sqEGg==",
       "dev": true,
       "requires": {
-        "css-select": "^3.1.0",
-        "dom-serializer": "^1.1.0",
-        "htmlparser2": "^5.0.1",
-        "postcss-value-parser": "^4.0.0"
+        "css-select": "^5.1.0",
+        "dom-serializer": "^2.0.0",
+        "htmlparser2": "^8.0.1",
+        "postcss-value-parser": "^4.2.0"
+      },
+      "dependencies": {
+        "dom-serializer": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+          "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.3.0",
+            "domhandler": "^5.0.2",
+            "entities": "^4.2.0"
+          }
+        },
+        "domhandler": {
+          "version": "5.0.3",
+          "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+          "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+          "dev": true,
+          "requires": {
+            "domelementtype": "^2.3.0"
+          }
+        },
+        "entities": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+          "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+          "dev": true
+        }
       }
     },
     "postcss-jsx": {
@@ -23639,9 +23920,9 @@
       }
     },
     "rollup": {
-      "version": "3.14.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.14.0.tgz",
-      "integrity": "sha512-o23sdgCLcLSe3zIplT9nQ1+r97okuaiR+vmAPZPTDYB7/f3tgWIYNyiQveMsZwshBT0is4eGax/HH83Q7CG+/Q==",
+      "version": "3.18.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.18.0.tgz",
+      "integrity": "sha512-J8C6VfEBjkvYPESMQYxKHxNOh4A5a3FlP+0BETGo34HEcE4eTlgCrO2+eWzlu2a/sHs2QUkZco+wscH7jhhgWg==",
       "dev": true,
       "requires": {
         "fsevents": "~2.3.2"
@@ -23739,9 +24020,9 @@
       "dev": true
     },
     "sass": {
-      "version": "1.58.0",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz",
-      "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==",
+      "version": "1.58.3",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.3.tgz",
+      "integrity": "sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==",
       "dev": true,
       "requires": {
         "chokidar": ">=3.0.0 <4.0.0",
@@ -24400,9 +24681,9 @@
       "dev": true
     },
     "stylelint": {
-      "version": "15.0.0",
-      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.0.0.tgz",
-      "integrity": "sha512-K97Jgy0ZYMSs6gXoboXbWvc0KvvGnUftiI1Tiv70mQ/DpeDTHOlqQSk3o65Ien+ddYAJeLjzkYM0O6TWiHdoSg==",
+      "version": "15.2.0",
+      "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.2.0.tgz",
+      "integrity": "sha512-wjg5OLn8zQwjlj5cYUgyQpMWKzct42AG5dYlqkHRJQJqsystFFn3onqEc263KH4xfEI0W3lZCnlIhFfS64uwSA==",
       "dev": true,
       "requires": {
         "@csstools/css-parser-algorithms": "^2.0.1",
@@ -25287,9 +25568,9 @@
       }
     },
     "stylelint-scss": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.3.0.tgz",
-      "integrity": "sha512-GvSaKCA3tipzZHoz+nNO7S02ZqOsdBzMiCx9poSmLlb3tdJlGddEX/8QzCOD8O7GQan9bjsvLMsO5xiw6IhhIQ==",
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-4.4.0.tgz",
+      "integrity": "sha512-Qy66a+/30aylFhPmUArHhVsHOun1qrO93LGT15uzLuLjWS7hKDfpFm34mYo1ndR4MCo8W4bEZM1+AlJRJORaaw==",
       "dev": true,
       "requires": {
         "lodash": "^4.17.21",
@@ -25485,9 +25766,9 @@
       }
     },
     "terser": {
-      "version": "5.16.3",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz",
-      "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==",
+      "version": "5.16.5",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.5.tgz",
+      "integrity": "sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==",
       "dev": true,
       "requires": {
         "@jridgewell/source-map": "^0.3.2",
@@ -26320,9 +26601,9 @@
       "dev": true
     },
     "yargs": {
-      "version": "17.6.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
-      "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
+      "version": "17.7.1",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz",
+      "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==",
       "dev": true,
       "requires": {
         "cliui": "^8.0.1",
diff --git a/package.json b/package.json
index a860fff37..dfac792ac 100644
--- a/package.json
+++ b/package.json
@@ -17,15 +17,15 @@
     "node": ">= 10"
   },
   "devDependencies": {
-    "@babel/cli": "^7.20.7",
-    "@babel/core": "^7.20.12",
+    "@babel/cli": "^7.21.0",
+    "@babel/core": "^7.21.0",
     "@babel/eslint-parser": "^7.19.1",
     "@babel/plugin-external-helpers": "^7.18.6",
     "@babel/preset-env": "^7.20.2",
-    "@babel/register": "^7.18.9",
+    "@babel/register": "^7.21.0",
     "@fortawesome/fontawesome-free": "^6.3.0",
     "@mdi/svg": "^7.1.96",
-    "@primer/octicons": "^17.11.1",
+    "@primer/octicons": "^18.0.0",
     "@rollup/plugin-babel": "^6.0.3",
     "@rollup/plugin-replace": "^5.0.2",
     "@rollup/plugin-terser": "^0.4.0",
@@ -34,7 +34,7 @@
     "clean-css": "^5.3.2",
     "css-mqpacker": "^7.0.0",
     "del": "^7.0.0",
-    "eslint": "^8.33.0",
+    "eslint": "^8.35.0",
     "fast-glob": "^3.2.12",
     "gulp": "^4.0.2",
     "gulp-clean-css": "^4.3.0",
@@ -51,21 +51,21 @@
     "gulp-touch-fd": "github:funkedigital/gulp-touch-fd",
     "material-design-color": "^2.3.2",
     "material-shadows": "^3.0.1",
-    "postcss-inline-svg": "^5.0.0",
+    "postcss-inline-svg": "^6.0.0",
     "postcss-pseudo-classes": "^0.2.1",
     "postcss-svgo": "^5.1.0",
     "promise": "^8.3.0",
-    "rollup": "^3.14.0",
+    "rollup": "^3.18.0",
     "rollup-plugin-output-manifest": "^2.0.0",
     "rollup-plugin-regenerator": "^0.6.0",
-    "sass": "^1.58.0",
-    "stylelint": "^15.0.0",
+    "sass": "^1.58.3",
+    "stylelint": "^15.2.0",
     "stylelint-config-rational-order": "^0.1.2",
     "stylelint-config-standard": "^30.0.1",
     "stylelint-order": "^6.0.2",
-    "stylelint-scss": "^4.3.0",
-    "terser": "^5.16.3",
+    "stylelint-scss": "^4.4.0",
+    "terser": "^5.16.5",
     "vinyl-paths": "^5.0.0",
-    "yargs": "^17.6.2"
+    "yargs": "^17.7.1"
   }
 }


Test patch:
diff --git a/tests/test_hsl.py b/tests/test_hsl.py
index 3b250d8f7..2039b785e 100644
--- a/tests/test_hsl.py
+++ b/tests/test_hsl.py
@@ -40,6 +40,9 @@ class TestHSL(util.ColorAssertsPyTest):
         ('hsla(270 30% 50% / 0.5)', 'color(--hsl 270 0.3 0.5 / 0.5)'),
         ('hsla(270 30% 50% / 50%)', 'color(--hsl 270 0.3 0.5 / 0.5)'),
         ('hsla(none none none / none)', 'color(--hsl none none none / none)'),
+        ('hsl(270 30 50)', 'color(--hsl 270 0.3 0.5)'),
+        ('hsl(270 30% 50)', 'color(--hsl 270 0.3 0.5)'),
+        ('hsla(270 30 50 / 0.5)', 'color(--hsl 270 0.3 0.5 / 0.5)'),
         ('hsl(50% 30 50)', None),
         # Test CSS color
         ('color(--hsl 270 0.3 0.5)', 'color(--hsl 270 0.3 0.5)'),
@@ -73,6 +76,8 @@ class TestHSLSerialize(util.ColorAssertsPyTest):
         ('hsl(270 30% 75% / 0.5)', {}, 'hsl(270 30% 75% / 0.5)'),
         ('hsl(270 30% 75%)', {'alpha': True}, 'hsl(270 30% 75% / 1)'),
         ('hsl(270 30% 75% / 0.5)', {'alpha': False}, 'hsl(270 30% 75%)'),
+        # Test percent
+        ('hsl(270 30% 75% / 50%)', {'percent': False}, 'hsl(270 30 75 / 0.5)'),
         # Test None
         ('hsl(none 30% 75%)', {}, 'hsl(0 30% 75%)'),
         ('hsl(none 30% 75%)', {'none': True}, 'hsl(none 30% 75%)'),
@@ -85,6 +90,8 @@ class TestHSLSerialize(util.ColorAssertsPyTest):
         ('hsl(270 30% 75% / 0.5)', {'comma': True}, 'hsla(270, 30%, 75%, 0.5)'),
         ('hsl(270 30% 75%)', {'comma': True, 'alpha': True}, 'hsla(270, 30%, 75%, 1)'),
         ('hsl(270 30% 75% / 0.5)', {'comma': True, 'alpha': False}, 'hsl(270, 30%, 75%)'),
+        # Test legacy percent
+        ('hsl(270 30% 75% / 50%)', {'comma': True, 'percent': False}, 'hsla(270, 30%, 75%, 0.5)'),
         # Test legacy None
         ('hsl(none 30% 75%)', {'comma': True}, 'hsl(0, 30%, 75%)'),
         ('hsl(none 30% 75%)', {'comma': True, 'none': True}, 'hsl(0, 30%, 75%)'),
diff --git a/tests/test_hwb.py b/tests/test_hwb.py
index 94d12e9bd..6bf242399 100644
--- a/tests/test_hwb.py
+++ b/tests/test_hwb.py
@@ -19,6 +19,14 @@ class TestHWB(util.ColorAssertsPyTest):
         ('white', 'color(--hwb none 1 0)'),
         ('gray', 'color(--hwb none 0.50196 0.49804)'),
         ('black', 'color(--hwb none 0 1)'),
+        # Test CSS
+        ('hwb(270 30% 50%)', 'color(--hwb 270 0.3 0.5)'),
+        ('hwb(270 30% 50% / 0.5)', 'color(--hwb 270 0.3 0.5 / 0.5)'),
+        ('hwb(270 30% 50% / 50%)', 'color(--hwb 270 0.3 0.5 / 0.5)'),
+        ('hwb(none none none / none)', 'color(--hwb none none none / none)'),
+        ('hwb(270 30 50)', 'color(--hwb 270 0.3 0.5)'),
+        ('hwb(270 30% 50)', 'color(--hwb 270 0.3 0.5)'),
+        ('hwb(50% 30 50)', None),
         # Test color
         ('color(--hwb 270 0.3 0.5)', 'color(--hwb 270 0.3 0.5)'),
         ('color(--hwb 270 0.3 0.5 / 0.5)', 'color(--hwb 270 0.3 0.5 / 0.5)'),
@@ -34,7 +42,11 @@ class TestHWB(util.ColorAssertsPyTest):
     def test_colors(self, color1, color2):
         """Test colors."""
 
-        self.assertColorEqual(Color(color1).convert('hwb'), Color(color2), color=True)
+        if color2 is None:
+            with pytest.raises(ValueError):
+                Color(color1)
+        else:
+            self.assertColorEqual(Color(color1).convert('hwb'), Color(color2), color=True)
 
 
 class TestHWBSerialize(util.ColorAssertsPyTest):
@@ -47,6 +59,8 @@ class TestHWBSerialize(util.ColorAssertsPyTest):
         ('hwb(270 30% 50% / 0.5)', {}, 'hwb(270 30% 50% / 0.5)'),
         ('hwb(270 30% 50%)', {'alpha': True}, 'hwb(270 30% 50% / 1)'),
         ('hwb(270 30% 50% / 0.5)', {'alpha': False}, 'hwb(270 30% 50%)'),
+        # Test percent
+        ('hwb(270 30% 75% / 50%)', {'percent': False}, 'hwb(270 30 75 / 0.5)'),
         # Test None
         ('hwb(none 30% 50%)', {}, 'hwb(0 30% 50%)'),
         ('hwb(none 30% 50%)', {'none': True}, 'hwb(none 30% 50%)'),
diff --git a/tests/test_srgb.py b/tests/test_srgb.py
index 74d03f03e..814d51e66 100644
--- a/tests/test_srgb.py
+++ b/tests/test_srgb.py
@@ -49,8 +49,8 @@ class TestsRGB(util.ColorAssertsPyTest):
         ('rgba(0 128 0 / 0.5)', 'color(srgb 0 0.50196 0 / 0.5)'),
         ('rgba(0 128 0 / 50%)', 'color(srgb 0 0.50196 0 / 0.5)'),
         ('rgba(none none none / none)', 'color(srgb none none none / none)'),
-        ('rgb(50% 128 0)', None),
-        ('rgba(50% 128 0)', None),
+        ('rgb(50% 128 0)', 'color(srgb 0.5 0.50196 0)'),
+        ('rgba(50% 128 0)', 'color(srgb 0.5 0.50196 0)'),
         # Test CSS color
         ('color(srgb 0 0.50196 0)', 'color(srgb 0 0.50196 0)'),
         ('color(srgb 0 0.50196 0 / 0.5)', 'color(srgb 0 0.50196 0 / 0.5)'),