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 791dfd4dbe..22cdad0009 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,7 +1,6 @@ package org.jetbrains.compose.web.css -import org.jetbrains.compose.web.css.selectors.CSSSelector -import org.jetbrains.compose.web.css.selectors.Nth +import org.jetbrains.compose.web.css.selectors.* interface CSSRulesHolder { val cssRules: CSSRuleDeclarationList @@ -27,24 +26,24 @@ interface GenericStyleSheetBuilder : CSSRulesHolder, SelectorsScope { } operator fun String.invoke(cssRule: TBuilder.() -> Unit) { - style(CSSSelector.Raw(this), cssRule) + style(Raw(this), cssRule) } infix fun String.style(cssRule: TBuilder.() -> Unit) { - style(CSSSelector.Raw(this), cssRule) + style(Raw(this), cssRule) } } interface SelectorsScope { - fun selector(selector: String): CSSSelector = CSSSelector.Raw(selector) - fun combine(vararg selectors: CSSSelector): CSSSelector = CSSSelector.Combine(selectors.toMutableList()) + fun selector(selector: String): CSSSelector = Raw(selector) + fun combine(vararg selectors: CSSSelector): CSSSelector = Combine(selectors.toMutableList()) operator fun CSSSelector.plus(selector: CSSSelector): CSSSelector { - if (this is CSSSelector.Combine) { + if (this is Combine) { this.selectors.add(selector) return this } - return if (selector is CSSSelector.Combine) { + return if (selector is Combine) { selector.selectors.add(0, this) selector } else { @@ -53,7 +52,7 @@ interface SelectorsScope { } operator fun CSSSelector.plus(selector: String): CSSSelector { - if (this is CSSSelector.Combine) { + if (this is Combine) { this.selectors.add(selector(selector)) return this } @@ -63,21 +62,21 @@ interface SelectorsScope { @JsName("returnUniversalSelector") @Deprecated("Use universal property", replaceWith = ReplaceWith("universal")) - fun universal(): CSSSelector = CSSSelector.Universal + fun universal(): CSSSelector = Universal val universal: CSSSelector - get() = CSSSelector.Universal + get() = Universal - fun type(type: String): CSSSelector = CSSSelector.Type(type) + fun type(type: String): CSSSelector = Type(type) fun className(className: String): CSSSelector = CSSSelector.CSSClass(className) - fun id(id: String): CSSSelector = CSSSelector.Id(id) + fun id(id: String): CSSSelector = Id(id) fun attr( name: String, value: String? = null, operator: CSSSelector.Attribute.Operator = CSSSelector.Attribute.Operator.Equals, caseSensitive: Boolean = true - ): CSSSelector = CSSSelector.AttributeInternal(name, value, operator, caseSensitive) + ): CSSSelector = Attribute(name, value, operator, caseSensitive) fun attrEquals(name: String, value: String? = null, caseSensitive: Boolean = true) = attr(name, value, CSSSelector.Attribute.Operator.Equals, caseSensitive) @@ -97,18 +96,18 @@ interface SelectorsScope { 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()) + fun group(vararg selectors: CSSSelector): CSSSelector = Group(selectors.toList()) @Deprecated("Replaced with `desc`", ReplaceWith("desc(parent, selected)")) fun descendant(parent: CSSSelector, selected: CSSSelector): CSSSelector = desc(parent, selected) - fun desc(parent: CSSSelector, selected: CSSSelector): CSSSelector = CSSSelector.Descendant(parent, selected) + fun desc(parent: CSSSelector, selected: CSSSelector): CSSSelector = Descendant(parent, selected) fun desc(parent: CSSSelector, selected: String): CSSSelector = desc(parent, selector(selected)) 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 sibling(sibling: CSSSelector, selected: CSSSelector): CSSSelector = CSSSelector.Sibling(sibling, selected) - fun adjacent(sibling: CSSSelector, selected: CSSSelector): CSSSelector = CSSSelector.Adjacent(sibling, selected) + fun child(parent: CSSSelector, selected: CSSSelector): CSSSelector = Child(parent, selected) + fun sibling(sibling: CSSSelector, selected: CSSSelector): CSSSelector = Sibling(sibling, selected) + fun adjacent(sibling: CSSSelector, selected: CSSSelector): CSSSelector = Adjacent(sibling, selected) @JsName("returnHoverSelector") @Deprecated("Use hover property", replaceWith = ReplaceWith("hover")) @@ -117,131 +116,277 @@ interface SelectorsScope { // Location pseudo-classes val anyLink: CSSSelector - get() = CSSSelector.PseudoClassInternal("any-link") + get() = PseudoClassInternal("any-link") val link: CSSSelector - get() = CSSSelector.PseudoClassInternal("link") + get() = PseudoClassInternal("link") val visited: CSSSelector - get() = CSSSelector.PseudoClassInternal("visited") + get() = PseudoClassInternal("visited") val localLink: CSSSelector - get() = CSSSelector.PseudoClassInternal("local-link") + get() = PseudoClassInternal("local-link") val target: CSSSelector - get() = CSSSelector.PseudoClassInternal("target") + get() = PseudoClassInternal("target") val targetWithin: CSSSelector - get() = CSSSelector.PseudoClassInternal("target-within") + get() = PseudoClassInternal("target-within") val scope: CSSSelector - get() = CSSSelector.PseudoClassInternal("scope") + get() = PseudoClassInternal("scope") // User action pseudo-classes val hover: CSSSelector - get() = CSSSelector.PseudoClassInternal("hover") + get() = PseudoClassInternal("hover") val active: CSSSelector - get() = CSSSelector.PseudoClassInternal("active") + get() = PseudoClassInternal("active") val focus: CSSSelector - get() = CSSSelector.PseudoClassInternal("focus") + get() = PseudoClassInternal("focus") val focusVisible: CSSSelector - get() = CSSSelector.PseudoClassInternal("focus-visible") + get() = PseudoClassInternal("focus-visible") // Resource state pseudo-classes val playing: CSSSelector - get() = CSSSelector.PseudoClassInternal("playing") + get() = PseudoClassInternal("playing") val paused: CSSSelector - get() = CSSSelector.PseudoClassInternal("paused") + get() = PseudoClassInternal("paused") // The input pseudo-classes val autofill: CSSSelector - get() = CSSSelector.PseudoClassInternal("autofill") + get() = PseudoClassInternal("autofill") val enabled: CSSSelector - get() = CSSSelector.PseudoClassInternal("enabled") + get() = PseudoClassInternal("enabled") val disabled: CSSSelector - get() = CSSSelector.PseudoClassInternal("disabled") + get() = PseudoClassInternal("disabled") val readOnly: CSSSelector - get() = CSSSelector.PseudoClassInternal("read-only") + get() = PseudoClassInternal("read-only") val readWrite: CSSSelector - get() = CSSSelector.PseudoClassInternal("read-write") + get() = PseudoClassInternal("read-write") val placeholderShown: CSSSelector - get() = CSSSelector.PseudoClassInternal("placeholder-shown") + get() = PseudoClassInternal("placeholder-shown") val default: CSSSelector - get() = CSSSelector.PseudoClassInternal("default") + get() = PseudoClassInternal("default") val checked: CSSSelector - get() = CSSSelector.PseudoClassInternal("checked") + get() = PseudoClassInternal("checked") val indeterminate: CSSSelector - get() = CSSSelector.PseudoClassInternal("indeterminate") + get() = PseudoClassInternal("indeterminate") val blank: CSSSelector - get() = CSSSelector.PseudoClassInternal("blank") + get() = PseudoClassInternal("blank") val valid: CSSSelector - get() = CSSSelector.PseudoClassInternal("valid") + get() = PseudoClassInternal("valid") val invalid: CSSSelector - get() = CSSSelector.PseudoClassInternal("invalid") + get() = PseudoClassInternal("invalid") val inRange: CSSSelector - get() = CSSSelector.PseudoClassInternal("in-range") + get() = PseudoClassInternal("in-range") val outOfRange: CSSSelector - get() = CSSSelector.PseudoClassInternal("out-of-range") + get() = PseudoClassInternal("out-of-range") val required: CSSSelector - get() = CSSSelector.PseudoClassInternal("required") + get() = PseudoClassInternal("required") val optional: CSSSelector - get() = CSSSelector.PseudoClassInternal("optional") + get() = PseudoClassInternal("optional") val userInvalid: CSSSelector - get() = CSSSelector.PseudoClassInternal("user-invalid") + get() = PseudoClassInternal("user-invalid") // Tree-structural pseudo-classes val root: CSSSelector - get() = CSSSelector.PseudoClassInternal("root") + get() = PseudoClassInternal("root") val empty: CSSSelector - get() = CSSSelector.PseudoClassInternal("empty") + get() = PseudoClassInternal("empty") val first: CSSSelector - get() = CSSSelector.PseudoClassInternal("first") + get() = PseudoClassInternal("first") val firstChild: CSSSelector - get() = CSSSelector.PseudoClassInternal("first-child") + get() = PseudoClassInternal("first-child") val lastChild: CSSSelector - get() = CSSSelector.PseudoClassInternal("last-child") + get() = PseudoClassInternal("last-child") val onlyChild: CSSSelector - get() = CSSSelector.PseudoClassInternal("only-child") + get() = PseudoClassInternal("only-child") val firstOfType: CSSSelector - get() = CSSSelector.PseudoClassInternal("first-of-type") + get() = PseudoClassInternal("first-of-type") val lastOfType: CSSSelector - get() = CSSSelector.PseudoClassInternal("last-of-type") + get() = PseudoClassInternal("last-of-type") val onlyOfType: CSSSelector - get() = CSSSelector.PseudoClassInternal("only-of-type") + get() = PseudoClassInternal("only-of-type") val host: CSSSelector - get() = CSSSelector.PseudoClassInternal("host") + get() = PseudoClassInternal("host") // Etc val defined: CSSSelector - get() = CSSSelector.PseudoClassInternal("defined") + get() = PseudoClassInternal("defined") val left: CSSSelector - get() = CSSSelector.PseudoClassInternal("left") + get() = PseudoClassInternal("left") val right: CSSSelector - get() = CSSSelector.PseudoClassInternal("right") + get() = 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) + fun lang(langCode: LanguageCode): CSSSelector = PseudoClassInternal.Lang(langCode) + fun nthChild(nth: Nth): CSSSelector = PseudoClassInternal.NthChild(nth) + fun nthLastChild(nth: Nth): CSSSelector = PseudoClassInternal.NthLastChild(nth) + fun nthOfType(nth: Nth): CSSSelector = PseudoClassInternal.NthOfType(nth) + fun nthLastOfType(nth: Nth): CSSSelector = PseudoClassInternal.NthLastOfType(nth) + fun host(selector: CSSSelector): CSSSelector = PseudoClassInternal.Host(selector) + fun not(selector: CSSSelector): CSSSelector = PseudoClassInternal.Not(selector) // Pseudo Element val after: CSSSelector - get() = CSSSelector.PseudoElementInternal("after") + get() = PseudoElementInternal("after") val before: CSSSelector - get() = CSSSelector.PseudoElementInternal("before") + get() = PseudoElementInternal("before") val cue: CSSSelector - get() = CSSSelector.PseudoElementInternal("cue") + get() = PseudoElementInternal("cue") val cueRegion: CSSSelector - get() = CSSSelector.PseudoElementInternal("cue-region") + get() = PseudoElementInternal("cue-region") val firstLetter: CSSSelector - get() = CSSSelector.PseudoElementInternal("first-letter") + get() = PseudoElementInternal("first-letter") val firstLine: CSSSelector - get() = CSSSelector.PseudoElementInternal("first-line") + get() = PseudoElementInternal("first-line") val fileSelectorButton: CSSSelector - get() = CSSSelector.PseudoElementInternal("file-selector-button") + get() = PseudoElementInternal("file-selector-button") val selection: CSSSelector - get() = CSSSelector.PseudoElementInternal("selection") + get() = PseudoElementInternal("selection") - fun slotted(selector: CSSSelector): CSSSelector = CSSSelector.PseudoElementInternal.Slotted(selector) + fun slotted(selector: CSSSelector): CSSSelector = PseudoElementInternal.Slotted(selector) } +private data class Id(val id: String) : CSSSelector() { + override fun toString(): String = "#$id" +} + +private data class Type(val type: String) : CSSSelector() { + override fun toString(): String = type +} + +private object Universal : CSSSelector() { + override fun toString(): String = "*" +} + +private data class Raw(val selector: String) : CSSSelector() { + override fun toString(): String = selector +} + +private data class Combine(val selectors: MutableList) : CSSSelector() { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, selectors, strict) + + override fun toString(): String = selectors.joinToString("") + override fun asString(): String = selectors.joinToString("") { it.asString() } +} + +private data class Group(val selectors: List) : CSSSelector() { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, selectors, strict) + + override fun toString(): String = selectors.joinToString(", ") + override fun asString(): String = selectors.joinToString(", ") { it.asString() } +} + +private data class Descendant(val parent: CSSSelector, val selected: CSSSelector) : + CSSSelector() { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(parent, selected), strict) + + override fun toString(): String = "$parent $selected" + override fun asString(): String = "${parent.asString()} ${selected.asString()}" +} + +private data class Child(val parent: CSSSelector, val selected: CSSSelector) : CSSSelector() { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(parent, selected), strict) + + override fun toString(): String = "$parent > $selected" + override fun asString(): String = "${parent.asString()} > ${selected.asString()}" +} + +private data class Sibling(val prev: CSSSelector, val selected: CSSSelector) : CSSSelector() { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(prev, selected), strict) + + override fun toString(): String = "$prev ~ $selected" + override fun asString(): String = "${prev.asString()} ~ ${selected.asString()}" +} + +private data class Adjacent(val prev: CSSSelector, val selected: CSSSelector) : CSSSelector() { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(prev, selected), strict) + + override fun toString(): String = "$prev + $selected" + override fun asString(): String = "${prev.asString()} + ${selected.asString()}" +} + +private data class Attribute( + 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 ""}" + } ?: "" + return "[$name$valueStr]" + } +} + +private open class PseudoClassInternal(val name: String) : CSSSelector() { + override fun equals(other: Any?): Boolean { + 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)" } ?: ""}" + + // Linguistic pseudo-classes + class Lang internal constructor(val langCode: LanguageCode) : PseudoClassInternal("lang") { + override fun argsStr() = langCode + } + + // Tree-structural pseudo-classes + class NthChild internal constructor(val nth: Nth) : PseudoClassInternal("nth-child") { + override fun argsStr() = "$nth" + } + + class NthLastChild internal constructor(val nth: Nth) : PseudoClassInternal("nth-last-child") { + override fun argsStr() = "$nth" + } + + class NthOfType internal constructor(val nth: Nth) : PseudoClassInternal("nth-of-type") { + override fun argsStr() = "$nth" + } + + class NthLastOfType internal constructor(val nth: Nth) : PseudoClassInternal("nth-last-of-type") { + override fun argsStr() = "$nth" + } + + class Host internal constructor(val selector: CSSSelector) : PseudoClassInternal("host") { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(selector), strict) + + override fun argsStr() = selector.asString() + } + + // Etc + class Not internal constructor(val selector: CSSSelector) : PseudoClassInternal("not") { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(selector), strict) + + override fun argsStr() = "$selector" + } +} + +private open class PseudoElementInternal(val name: String) : CSSSelector() { + override fun equals(other: Any?): Boolean { + 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)" } ?: ""}" + + class Slotted internal constructor(val selector: CSSSelector) : PseudoElementInternal("slotted") { + override fun contains(other: CSSSelector, strict: Boolean): Boolean = + contains(this, other, listOf(selector), strict) + + override fun argsStr() = selector.asString() + } +} + + interface StyleSheetBuilder : CSSRulesHolder, GenericStyleSheetBuilder { override fun style(selector: CSSSelector, cssRule: CSSStyleRuleBuilder.() -> Unit) { add(selector, buildCSSStyleRule(cssRule)) 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 eac2482a91..4104c13205 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 @@ -2,7 +2,10 @@ package org.jetbrains.compose.web.css.selectors -import org.jetbrains.compose.web.css.LanguageCode +import org.jetbrains.compose.web.css.SelectorsScope + +internal const val webCssSelectorsDeprecationMessage = "Consider using a property from SelectorsScope" +private val selectorScope = object : SelectorsScope {} sealed class Nth { data class Functional(val a: Int? = null, val b: Int? = null) { @@ -30,31 +33,23 @@ abstract class CSSSelector internal constructor() { return if (strict) this === other else this == other } + @Suppress("SuspiciousEqualsCombination") + protected fun contains(that: CSSSelector, other: CSSSelector, children: List, strict: Boolean): Boolean { + return that === other || // exactly same selector + children.any { it.contains(other, strict) } || // contains it in children + (!strict && that == other) // equals structurally + } + + // This method made for workaround because of possible concatenation of `String + CSSSelector`, // so `toString` is called for such operator, but we are calling `asString` for instantiation. // `toString` is reloaded for CSSSelfSelector internal open fun asString(): String = toString() - internal data class Raw internal constructor(val selector: String) : CSSSelector() { - override fun toString(): String = selector - } - - internal object Universal : CSSSelector() { - override fun toString(): String = "*" - } - - internal data class Type internal constructor(val type: String) : CSSSelector() { - override fun toString(): String = type - } - internal data class CSSClass internal constructor(val className: String) : CSSSelector() { override fun toString(): String = ".$className" } - internal data class Id internal constructor(val id: String) : CSSSelector() { - override fun toString(): String = "#$id" - } - object Attribute { enum class Operator(val value: String) { Equals("="), @@ -66,261 +61,122 @@ abstract class CSSSelector internal constructor() { } } - 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 ""}" - } ?: "" - return "[$name$valueStr]" - } - } - - internal data class Combine internal constructor(val selectors: MutableList) : CSSSelector() { - override fun contains(other: CSSSelector, strict: Boolean): Boolean = - contains(this, other, selectors, strict) - - override fun toString(): String = selectors.joinToString("") - override fun asString(): String = selectors.joinToString("") { it.asString() } - } - - internal data class Group internal constructor(val selectors: List) : CSSSelector() { - override fun contains(other: CSSSelector, strict: Boolean): Boolean = - contains(this, other, selectors, strict) - - override fun toString(): String = selectors.joinToString(", ") - override fun asString(): String = selectors.joinToString(", ") { it.asString() } - } - - 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) - - override fun toString(): String = "$parent $selected" - override fun asString(): String = "${parent.asString()} ${selected.asString()}" - } - - 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) - - override fun toString(): String = "$parent > $selected" - override fun asString(): String = "${parent.asString()} > ${selected.asString()}" - } - - 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) - - override fun toString(): String = "$prev ~ $selected" - override fun asString(): String = "${prev.asString()} ~ ${selected.asString()}" - } - - 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) - - override fun toString(): String = "$prev + $selected" - override fun asString(): String = "${prev.asString()} + ${selected.asString()}" - } - object PseudoClass { // Location pseudo-classes @Deprecated(webCssSelectorsDeprecationMessage) - val anyLink : CSSSelector = PseudoClassInternal("any-link") + val anyLink : CSSSelector = selectorScope.anyLink @Deprecated(webCssSelectorsDeprecationMessage) - val link : CSSSelector = PseudoClassInternal("link") + val link : CSSSelector = selectorScope.link @Deprecated(webCssSelectorsDeprecationMessage) - val visited : CSSSelector = PseudoClassInternal("visited") + val visited : CSSSelector = selectorScope.visited @Deprecated(webCssSelectorsDeprecationMessage) - val localLink : CSSSelector = PseudoClassInternal("local-link") + val localLink : CSSSelector = selectorScope.localLink @Deprecated(webCssSelectorsDeprecationMessage) - val target : CSSSelector = PseudoClassInternal("target") + val target : CSSSelector = selectorScope.target @Deprecated(webCssSelectorsDeprecationMessage) - val targetWithin : CSSSelector = PseudoClassInternal("target-within") + val targetWithin : CSSSelector = selectorScope.targetWithin @Deprecated(webCssSelectorsDeprecationMessage) - val scope : CSSSelector = PseudoClassInternal("scope") + val scope : CSSSelector = selectorScope.scope // User action pseudo-classes @Deprecated(webCssSelectorsDeprecationMessage) - val hover : CSSSelector = PseudoClassInternal("hover") + val hover : CSSSelector = selectorScope.hover @Deprecated(webCssSelectorsDeprecationMessage) - val active : CSSSelector = PseudoClassInternal("active") + val active : CSSSelector = selectorScope.active @Deprecated(webCssSelectorsDeprecationMessage) - val focus : CSSSelector = PseudoClassInternal("focus") + val focus : CSSSelector = selectorScope.focus @Deprecated(webCssSelectorsDeprecationMessage) - val focusVisible : CSSSelector = PseudoClassInternal("focus-visible") + val focusVisible : CSSSelector = selectorScope.focusVisible // Resource state pseudo-classes @Deprecated(webCssSelectorsDeprecationMessage) - val playing : CSSSelector = PseudoClassInternal("playing") + val playing : CSSSelector = selectorScope.playing @Deprecated(webCssSelectorsDeprecationMessage) - val paused : CSSSelector = PseudoClassInternal("paused") + val paused : CSSSelector = selectorScope.paused // The input pseudo-classes @Deprecated(webCssSelectorsDeprecationMessage) - val autofill : CSSSelector = PseudoClassInternal("autofill") + val autofill : CSSSelector = selectorScope.autofill @Deprecated(webCssSelectorsDeprecationMessage) - val enabled : CSSSelector = PseudoClassInternal("enabled") + val enabled : CSSSelector = selectorScope.enabled @Deprecated(webCssSelectorsDeprecationMessage) - val disabled : CSSSelector = PseudoClassInternal("disabled") + val disabled : CSSSelector = selectorScope.disabled @Deprecated(webCssSelectorsDeprecationMessage) - val readOnly : CSSSelector = PseudoClassInternal("read-only") + val readOnly : CSSSelector = selectorScope.readOnly @Deprecated(webCssSelectorsDeprecationMessage) - val readWrite : CSSSelector = PseudoClassInternal("read-write") + val readWrite : CSSSelector = selectorScope.readWrite @Deprecated(webCssSelectorsDeprecationMessage) - val placeholderShown : CSSSelector = PseudoClassInternal("placeholder-shown") + val placeholderShown : CSSSelector = selectorScope.placeholderShown @Deprecated(webCssSelectorsDeprecationMessage) - val default : CSSSelector = PseudoClassInternal("default") + val default : CSSSelector = selectorScope.default @Deprecated(webCssSelectorsDeprecationMessage) - val checked : CSSSelector = PseudoClassInternal("checked") + val checked : CSSSelector = selectorScope.checked @Deprecated(webCssSelectorsDeprecationMessage) - val indeterminate : CSSSelector = PseudoClassInternal("indeterminate") + val indeterminate : CSSSelector = selectorScope.indeterminate @Deprecated(webCssSelectorsDeprecationMessage) - val blank : CSSSelector = PseudoClassInternal("blank") + val blank : CSSSelector = selectorScope.blank @Deprecated(webCssSelectorsDeprecationMessage) - val valid : CSSSelector = PseudoClassInternal("valid") + val valid : CSSSelector = selectorScope.valid @Deprecated(webCssSelectorsDeprecationMessage) - val invalid : CSSSelector = PseudoClassInternal("invalid") + val invalid : CSSSelector = selectorScope.invalid @Deprecated(webCssSelectorsDeprecationMessage) - val inRange : CSSSelector = PseudoClassInternal("in-range") + val inRange : CSSSelector = selectorScope.invalid @Deprecated(webCssSelectorsDeprecationMessage) - val outOfRange : CSSSelector = PseudoClassInternal("out-of-range") + val outOfRange : CSSSelector = selectorScope.outOfRange @Deprecated(webCssSelectorsDeprecationMessage) - val required : CSSSelector = PseudoClassInternal("required") + val required : CSSSelector = selectorScope.required @Deprecated(webCssSelectorsDeprecationMessage) - val optional : CSSSelector = PseudoClassInternal("optional") + val optional : CSSSelector = selectorScope.optional @Deprecated(webCssSelectorsDeprecationMessage) - val userInvalid : CSSSelector = PseudoClassInternal("user-invalid") + val userInvalid : CSSSelector = selectorScope.userInvalid // Tree-structural pseudo-classes @Deprecated(webCssSelectorsDeprecationMessage) - val root : CSSSelector = PseudoClassInternal("root") + val root : CSSSelector = selectorScope.root @Deprecated(webCssSelectorsDeprecationMessage) - val empty : CSSSelector = PseudoClassInternal("empty") + val empty : CSSSelector = selectorScope.empty @Deprecated(webCssSelectorsDeprecationMessage) - val first : CSSSelector = PseudoClassInternal("first") + val first : CSSSelector = selectorScope.first @Deprecated(webCssSelectorsDeprecationMessage) - val firstChild : CSSSelector = PseudoClassInternal("first-child") + val firstChild : CSSSelector = selectorScope.firstChild @Deprecated(webCssSelectorsDeprecationMessage) - val lastChild : CSSSelector = PseudoClassInternal("last-child") + val lastChild : CSSSelector = selectorScope.lastChild @Deprecated(webCssSelectorsDeprecationMessage) - val onlyChild : CSSSelector = PseudoClassInternal("only-child") + val onlyChild : CSSSelector = selectorScope.onlyChild @Deprecated(webCssSelectorsDeprecationMessage) - val firstOfType : CSSSelector = PseudoClassInternal("first-of-type") + val firstOfType : CSSSelector = selectorScope.firstOfType @Deprecated(webCssSelectorsDeprecationMessage) - val lastOfType : CSSSelector = PseudoClassInternal("last-of-type") + val lastOfType : CSSSelector = selectorScope.lastOfType @Deprecated(webCssSelectorsDeprecationMessage) - val onlyOfType : CSSSelector = PseudoClassInternal("only-of-type") + val onlyOfType : CSSSelector = selectorScope.onlyOfType @Deprecated(webCssSelectorsDeprecationMessage) - val host : CSSSelector = PseudoClassInternal("host") + val host : CSSSelector = selectorScope.host // Etc @Deprecated(webCssSelectorsDeprecationMessage) - val defined : CSSSelector = PseudoClassInternal("defined") + val defined : CSSSelector = selectorScope.defined @Deprecated(webCssSelectorsDeprecationMessage) - val left : CSSSelector = PseudoClassInternal("left") + val left : CSSSelector = selectorScope.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 PseudoClassInternal) { - name == other.name && argsStr() == other.argsStr() - } else false - } - open fun argsStr(): String? = null - override fun toString(): String = ":$name${argsStr()?.let { "($it)" } ?: ""}" - - // Linguistic pseudo-classes - internal class Lang internal constructor(val langCode: LanguageCode) : PseudoClassInternal("lang") { - override fun argsStr() = langCode - } - - // Tree-structural pseudo-classes - internal class NthChild internal constructor(val nth: Nth) : PseudoClassInternal("nth-child") { - override fun argsStr() = "$nth" - } - - internal class NthLastChild internal constructor(val nth: Nth) : PseudoClassInternal("nth-last-child") { - override fun argsStr() = "$nth" - } - - internal class NthOfType internal constructor(val nth: Nth) : PseudoClassInternal("nth-of-type") { - override fun argsStr() = "$nth" - } - - internal class NthLastOfType internal constructor(val nth: Nth) : PseudoClassInternal("nth-last-of-type") { - override fun argsStr() = "$nth" - } - - internal class Host internal constructor(val selector: CSSSelector) : PseudoClassInternal("host") { - override fun contains(other: CSSSelector, strict: Boolean): Boolean = - contains(this, other, listOf(selector), strict) - - override fun argsStr() = "${selector.asString()}" - } - - // Etc - internal class Not internal constructor(val selector: CSSSelector) : PseudoClassInternal("not") { - override fun contains(other: CSSSelector, strict: Boolean): Boolean = - contains(this, other, listOf(selector), strict) - - override fun argsStr() = "$selector" - } + val right : CSSSelector = selectorScope.right } object PseudoElement { @Deprecated(webCssSelectorsDeprecationMessage) - val after : CSSSelector = PseudoElementInternal("after") + val after : CSSSelector = selectorScope.after @Deprecated(webCssSelectorsDeprecationMessage) - val before : CSSSelector = PseudoElementInternal("before") + val before : CSSSelector = selectorScope.before @Deprecated(webCssSelectorsDeprecationMessage) - val cue : CSSSelector = PseudoElementInternal("cue") + val cue : CSSSelector = selectorScope.cue @Deprecated(webCssSelectorsDeprecationMessage) - val cueRegion : CSSSelector = PseudoElementInternal("cue-region") + val cueRegion : CSSSelector = selectorScope.cueRegion @Deprecated(webCssSelectorsDeprecationMessage) - val firstLetter : CSSSelector = PseudoElementInternal("first-letter") + val firstLetter : CSSSelector = selectorScope.firstLetter @Deprecated(webCssSelectorsDeprecationMessage) - val firstLine : CSSSelector = PseudoElementInternal("first-line") + val firstLine : CSSSelector = selectorScope.firstLine @Deprecated(webCssSelectorsDeprecationMessage) - val fileSelectorButton : CSSSelector = PseudoElementInternal("file-selector-button") + val fileSelectorButton : CSSSelector = selectorScope.fileSelectorButton @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 PseudoElementInternal) { - name == other.name && argsStr() == other.argsStr() - } else false - } - - open fun argsStr(): String? = null - override fun toString(): String = "::$name${argsStr()?.let { "($it)" } ?: ""}" - - internal class Slotted internal constructor(val selector: CSSSelector) : PseudoElementInternal("slotted") { - override fun contains(other: CSSSelector, strict: Boolean): Boolean = - contains(this, other, listOf(selector), strict) - - override fun argsStr() = selector.asString() - } + val selection : CSSSelector = selectorScope.selection } } - -@Suppress("SuspiciousEqualsCombination") -private fun contains(that: CSSSelector, other: CSSSelector, children: List, strict: Boolean): Boolean { - return that === other || // exactly same selector - children.any { it.contains(other, strict) } || // contains it in children - (!strict && that == other) // equals structurally -} - -internal const val webCssSelectorsDeprecationMessage = "Consider using a property from SelectorsScope"