Plumeria

Plumeria 19.8

Sou Watanabe
Sou WatanabePlumeria Core
Anionix
AnionixPlumeria Core

Plumeria v19.8 rewrites how the compiler reads selector keys. The algorithm was proposed by Anionix.

1. One pass for specificity

Specificity is computed in a single pass with a stack of frames, without recursion or copies of the selector. It is 3 to 9 times faster on short keys and about twice as fast on a 4 KB key. Valid selectors get the same specificity as in 19.7.

2. Fixes

  • A comment in a key no longer counts toward specificity, so '.a/* #b */' is not ordered as if it held an ID.
  • :nth-child(2n OF .a) reads OF in any case, as CSS keywords are case-insensitive.
  • A stray or unclosed quote, such as ':hover":is(.x)', stops the build.

3. Selector rules

:not() can nest inside :not() again. Unlike :is() or :where(), a :not() inside :not() changes what the selector matches, so it cannot be flattened:

':not(:not(.a), .b)' // matches .a, but not .b
':not(.a, .b)'       // matches neither

A key can nest :not() and functional pseudo-classes of different names up to 16 levels deep. Any other functional pseudo-class still cannot nest inside one of the same name, as in 19.7:

':is(:where(.a))'      // allowed
':is(:where(:is(.a)))' // stops the build

no-invalid-selector reports the same keys the compiler rejects. Neither a person nor an AI agent can write a key past these limits: the lint reports it, and the compiler stops the build. See selector rules.


Release notes

19.8.2 (Oct 5, 2026)

  • Remove the funding field from package.json
  • Move the test-only devDependencies of @plumeria/compiler to the workspace root
  • Update the next devDependency of @plumeria/next-plugin to 16.3.8

19.8.1 (Oct 4, 2026)

  • Fix #631: specificity reads selector names as CSS identifiers, so of in :nth-child() is read when ., # or : follows it directly (2 of.a) and when escaped (o\66). Proposed by Anionix
  • Count escaped pseudo-class names such as :\69s() and :nth-chil\64()
  • Count type selectors that start with a non-ASCII character

19.8.0 (Oct 3, 2026)

  • Compute specificity in one pass, and stop counting comments in selector keys
  • Read OF in :nth-child() in any case
  • Allow :not() inside :not(), and stop the build on a key nested deeper than 16 levels or holding a stray quote
  • no-invalid-selector reports a key nested deeper than 16 levels or holding a stray quote