From 8d67a099571ec4b00b3d3929e2fadad2e4d0791f Mon Sep 17 00:00:00 2001 From: kdelay Date: Fri, 4 Sep 2026 00:01:16 +0900 Subject: [PATCH] fix: accept a negative `a` in `:nth-child(an+b)` and an uppercase `n` `REGEX_NTH_OF` only allowed a `+` offset after a negative `a`, only an unsigned lone ``, and a lowercase `n`, so valid `` values such as `-1`, `-2n`, `-2n-1` and `2N+1` failed to compile with `css_expected_identifier`. Fold the two sign branches into one and match `n` case-insensitively. The `of` keyword is left as it was. --- .changeset/signed-nth-child.md | 5 ++++ .../src/compiler/phases/1-parse/read/style.js | 5 ++-- .../nth-child-signed-an-plus-b/expected.css | 17 ++++++++++++++ .../nth-child-signed-an-plus-b/input.svelte | 23 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 .changeset/signed-nth-child.md create mode 100644 packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/expected.css create mode 100644 packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/input.svelte diff --git a/.changeset/signed-nth-child.md b/.changeset/signed-nth-child.md new file mode 100644 index 0000000000..ee6144a5ac --- /dev/null +++ b/.changeset/signed-nth-child.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: accept a negative `a` in `:nth-child(an+b)` and an uppercase `n` diff --git a/packages/svelte/src/compiler/phases/1-parse/read/style.js b/packages/svelte/src/compiler/phases/1-parse/read/style.js index 574c353adb..126173dbd5 100644 --- a/packages/svelte/src/compiler/phases/1-parse/read/style.js +++ b/packages/svelte/src/compiler/phases/1-parse/read/style.js @@ -9,9 +9,10 @@ const REGEX_COMBINATOR = /(\+|~|>|\|\|)/y; const REGEX_PERCENTAGE = /\d+(\.\d+)?%/y; // `of` must be preceded by whitespace, otherwise it would be part of the `` token // (`2nof` is a single dimension token). It does not need to be followed by whitespace, -// because a `.`, `#`, `[`, `*`, `:` or `&` already ends the `of` identifier — minifiers rely on that +// because a `.`, `#`, `[`, `*`, `:` or `&` already ends the `of` identifier — minifiers rely on that. +// The sign of `a` (or of a lone ``) may be `+` or `-`, and the `n` is case-insensitive const REGEX_NTH_OF = - /(even|odd|\+?(\d+|\d*n(\s*[+-]\s*\d+)?)|-\d*n(\s*\+\s*\d+))((?=\s*[,)])|\s+of(\s+|(?=[.#[*:&])))/y; + /(even|odd|[+-]?(\d+|\d*[nN](\s*[+-]\s*\d+)?))((?=\s*[,)])|\s+of(\s+|(?=[.#[*:&])))/y; const REGEX_WHITESPACE_OR_COLON = /[\s:]/; const REGEX_LEADING_HYPHEN_OR_DIGIT = /-?\d/y; const REGEX_VALID_IDENTIFIER_CHAR = /[a-zA-Z0-9_-]/; diff --git a/packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/expected.css b/packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/expected.css new file mode 100644 index 0000000000..ed8edc4656 --- /dev/null +++ b/packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/expected.css @@ -0,0 +1,17 @@ + + /* the `a` of `an+b`, and a lone ``, can be negative, and `n` is case-insensitive */ + li.svelte-xyz:nth-child(-1) { + color: red; + } + li.svelte-xyz:nth-child(-2n) { + color: green; + } + li.svelte-xyz:nth-child(-2n-1) { + color: blue; + } + li.svelte-xyz:nth-child(2N+1) { + color: yellow; + } + li.svelte-xyz:nth-child(-2n-1 of .important) { + color: purple; + } diff --git a/packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/input.svelte b/packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/input.svelte new file mode 100644 index 0000000000..f92cdaa222 --- /dev/null +++ b/packages/svelte/tests/css/samples/nth-child-signed-an-plus-b/input.svelte @@ -0,0 +1,23 @@ +
    +
  • a
  • +
  • b
  • +
+ +