diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSBuilder.kt index 2c25442b79..ab837611a4 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/CSSBuilder.kt @@ -3,26 +3,25 @@ package org.jetbrains.compose.web.css import org.jetbrains.compose.web.css.selectors.CSSSelector interface CSSBuilder : CSSStyleRuleBuilder, GenericStyleSheetBuilder { - val root: CSSSelector val self: CSSSelector } class CSSBuilderImpl( - override val root: CSSSelector, + private val currentRoot: CSSSelector, override val self: CSSSelector, rulesHolder: CSSRulesHolder ) : CSSRuleBuilderImpl(), CSSBuilder, CSSRulesHolder by rulesHolder { override fun style(selector: CSSSelector, cssRule: CSSBuilder.() -> Unit) { - val resolvedSelector = if (selector.contains(self, true) || selector.contains(root, true)) { + val resolvedSelector = if (selector.contains(self, true) || selector.contains(currentRoot, true)) { selector } else { desc(self, selector) } - val (style, rules) = buildCSS(root, resolvedSelector, cssRule) + val (style, rules) = buildCSS(currentRoot, resolvedSelector, cssRule) rules.forEach { add(it) } add(resolvedSelector, style) } override fun buildRules(rulesBuild: GenericStyleSheetBuilder.() -> Unit) = - CSSBuilderImpl(root, self, StyleSheetBuilderImpl()).apply(rulesBuild).cssRules + CSSBuilderImpl(currentRoot, self, StyleSheetBuilderImpl()).apply(rulesBuild).cssRules } diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleSheetBuilder.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleSheetBuilder.kt index 5aaf5c9c66..791dfd4dbe 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleSheetBuilder.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleSheetBuilder.kt @@ -1,6 +1,7 @@ package org.jetbrains.compose.web.css import org.jetbrains.compose.web.css.selectors.CSSSelector +import org.jetbrains.compose.web.css.selectors.Nth interface CSSRulesHolder { val cssRules: CSSRuleDeclarationList @@ -60,16 +61,42 @@ interface SelectorsScope { return combine(this, selector(selector)) } + @JsName("returnUniversalSelector") + @Deprecated("Use universal property", replaceWith = ReplaceWith("universal")) fun universal(): CSSSelector = CSSSelector.Universal + + val universal: CSSSelector + get() = CSSSelector.Universal + fun type(type: String): CSSSelector = CSSSelector.Type(type) fun className(className: String): CSSSelector = CSSSelector.CSSClass(className) fun id(id: String): CSSSelector = CSSSelector.Id(id) + fun attr( name: String, value: String? = null, operator: CSSSelector.Attribute.Operator = CSSSelector.Attribute.Operator.Equals, caseSensitive: Boolean = true - ): CSSSelector = CSSSelector.Attribute(name, value, operator, caseSensitive) + ): CSSSelector = CSSSelector.AttributeInternal(name, value, operator, caseSensitive) + + fun attrEquals(name: String, value: String? = null, caseSensitive: Boolean = true) = + attr(name, value, CSSSelector.Attribute.Operator.Equals, caseSensitive) + + fun attrListContains(name: String, value: String? = null, caseSensitive: Boolean = true) = + attr(name, value, CSSSelector.Attribute.Operator.ListContains, caseSensitive) + + fun attrHyphened(name: String, value: String? = null, caseSensitive: Boolean = true) = + attr(name, value, CSSSelector.Attribute.Operator.Hyphened, caseSensitive) + + fun attrPrefixed(name: String, value: String? = null, caseSensitive: Boolean = true) = + attr(name, value, CSSSelector.Attribute.Operator.Prefixed, caseSensitive) + + fun attrSuffixed(name: String, value: String? = null, caseSensitive: Boolean = true) = + attr(name, value, CSSSelector.Attribute.Operator.Suffixed, caseSensitive) + + fun attrContains(name: String, value: String? = null, caseSensitive: Boolean = true) = + attr(name, value, CSSSelector.Attribute.Operator.Contains, caseSensitive) + fun group(vararg selectors: CSSSelector): CSSSelector = CSSSelector.Group(selectors.toList()) @Deprecated("Replaced with `desc`", ReplaceWith("desc(parent, selected)")) @@ -79,14 +106,140 @@ interface SelectorsScope { fun desc(parent: String, selected: CSSSelector): CSSSelector = desc(selector(parent), selected) fun desc(parent: String, selected: String): CSSSelector = desc(selector(parent), selector(selected)) - fun child(parent: CSSSelector, selected: CSSSelector): CSSSelector = - CSSSelector.Child(parent, selected) + fun child(parent: CSSSelector, selected: CSSSelector): CSSSelector = CSSSelector.Child(parent, selected) fun sibling(sibling: CSSSelector, selected: CSSSelector): CSSSelector = CSSSelector.Sibling(sibling, selected) fun adjacent(sibling: CSSSelector, selected: CSSSelector): CSSSelector = CSSSelector.Adjacent(sibling, selected) - fun not(selector: CSSSelector): CSSSelector = CSSSelector.PseudoClass.Not(selector) - fun hover(): CSSSelector = CSSSelector.PseudoClass.hover - fun hover(selector: CSSSelector): CSSSelector = selector + hover() + @JsName("returnHoverSelector") + @Deprecated("Use hover property", replaceWith = ReplaceWith("hover")) + fun hover(): CSSSelector = hover + fun hover(selector: CSSSelector): CSSSelector = selector + hover + + // Location pseudo-classes + val anyLink: CSSSelector + get() = CSSSelector.PseudoClassInternal("any-link") + val link: CSSSelector + get() = CSSSelector.PseudoClassInternal("link") + val visited: CSSSelector + get() = CSSSelector.PseudoClassInternal("visited") + val localLink: CSSSelector + get() = CSSSelector.PseudoClassInternal("local-link") + val target: CSSSelector + get() = CSSSelector.PseudoClassInternal("target") + val targetWithin: CSSSelector + get() = CSSSelector.PseudoClassInternal("target-within") + val scope: CSSSelector + get() = CSSSelector.PseudoClassInternal("scope") + + // User action pseudo-classes + val hover: CSSSelector + get() = CSSSelector.PseudoClassInternal("hover") + val active: CSSSelector + get() = CSSSelector.PseudoClassInternal("active") + val focus: CSSSelector + get() = CSSSelector.PseudoClassInternal("focus") + val focusVisible: CSSSelector + get() = CSSSelector.PseudoClassInternal("focus-visible") + + // Resource state pseudo-classes + val playing: CSSSelector + get() = CSSSelector.PseudoClassInternal("playing") + val paused: CSSSelector + get() = CSSSelector.PseudoClassInternal("paused") + + // The input pseudo-classes + val autofill: CSSSelector + get() = CSSSelector.PseudoClassInternal("autofill") + val enabled: CSSSelector + get() = CSSSelector.PseudoClassInternal("enabled") + val disabled: CSSSelector + get() = CSSSelector.PseudoClassInternal("disabled") + val readOnly: CSSSelector + get() = CSSSelector.PseudoClassInternal("read-only") + val readWrite: CSSSelector + get() = CSSSelector.PseudoClassInternal("read-write") + val placeholderShown: CSSSelector + get() = CSSSelector.PseudoClassInternal("placeholder-shown") + val default: CSSSelector + get() = CSSSelector.PseudoClassInternal("default") + val checked: CSSSelector + get() = CSSSelector.PseudoClassInternal("checked") + val indeterminate: CSSSelector + get() = CSSSelector.PseudoClassInternal("indeterminate") + val blank: CSSSelector + get() = CSSSelector.PseudoClassInternal("blank") + val valid: CSSSelector + get() = CSSSelector.PseudoClassInternal("valid") + val invalid: CSSSelector + get() = CSSSelector.PseudoClassInternal("invalid") + val inRange: CSSSelector + get() = CSSSelector.PseudoClassInternal("in-range") + val outOfRange: CSSSelector + get() = CSSSelector.PseudoClassInternal("out-of-range") + val required: CSSSelector + get() = CSSSelector.PseudoClassInternal("required") + val optional: CSSSelector + get() = CSSSelector.PseudoClassInternal("optional") + val userInvalid: CSSSelector + get() = CSSSelector.PseudoClassInternal("user-invalid") + + // Tree-structural pseudo-classes + val root: CSSSelector + get() = CSSSelector.PseudoClassInternal("root") + val empty: CSSSelector + get() = CSSSelector.PseudoClassInternal("empty") + val first: CSSSelector + get() = CSSSelector.PseudoClassInternal("first") + val firstChild: CSSSelector + get() = CSSSelector.PseudoClassInternal("first-child") + val lastChild: CSSSelector + get() = CSSSelector.PseudoClassInternal("last-child") + val onlyChild: CSSSelector + get() = CSSSelector.PseudoClassInternal("only-child") + val firstOfType: CSSSelector + get() = CSSSelector.PseudoClassInternal("first-of-type") + val lastOfType: CSSSelector + get() = CSSSelector.PseudoClassInternal("last-of-type") + val onlyOfType: CSSSelector + get() = CSSSelector.PseudoClassInternal("only-of-type") + val host: CSSSelector + get() = CSSSelector.PseudoClassInternal("host") + + // Etc + val defined: CSSSelector + get() = CSSSelector.PseudoClassInternal("defined") + val left: CSSSelector + get() = CSSSelector.PseudoClassInternal("left") + val right: CSSSelector + get() = CSSSelector.PseudoClassInternal("right") + + fun lang(langCode: LanguageCode): CSSSelector = CSSSelector.PseudoClassInternal.Lang(langCode) + fun nthChild(nth: Nth): CSSSelector = CSSSelector.PseudoClassInternal.NthChild(nth) + fun nthLastChild(nth: Nth): CSSSelector = CSSSelector.PseudoClassInternal.NthLastChild(nth) + fun nthOfType(nth: Nth): CSSSelector = CSSSelector.PseudoClassInternal.NthOfType(nth) + fun nthLastOfType(nth: Nth): CSSSelector = CSSSelector.PseudoClassInternal.NthLastOfType(nth) + fun host(selector: CSSSelector): CSSSelector = CSSSelector.PseudoClassInternal.Host(selector) + fun not(selector: CSSSelector): CSSSelector = CSSSelector.PseudoClassInternal.Not(selector) + + // Pseudo Element + val after: CSSSelector + get() = CSSSelector.PseudoElementInternal("after") + val before: CSSSelector + get() = CSSSelector.PseudoElementInternal("before") + val cue: CSSSelector + get() = CSSSelector.PseudoElementInternal("cue") + val cueRegion: CSSSelector + get() = CSSSelector.PseudoElementInternal("cue-region") + val firstLetter: CSSSelector + get() = CSSSelector.PseudoElementInternal("first-letter") + val firstLine: CSSSelector + get() = CSSSelector.PseudoElementInternal("first-line") + val fileSelectorButton: CSSSelector + get() = CSSSelector.PseudoElementInternal("file-selector-button") + val selection: CSSSelector + get() = CSSSelector.PseudoElementInternal("selection") + + fun slotted(selector: CSSSelector): CSSSelector = CSSSelector.PseudoElementInternal.Slotted(selector) } interface StyleSheetBuilder : CSSRulesHolder, GenericStyleSheetBuilder { diff --git a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/selectors/CSSSelectors.kt b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/selectors/CSSSelectors.kt index 73b4a20ceb..eac2482a91 100644 --- a/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/selectors/CSSSelectors.kt +++ b/web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/selectors/CSSSelectors.kt @@ -21,7 +21,7 @@ sealed class Nth { } } -abstract class CSSSelector { +abstract class CSSSelector internal constructor() { override fun equals(other: Any?): Boolean { return this === other || asString() == (other as? CSSSelector)?.asString() } @@ -35,32 +35,27 @@ abstract class CSSSelector { // `toString` is reloaded for CSSSelfSelector internal open fun asString(): String = toString() - data class Raw(val selector: String) : CSSSelector() { + internal data class Raw internal constructor(val selector: String) : CSSSelector() { override fun toString(): String = selector } - object Universal : CSSSelector() { + internal object Universal : CSSSelector() { override fun toString(): String = "*" } - data class Type(val type: String) : CSSSelector() { + internal data class Type internal constructor(val type: String) : CSSSelector() { override fun toString(): String = type } - data class CSSClass(val className: String) : CSSSelector() { + internal data class CSSClass internal constructor(val className: String) : CSSSelector() { override fun toString(): String = ".$className" } - data class Id(val id: String) : CSSSelector() { + internal data class Id internal constructor(val id: String) : CSSSelector() { override fun toString(): String = "#$id" } - data class Attribute( - val name: String, - val value: String? = null, - val operator: Operator = Operator.Equals, - val caseSensitive: Boolean = true - ) : CSSSelector() { + object Attribute { enum class Operator(val value: String) { Equals("="), ListContains("~="), @@ -69,6 +64,15 @@ abstract class CSSSelector { Suffixed("$="), Contains("*=") } + } + + internal data class AttributeInternal internal constructor( + val name: String, + val value: String? = null, + val operator: Attribute.Operator = Attribute.Operator.Equals, + val caseSensitive: Boolean = true + ) : CSSSelector() { + override fun toString(): String { val valueStr = value?.let { "${operator.value}$value${if (!caseSensitive) " i" else ""}" @@ -77,7 +81,7 @@ abstract class CSSSelector { } } - data class Combine(val selectors: MutableList) : CSSSelector() { + internal data class Combine internal constructor(val selectors: MutableList) : CSSSelector() { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, selectors, strict) @@ -85,7 +89,7 @@ abstract class CSSSelector { override fun asString(): String = selectors.joinToString("") { it.asString() } } - data class Group(val selectors: List) : CSSSelector() { + internal data class Group internal constructor(val selectors: List) : CSSSelector() { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, selectors, strict) @@ -93,7 +97,8 @@ abstract class CSSSelector { override fun asString(): String = selectors.joinToString(", ") { it.asString() } } - data class Descendant(val parent: CSSSelector, val selected: CSSSelector) : CSSSelector() { + internal data class Descendant internal constructor(val parent: CSSSelector, val selected: CSSSelector) : + CSSSelector() { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(parent, selected), strict) @@ -101,7 +106,7 @@ abstract class CSSSelector { override fun asString(): String = "${parent.asString()} ${selected.asString()}" } - data class Child(val parent: CSSSelector, val selected: CSSSelector) : CSSSelector() { + internal data class Child internal constructor(val parent: CSSSelector, val selected: CSSSelector) : CSSSelector() { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(parent, selected), strict) @@ -109,7 +114,7 @@ abstract class CSSSelector { override fun asString(): String = "${parent.asString()} > ${selected.asString()}" } - data class Sibling(val prev: CSSSelector, val selected: CSSSelector) : CSSSelector() { + internal data class Sibling internal constructor(val prev: CSSSelector, val selected: CSSSelector) : CSSSelector() { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(prev, selected), strict) @@ -117,7 +122,8 @@ abstract class CSSSelector { override fun asString(): String = "${prev.asString()} ~ ${selected.asString()}" } - data class Adjacent(val prev: CSSSelector, val selected: CSSSelector) : CSSSelector() { + internal data class Adjacent internal constructor(val prev: CSSSelector, val selected: CSSSelector) : + CSSSelector() { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(prev, selected), strict) @@ -125,91 +131,138 @@ abstract class CSSSelector { override fun asString(): String = "${prev.asString()} + ${selected.asString()}" } - open class PseudoClass(val name: String) : CSSSelector() { + object PseudoClass { + // Location pseudo-classes + @Deprecated(webCssSelectorsDeprecationMessage) + val anyLink : CSSSelector = PseudoClassInternal("any-link") + @Deprecated(webCssSelectorsDeprecationMessage) + val link : CSSSelector = PseudoClassInternal("link") + @Deprecated(webCssSelectorsDeprecationMessage) + val visited : CSSSelector = PseudoClassInternal("visited") + @Deprecated(webCssSelectorsDeprecationMessage) + val localLink : CSSSelector = PseudoClassInternal("local-link") + @Deprecated(webCssSelectorsDeprecationMessage) + val target : CSSSelector = PseudoClassInternal("target") + @Deprecated(webCssSelectorsDeprecationMessage) + val targetWithin : CSSSelector = PseudoClassInternal("target-within") + @Deprecated(webCssSelectorsDeprecationMessage) + val scope : CSSSelector = PseudoClassInternal("scope") + + // User action pseudo-classes + @Deprecated(webCssSelectorsDeprecationMessage) + val hover : CSSSelector = PseudoClassInternal("hover") + @Deprecated(webCssSelectorsDeprecationMessage) + val active : CSSSelector = PseudoClassInternal("active") + @Deprecated(webCssSelectorsDeprecationMessage) + val focus : CSSSelector = PseudoClassInternal("focus") + @Deprecated(webCssSelectorsDeprecationMessage) + val focusVisible : CSSSelector = PseudoClassInternal("focus-visible") + + // Resource state pseudo-classes + @Deprecated(webCssSelectorsDeprecationMessage) + val playing : CSSSelector = PseudoClassInternal("playing") + @Deprecated(webCssSelectorsDeprecationMessage) + val paused : CSSSelector = PseudoClassInternal("paused") + + // The input pseudo-classes + @Deprecated(webCssSelectorsDeprecationMessage) + val autofill : CSSSelector = PseudoClassInternal("autofill") + @Deprecated(webCssSelectorsDeprecationMessage) + val enabled : CSSSelector = PseudoClassInternal("enabled") + @Deprecated(webCssSelectorsDeprecationMessage) + val disabled : CSSSelector = PseudoClassInternal("disabled") + @Deprecated(webCssSelectorsDeprecationMessage) + val readOnly : CSSSelector = PseudoClassInternal("read-only") + @Deprecated(webCssSelectorsDeprecationMessage) + val readWrite : CSSSelector = PseudoClassInternal("read-write") + @Deprecated(webCssSelectorsDeprecationMessage) + val placeholderShown : CSSSelector = PseudoClassInternal("placeholder-shown") + @Deprecated(webCssSelectorsDeprecationMessage) + val default : CSSSelector = PseudoClassInternal("default") + @Deprecated(webCssSelectorsDeprecationMessage) + val checked : CSSSelector = PseudoClassInternal("checked") + @Deprecated(webCssSelectorsDeprecationMessage) + val indeterminate : CSSSelector = PseudoClassInternal("indeterminate") + @Deprecated(webCssSelectorsDeprecationMessage) + val blank : CSSSelector = PseudoClassInternal("blank") + @Deprecated(webCssSelectorsDeprecationMessage) + val valid : CSSSelector = PseudoClassInternal("valid") + @Deprecated(webCssSelectorsDeprecationMessage) + val invalid : CSSSelector = PseudoClassInternal("invalid") + @Deprecated(webCssSelectorsDeprecationMessage) + val inRange : CSSSelector = PseudoClassInternal("in-range") + @Deprecated(webCssSelectorsDeprecationMessage) + val outOfRange : CSSSelector = PseudoClassInternal("out-of-range") + @Deprecated(webCssSelectorsDeprecationMessage) + val required : CSSSelector = PseudoClassInternal("required") + @Deprecated(webCssSelectorsDeprecationMessage) + val optional : CSSSelector = PseudoClassInternal("optional") + @Deprecated(webCssSelectorsDeprecationMessage) + val userInvalid : CSSSelector = PseudoClassInternal("user-invalid") + + // Tree-structural pseudo-classes + @Deprecated(webCssSelectorsDeprecationMessage) + val root : CSSSelector = PseudoClassInternal("root") + @Deprecated(webCssSelectorsDeprecationMessage) + val empty : CSSSelector = PseudoClassInternal("empty") + @Deprecated(webCssSelectorsDeprecationMessage) + val first : CSSSelector = PseudoClassInternal("first") + @Deprecated(webCssSelectorsDeprecationMessage) + val firstChild : CSSSelector = PseudoClassInternal("first-child") + @Deprecated(webCssSelectorsDeprecationMessage) + val lastChild : CSSSelector = PseudoClassInternal("last-child") + @Deprecated(webCssSelectorsDeprecationMessage) + val onlyChild : CSSSelector = PseudoClassInternal("only-child") + @Deprecated(webCssSelectorsDeprecationMessage) + val firstOfType : CSSSelector = PseudoClassInternal("first-of-type") + @Deprecated(webCssSelectorsDeprecationMessage) + val lastOfType : CSSSelector = PseudoClassInternal("last-of-type") + @Deprecated(webCssSelectorsDeprecationMessage) + val onlyOfType : CSSSelector = PseudoClassInternal("only-of-type") + @Deprecated(webCssSelectorsDeprecationMessage) + val host : CSSSelector = PseudoClassInternal("host") + + // Etc + @Deprecated(webCssSelectorsDeprecationMessage) + val defined : CSSSelector = PseudoClassInternal("defined") + @Deprecated(webCssSelectorsDeprecationMessage) + val left : CSSSelector = PseudoClassInternal("left") + @Deprecated(webCssSelectorsDeprecationMessage) + val right : CSSSelector = PseudoClassInternal("right") + } + + internal open class PseudoClassInternal internal constructor(val name: String) : CSSSelector() { override fun equals(other: Any?): Boolean { - return if (other is PseudoClass) { + return if (other is PseudoClassInternal) { name == other.name && argsStr() == other.argsStr() } else false } open fun argsStr(): String? = null override fun toString(): String = ":$name${argsStr()?.let { "($it)" } ?: ""}" - companion object { - // Location pseudo-classes - val anyLink = PseudoClass("any-link") - val link = PseudoClass("link") - val visited = PseudoClass("visited") - val localLink = PseudoClass("local-link") - val target = PseudoClass("target") - val targetWithin = PseudoClass("target-within") - val scope = PseudoClass("scope") - - // User action pseudo-classes - val hover = PseudoClass("hover") - val active = PseudoClass("active") - val focus = PseudoClass("focus") - val focusVisible = PseudoClass("focus-visible") - - // Resource state pseudo-classes - val playing = PseudoClass("playing") - val paused = PseudoClass("paused") - - // The input pseudo-classes - val autofill = PseudoClass("autofill") - val enabled = PseudoClass("enabled") - val disabled = PseudoClass("disabled") - val readOnly = PseudoClass("read-only") - val readWrite = PseudoClass("read-write") - val placeholderShown = PseudoClass("placeholder-shown") - val default = PseudoClass("default") - val checked = PseudoClass("checked") - val indeterminate = PseudoClass("indeterminate") - val blank = PseudoClass("blank") - val valid = PseudoClass("valid") - val invalid = PseudoClass("invalid") - val inRange = PseudoClass("in-range") - val outOfRange = PseudoClass("out-of-range") - val required = PseudoClass("required") - val optional = PseudoClass("optional") - val userInvalid = PseudoClass("user-invalid") - - // Tree-structural pseudo-classes - val root = PseudoClass("root") - val empty = PseudoClass("empty") - val first = PseudoClass("first") - val firstChild = PseudoClass("first-child") - val lastChild = PseudoClass("last-child") - val onlyChild = PseudoClass("only-child") - val firstOfType = PseudoClass("first-of-type") - val lastOfType = PseudoClass("last-of-type") - val onlyOfType = PseudoClass("only-of-type") - val host = PseudoClass("host") - - // Etc - val defined = PseudoClass("defined") - val left = PseudoClass("left") - val right = PseudoClass("right") - } - // Linguistic pseudo-classes - class Lang(val langCode: LanguageCode) : PseudoClass("lang") { + internal class Lang internal constructor(val langCode: LanguageCode) : PseudoClassInternal("lang") { override fun argsStr() = langCode } // Tree-structural pseudo-classes - class NthChild(val nth: Nth) : PseudoClass("nth-child") { + internal class NthChild internal constructor(val nth: Nth) : PseudoClassInternal("nth-child") { override fun argsStr() = "$nth" } - class NthLastChild(val nth: Nth) : PseudoClass("nth-last-child") { + + internal class NthLastChild internal constructor(val nth: Nth) : PseudoClassInternal("nth-last-child") { override fun argsStr() = "$nth" } - class NthOfType(val nth: Nth) : PseudoClass("nth-of-type") { + + internal class NthOfType internal constructor(val nth: Nth) : PseudoClassInternal("nth-of-type") { override fun argsStr() = "$nth" } - class NthLastOfType(val nth: Nth) : PseudoClass("nth-last-of-type") { + + internal class NthLastOfType internal constructor(val nth: Nth) : PseudoClassInternal("nth-last-of-type") { override fun argsStr() = "$nth" } - class Host(val selector: CSSSelector) : PseudoClass("host") { + + internal class Host internal constructor(val selector: CSSSelector) : PseudoClassInternal("host") { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(selector), strict) @@ -217,7 +270,7 @@ abstract class CSSSelector { } // Etc - class Not(val selector: CSSSelector) : PseudoClass("not") { + internal class Not internal constructor(val selector: CSSSelector) : PseudoClassInternal("not") { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(selector), strict) @@ -225,27 +278,36 @@ abstract class CSSSelector { } } - open class PseudoElement(val name: String) : CSSSelector() { + object PseudoElement { + @Deprecated(webCssSelectorsDeprecationMessage) + val after : CSSSelector = PseudoElementInternal("after") + @Deprecated(webCssSelectorsDeprecationMessage) + val before : CSSSelector = PseudoElementInternal("before") + @Deprecated(webCssSelectorsDeprecationMessage) + val cue : CSSSelector = PseudoElementInternal("cue") + @Deprecated(webCssSelectorsDeprecationMessage) + val cueRegion : CSSSelector = PseudoElementInternal("cue-region") + @Deprecated(webCssSelectorsDeprecationMessage) + val firstLetter : CSSSelector = PseudoElementInternal("first-letter") + @Deprecated(webCssSelectorsDeprecationMessage) + val firstLine : CSSSelector = PseudoElementInternal("first-line") + @Deprecated(webCssSelectorsDeprecationMessage) + val fileSelectorButton : CSSSelector = PseudoElementInternal("file-selector-button") + @Deprecated(webCssSelectorsDeprecationMessage) + val selection : CSSSelector = PseudoElementInternal("selection") + } + + internal open class PseudoElementInternal internal constructor(val name: String) : CSSSelector() { override fun equals(other: Any?): Boolean { - return if (other is PseudoElement) { + return if (other is PseudoElementInternal) { name == other.name && argsStr() == other.argsStr() } else false } + open fun argsStr(): String? = null override fun toString(): String = "::$name${argsStr()?.let { "($it)" } ?: ""}" - companion object { - val after = PseudoElement("after") - val before = PseudoElement("before") - val cue = PseudoElement("cue") - val cueRegion = PseudoElement("cue-region") - val firstLetter = PseudoElement("first-letter") - val firstLine = PseudoElement("first-line") - val fileSelectorButton = PseudoElement("file-selector-button") - val selection = PseudoElement("selection") - } - - class Slotted(val selector: CSSSelector) : PseudoElement("slotted") { + internal class Slotted internal constructor(val selector: CSSSelector) : PseudoElementInternal("slotted") { override fun contains(other: CSSSelector, strict: Boolean): Boolean = contains(this, other, listOf(selector), strict) @@ -260,3 +322,5 @@ private fun contains(that: CSSSelector, other: CSSSelector, children: List