Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat parse more selectors #3729

Merged
merged 19 commits into from
Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 58 additions & 12 deletions crates/swc_css_ast/src/selector.rs
Expand Up @@ -3,14 +3,26 @@ use string_enum::StringEnum;
use swc_atoms::JsWord;
use swc_common::{ast_node, EqIgnoreSpan, Span};

use crate::{Ident, Str, TokenAndSpan};
use crate::{Delimiter, Ident, Str, TokenAndSpan};

#[ast_node("SelectorList")]
pub struct SelectorList {
pub span: Span,
pub children: Vec<ComplexSelector>,
}

#[ast_node("CompoundSelectorList")]
pub struct CompoundSelectorList {
pub span: Span,
pub children: Vec<CompoundSelector>,
}

#[ast_node("RelativeSelectorList")]
pub struct RelativeSelectorList {
pub span: Span,
pub children: Vec<RelativeSelector>,
}

#[ast_node("ComplexSelector")]
pub struct ComplexSelector {
pub span: Span,
Expand All @@ -26,6 +38,13 @@ pub enum ComplexSelectorChildren {
Combinator(Combinator),
}

#[ast_node("RelativeSelector")]
pub struct RelativeSelector {
pub span: Span,
pub combinator: Option<Combinator>,
pub selector: ComplexSelector,
}

/// e.g. `foo.c1.c2`
#[ast_node("CompoundSelector")]
pub struct CompoundSelector {
Expand Down Expand Up @@ -185,29 +204,37 @@ pub struct AttributeSelectorModifier {
pub struct PseudoClassSelector {
pub span: Span,
pub name: Ident,
pub children: Option<Vec<PseudoSelectorChildren>>,
}

#[ast_node("PseudoElementSelector")]
pub struct PseudoElementSelector {
pub span: Span,
pub name: Ident,
pub children: Option<Vec<TokenAndSpan>>,
pub children: Option<Vec<PseudoClassSelectorChildren>>,
}

#[ast_node]
pub enum PseudoSelectorChildren {
pub enum PseudoClassSelectorChildren {
#[tag("TokenAndSpan")]
PreservedToken(TokenAndSpan),

#[tag("AnPlusB")]
AnPlusB(AnPlusB),

#[tag("Ident")]
Ident(Ident),

#[tag("Str")]
Str(Str),

#[tag("Delimiter")]
Delimiter(Delimiter),

#[tag("SelectorList")]
SelectorList(SelectorList),

#[tag("TokenAndSpan")]
PreservedToken(TokenAndSpan),
#[tag("CompoundSelectorList")]
CompoundSelectorList(CompoundSelectorList),

#[tag("RelativeSelectorList")]
RelativeSelectorList(RelativeSelectorList),

#[tag("CompoundSelector")]
CompoundSelector(CompoundSelector),
}

#[ast_node]
Expand All @@ -226,3 +253,22 @@ pub struct AnPlusBNotation {
pub b: Option<i32>,
pub b_raw: Option<JsWord>,
}

#[ast_node("PseudoElementSelector")]
pub struct PseudoElementSelector {
pub span: Span,
pub name: Ident,
pub children: Option<Vec<PseudoElementSelectorChildren>>,
}

#[ast_node]
pub enum PseudoElementSelectorChildren {
#[tag("TokenAndSpan")]
PreservedToken(TokenAndSpan),

#[tag("Ident")]
Ident(Ident),

#[tag("CompoundSelector")]
CompoundSelector(CompoundSelector),
}
128 changes: 98 additions & 30 deletions crates/swc_css_codegen/src/lib.rs
Expand Up @@ -1494,26 +1494,49 @@ where
self.emit_list(&n.children, ListFormat::CommaDelimited)?;
}

#[emitter]
fn emit_compound_selector_list(&mut self, n: &CompoundSelectorList) -> Result {
self.emit_list(&n.children, ListFormat::CommaDelimited)?;
}

#[emitter]
fn emit_relative_selector_list(&mut self, n: &RelativeSelectorList) -> Result {
self.emit_list(&n.children, ListFormat::CommaDelimited)?;
}

#[emitter]
fn emit_complex_selector(&mut self, n: &ComplexSelector) -> Result {
let mut need_space = false;
for (idx, node) in n.children.iter().enumerate() {
if let ComplexSelectorChildren::Combinator(..) = node {
need_space = false;
}

if idx != 0 && need_space {
need_space = false;
emit!(self, node);

self.wr.write_space()?;
match node {
ComplexSelectorChildren::Combinator(Combinator {
value: CombinatorValue::Descendant,
..
}) => {}
_ => match n.children.get(idx + 1) {
Some(ComplexSelectorChildren::Combinator(Combinator {
value: CombinatorValue::Descendant,
..
})) => {}
Some(_) => {
formatting_space!(self);
}
_ => {}
},
}
}
}

if let ComplexSelectorChildren::CompoundSelector(..) = node {
need_space = true;
}
#[emitter]
fn emit_relative_selector(&mut self, n: &RelativeSelector) -> Result {
if let Some(combinator) = &n.combinator {
emit!(self, combinator);

emit!(self, node)
formatting_space!(self);
}

emit!(self, n.selector);
}

#[emitter]
Expand Down Expand Up @@ -1689,24 +1712,47 @@ where
}

#[emitter]
fn emit_pseudo_selector_children(&mut self, n: &PseudoSelectorChildren) -> Result {
match n {
PseudoSelectorChildren::AnPlusB(n) => emit!(self, n),
PseudoSelectorChildren::Ident(n) => emit!(self, n),
PseudoSelectorChildren::SelectorList(n) => emit!(self, n),
PseudoSelectorChildren::PreservedToken(n) => emit!(self, n),
fn emit_pseudo_class_selector(&mut self, n: &PseudoClassSelector) -> Result {
punct!(self, ":");
emit!(self, n.name);

if let Some(children) = &n.children {
punct!(self, "(");
self.emit_list_pseudo_class_selector_children(children)?;
punct!(self, ")");
}
}

fn emit_list_pseudo_children(&mut self, nodes: &[PseudoSelectorChildren]) -> Result {
#[emitter]
fn emit_pseudo_class_selector_children(&mut self, n: &PseudoClassSelectorChildren) -> Result {
match n {
PseudoClassSelectorChildren::PreservedToken(n) => emit!(self, n),
PseudoClassSelectorChildren::AnPlusB(n) => emit!(self, n),
PseudoClassSelectorChildren::Ident(n) => emit!(self, n),
PseudoClassSelectorChildren::Str(n) => emit!(self, n),
PseudoClassSelectorChildren::Delimiter(n) => emit!(self, n),
PseudoClassSelectorChildren::SelectorList(n) => emit!(self, n),
PseudoClassSelectorChildren::CompoundSelectorList(n) => emit!(self, n),
PseudoClassSelectorChildren::RelativeSelectorList(n) => emit!(self, n),
PseudoClassSelectorChildren::CompoundSelector(n) => emit!(self, n),
}
}

fn emit_list_pseudo_class_selector_children(
&mut self,
nodes: &[PseudoClassSelectorChildren],
) -> Result {
let len = nodes.len();

for (idx, node) in nodes.iter().enumerate() {
emit!(self, node);

if idx != len - 1 {
match node {
PseudoSelectorChildren::PreservedToken(_) => {}
PseudoClassSelectorChildren::PreservedToken(_) => {}
PseudoClassSelectorChildren::Delimiter(_) => {
formatting_space!(self);
}
_ => {
space!(self)
}
Expand All @@ -1718,28 +1764,50 @@ where
}

#[emitter]
fn emit_pseudo_class_selector(&mut self, n: &PseudoClassSelector) -> Result {
fn emit_pseudo_element_selector(&mut self, n: &PseudoElementSelector) -> Result {
punct!(self, ":");
punct!(self, ":");
emit!(self, n.name);

if let Some(children) = &n.children {
punct!(self, "(");
self.emit_list_pseudo_children(children)?;
self.emit_list_pseudo_element_selector_children(children)?;
punct!(self, ")");
}
}

#[emitter]
fn emit_pseudo_element_selector(&mut self, n: &PseudoElementSelector) -> Result {
punct!(self, ":");
punct!(self, ":");
emit!(self, n.name);
fn emit_pseudo_element_selector_children(
&mut self,
n: &PseudoElementSelectorChildren,
) -> Result {
match n {
PseudoElementSelectorChildren::PreservedToken(n) => emit!(self, n),
PseudoElementSelectorChildren::Ident(n) => emit!(self, n),
PseudoElementSelectorChildren::CompoundSelector(n) => emit!(self, n),
}
}

if let Some(children) = &n.children {
punct!(self, "(");
self.emit_list(children, ListFormat::NotDelimited)?;
punct!(self, ")");
fn emit_list_pseudo_element_selector_children(
&mut self,
nodes: &[PseudoElementSelectorChildren],
) -> Result {
let len = nodes.len();

for (idx, node) in nodes.iter().enumerate() {
emit!(self, node);

if idx != len - 1 {
match node {
PseudoElementSelectorChildren::PreservedToken(_) => {}
_ => {
space!(self)
}
}
}
}

Ok(())
}

fn emit_list<N>(&mut self, nodes: &[N], format: ListFormat) -> Result
Expand Down