Skip to content

Commit

Permalink
feat: add selectorOverrideCommentDirective option
Browse files Browse the repository at this point in the history
  • Loading branch information
g-plane committed Aug 3, 2024
1 parent bdebb2a commit 6304f34
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 3 deletions.
34 changes: 34 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,40 @@ Default option is `"always"`.
[key=value] {}
```

## `selectorOverrideCommentDirective`

Text directive for overriding selector formatting.

This can be used to ignore formatting selector of a specific qualified rule without ignoring the whole qualified rule.
Or, it can be used to format a specific selector in a different way.
For example, you're resetting CSS with many tag name selectors,
then you can use "wrap" style to format this selector only without affecting other selectors.

Suppose `"blockSelectorLineBreak"` is `"always"` in configuration, with the following CSS:

```css
/* malva-selector-override wrap */
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
pre, abbr {}

.btn,
.btn-primary {}
```

Note that nested qualified rules won't be affected:

```css
/* malva-selector-override wrap */
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
pre, abbr {
/* nested qualified rule is still respecting configuration, not overriden value */
.btn,
.btn-primary {}
}
```

Default is `"malva-selector-override"`.

## `ignoreCommentDirective`

Text directive for ignoring formatting specific statement.
Expand Down
5 changes: 5 additions & 0 deletions dprint_plugin/deployment/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@
],
"default": "always"
},
"selectorOverrideCommentDirective": {
"description": "Text directive for overriding selector formatting.",
"type": "string",
"default": "malva-selector-override"
},
"ignoreCommentDirective": {
"description": "Text directive for ignoring formatting specific statement.",
"type": "string",
Expand Down
6 changes: 6 additions & 0 deletions dprint_plugin/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ pub(crate) fn resolve_config(
Default::default()
}
},
selector_override_comment_directive: get_value(
&mut config,
"selectorOverrideCommentDirective",
"malva-selector-override".into(),
&mut diagnostics,
),
ignore_comment_directive: get_value(
&mut config,
"ignoreCommentDirective",
Expand Down
8 changes: 8 additions & 0 deletions malva/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ pub struct LanguageOptions {
/// See [`attrValueQuotes`](https://github.com/g-plane/malva/blob/main/docs/config.md#attrvaluequotes) on GitHub
pub attr_value_quotes: AttrValueQuotes,

#[cfg_attr(
feature = "config_serde",
serde(alias = "selectorOverrideCommentDirective")
)]
/// See [`selectorOverrideCommentDirective`](https://github.com/g-plane/malva/blob/main/docs/config.md#selectoroverridecommentdirective) on GitHub
pub selector_override_comment_directive: String,

#[cfg_attr(feature = "config_serde", serde(alias = "ignoreCommentDirective"))]
/// See [`ignoreCommentDirective`](https://github.com/g-plane/malva/blob/main/docs/config.md#ignorecommentdirective) on GitHub
pub ignore_comment_directive: String,
Expand All @@ -156,6 +163,7 @@ impl Default for LanguageOptions {
single_line_block_threshold: None,
keyframe_selector_notation: None,
attr_value_quotes: AttrValueQuotes::default(),
selector_override_comment_directive: "malva-selector-override".into(),
ignore_comment_directive: "malva-ignore".into(),
}
}
Expand Down
27 changes: 25 additions & 2 deletions malva/src/doc_gen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,34 @@ pub(super) fn format_selectors_before_block<'s, N>(
where
N: DocGen<'s> + Spanned,
{
use crate::config::BlockSelectorLineBreak;
use crate::{config::BlockSelectorLineBreak, state::SelectorOverride};

let linebreak = match state.selector_override {
SelectorOverride::Unset => ctx.options.block_selector_linebreak.clone(),
SelectorOverride::Ignore => {
if let Some(source) = ctx.source {
let first = selectors[0].span();
let raw = &source[first.start
..selectors
.last()
.map(|last| last.span())
.unwrap_or(first)
.end];
return Doc::list(
itertools::intersperse(raw.lines().map(Doc::text), Doc::empty_line()).collect(),
);
} else {
ctx.options.block_selector_linebreak.clone()
}
}
SelectorOverride::Always => BlockSelectorLineBreak::Always,
SelectorOverride::Consistent => BlockSelectorLineBreak::Consistent,
SelectorOverride::Wrap => BlockSelectorLineBreak::Wrap,
};

SeparatedListFormatter::new(
",",
match ctx.options.block_selector_linebreak {
match linebreak {
BlockSelectorLineBreak::Always => Doc::hard_line(),
BlockSelectorLineBreak::Consistent => Doc::line_or_space(),
BlockSelectorLineBreak::Wrap => Doc::soft_line(),
Expand Down
3 changes: 2 additions & 1 deletion malva/src/doc_gen/less.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,12 @@ impl<'s> DocGen<'s> for LessConditions<'s> {
}

impl<'s> DocGen<'s> for LessDetachedRuleset<'s> {
fn doc(&self, ctx: &Ctx<'_, 's>, _: &State) -> Doc<'s> {
fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
self.block.doc(
ctx,
&State {
in_less_detached_ruleset: true,
..state.clone()
},
)
}
Expand Down
26 changes: 26 additions & 0 deletions malva/src/doc_gen/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,13 @@ struct SingleStmtFormatter<'a, 's> {
}
impl<'a, 's> SingleStmtFormatter<'a, 's> {
fn format(self, ctx: &Ctx<'_, 's>, state: &State) -> Vec<Doc<'s>> {
use crate::state::SelectorOverride;

let mut docs = Vec::with_capacity(3);

let span = self.stmt.span();
let is_qualified_rule = self.stmt.is_qualified_rule();
let mut selector_override = SelectorOverride::Unset;

let comments = ctx.get_comments_between(*self.pos, span.start);
let has_comments =
Expand All @@ -505,6 +509,20 @@ impl<'a, 's> SingleStmtFormatter<'a, 's> {
}
}
docs.push(format_comment(comment, ctx));
if is_qualified_rule {
selector_override = comment
.content
.trim()
.strip_prefix(&ctx.options.selector_override_comment_directive)
.map(|s| match s.strip_prefix(':').unwrap_or(s).trim() {
"ignore" => SelectorOverride::Ignore,
"always" => SelectorOverride::Always,
"consistent" => SelectorOverride::Consistent,
"wrap" => SelectorOverride::Wrap,
_ => SelectorOverride::Unset,
})
.unwrap_or(SelectorOverride::Unset);
}
*self.pos = comment.span.end;
true
});
Expand All @@ -517,6 +535,14 @@ impl<'a, 's> SingleStmtFormatter<'a, 's> {
docs.push(Doc::hard_line());
}
}
let state = if is_qualified_rule {
&State {
selector_override,
..state.clone()
}
} else {
state
};
if comments
.last()
.and_then(|comment| {
Expand Down
1 change: 1 addition & 0 deletions malva/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub fn print_stylesheet<'a, 's>(
};
let state = State {
in_less_detached_ruleset: false,
selector_override: crate::state::SelectorOverride::Unset,
};
let doc = stylesheet.doc(&ctx, &state);
tiny_pretty::print(
Expand Down
10 changes: 10 additions & 0 deletions malva/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
#[derive(Clone)]
pub(crate) struct State {
pub(crate) in_less_detached_ruleset: bool,
pub(crate) selector_override: SelectorOverride,
}

#[derive(Clone)]
pub(crate) enum SelectorOverride {
Unset,
Ignore,
Always,
Consistent,
Wrap,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* malva-selector-override always */
div,span {
div,span{} /* this shouldn't be overriden */
}

/* malva-selector-override: always */
div,span {
div,span{} /* this shouldn't be overriden */
}
14 changes: 14 additions & 0 deletions malva/tests/fmt/css/block-selector-linebreak/override-always.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: malva/tests/fmt.rs
---
/* malva-selector-override always */
div,
span {
div, span {} /* this shouldn't be overriden */
}

/* malva-selector-override: always */
div,
span {
div, span {} /* this shouldn't be overriden */
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*cfg blockSelectorLinebreak = "always"*/

/* malva-selector-override consistent */
div,span {
div,span{} /* this shouldn't be overriden */
}

/* malva-selector-override: consistent */
div,span {
div,span{} /* this shouldn't be overriden */
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: malva/tests/fmt.rs
---
/*cfg blockSelectorLinebreak = "always"*/

/* malva-selector-override consistent */
div, span {
div,
span {} /* this shouldn't be overriden */
}

/* malva-selector-override: consistent */
div, span {
div,
span {} /* this shouldn't be overriden */
}
13 changes: 13 additions & 0 deletions malva/tests/fmt/css/block-selector-linebreak/override-ignore.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* malva-selector-override ignore */
h1, h2,
h3, h4,
h5, h6 {
div,span{} /* this shouldn't be overriden */
}

/* malva-selector-override: ignore */
h1, h2,
h3, h4,
h5, h6 {
div,span{} /* this shouldn't be overriden */
}
16 changes: 16 additions & 0 deletions malva/tests/fmt/css/block-selector-linebreak/override-ignore.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
source: malva/tests/fmt.rs
---
/* malva-selector-override ignore */
h1, h2,
h3, h4,
h5, h6 {
div, span {} /* this shouldn't be overriden */
}

/* malva-selector-override: ignore */
h1, h2,
h3, h4,
h5, h6 {
div, span {} /* this shouldn't be overriden */
}
17 changes: 17 additions & 0 deletions malva/tests/fmt/css/block-selector-linebreak/override-wrap.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*cfg blockSelectorLinebreak = "always"*/

/* malva-selector-override wrap */
html, body, div,
span, object, iframe,
h1, h2, h3, h4, h5, h6,
p, blockquote, pre, abbr {
div,span{} /* this shouldn't be overriden */
}

/* malva-selector-override: wrap */
html, body, div,
span, object, iframe,
h1, h2, h3, h4, h5, h6,
p, blockquote, pre, abbr {
div,span{} /* this shouldn't be overriden */
}
18 changes: 18 additions & 0 deletions malva/tests/fmt/css/block-selector-linebreak/override-wrap.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: malva/tests/fmt.rs
---
/*cfg blockSelectorLinebreak = "always"*/

/* malva-selector-override wrap */
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
pre, abbr {
div,
span {} /* this shouldn't be overriden */
}

/* malva-selector-override: wrap */
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
pre, abbr {
div,
span {} /* this shouldn't be overriden */
}

0 comments on commit 6304f34

Please sign in to comment.