Skip to content

Commit

Permalink
Add :only-child pseudo-class selector
Browse files Browse the repository at this point in the history
  • Loading branch information
kzu committed Aug 31, 2021
1 parent 2427ab9 commit b6bbc91
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 1 deletion.
5 changes: 5 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ At the moment, supports the following CSS selector features:
- [Attribute selector](https://www.w3.org/TR/selectors-3/#attribute-selectors)
- [Class selector](https://www.w3.org/TR/selectors-3/#class-html)
- [ID selector](https://www.w3.org/TR/selectors-3/#id-selectors)
- [Pseudo-classes](https://www.w3.org/TR/selectors-3/#pseudo-classes):
* [:checked](https://www.w3.org/TR/selectors-3/#checked)
* [:first-child](https://www.w3.org/TR/selectors-3/#first-child-pseudo)
* [:last-child](https://www.w3.org/TR/selectors-3/#last-child-pseudo)
* [:only-child](https://www.w3.org/TR/selectors-3/#only-child-pseudo)

And all [combinators](https://www.w3.org/TR/selectors-3/#combinators)

Expand Down
7 changes: 7 additions & 0 deletions src/Css/Css.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ record LastChildSelector : SimpleSelector
public override void Append(StringBuilder builder) => builder.Append("[not(following-sibling::*)]");
}

record OnlyChildSelector : SimpleSelector
{
public static SimpleSelector Default { get; } = new OnlyChildSelector();
OnlyChildSelector() { }
public override void Append(StringBuilder builder) => builder.Append("[not(preceding-sibling::*) and not(following-sibling::*)]");
}

enum Combinator
{
None,
Expand Down
2 changes: 2 additions & 0 deletions src/Css/Parser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,13 @@ class Parser
from identifier in Span.EqualTo("checked")
.Or(Span.EqualTo("first-child"))
.Or(Span.EqualTo("last-child"))
.Or(Span.EqualTo("only-child"))
select identifier.ToStringValue() switch
{
"checked" => CheckedSelector.Default,
"first-child" => FirstChildSelector.Default,
"last-child" => LastChildSelector.Default,
"only-child" => OnlyChildSelector.Default,
_ => throw new NotSupportedException()
})
.Named("checked pseudo selector");
Expand Down
1 change: 1 addition & 0 deletions src/Tests/XPathTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void ToXPath(string css, string xpath)
[InlineData("option:checked", "second")]
[InlineData("div:first-child", "Warning Hello")]
[InlineData("div:last-child", "Footer")]
[InlineData("h1:only-child", "Sub-header")]
[Theory]
public void EvaluatePageHtml(string expression, string value)
=> Assert.Equal(value, string.Join(' ', XDocument.Load("page.html")
Expand Down
5 changes: 4 additions & 1 deletion src/Tests/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
</head>
<body>
<div role="alert">Warning</div>
<p>para</p>
<h1>Header</h1>
<p>
<h1>Sub-header</h1>
</p>
<div class="container main flow">
<div id="title">Hello</div>
<span>1</span>
Expand Down

0 comments on commit b6bbc91

Please sign in to comment.