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(css_formatter): CssImportAtRule formatting #2180

Merged
merged 1 commit into from
Mar 25, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::prelude::*;
use biome_css_syntax::CssImportAnonymousLayer;
use biome_rowan::AstNode;
use biome_css_syntax::{CssImportAnonymousLayer, CssImportAnonymousLayerFields};
use biome_formatter::write;

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatCssImportAnonymousLayer;
impl FormatNodeRule<CssImportAnonymousLayer> for FormatCssImportAnonymousLayer {
fn fmt_fields(&self, node: &CssImportAnonymousLayer, f: &mut CssFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let CssImportAnonymousLayerFields { layer_token } = node.as_fields();

write!(f, [layer_token.format()])
}
}
24 changes: 21 additions & 3 deletions crates/biome_css_formatter/src/css/auxiliary/import_named_layer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
use crate::prelude::*;
use biome_css_syntax::CssImportNamedLayer;
use biome_rowan::AstNode;
use biome_css_syntax::{CssImportNamedLayer, CssImportNamedLayerFields};
use biome_formatter::{format_args, write};

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatCssImportNamedLayer;
impl FormatNodeRule<CssImportNamedLayer> for FormatCssImportNamedLayer {
fn fmt_fields(&self, node: &CssImportNamedLayer, f: &mut CssFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let CssImportNamedLayerFields {
layer_token,
l_paren_token,
name,
r_paren_token,
} = node.as_fields();

write!(
f,
[
layer_token.format(),
group(&format_args![
l_paren_token.format(),
soft_block_indent(&name.format()),
r_paren_token.format()
])
]
)
}
}
24 changes: 21 additions & 3 deletions crates/biome_css_formatter/src/css/auxiliary/import_supports.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
use crate::prelude::*;
use biome_css_syntax::CssImportSupports;
use biome_rowan::AstNode;
use biome_css_syntax::{CssImportSupports, CssImportSupportsFields};
use biome_formatter::{format_args, write};

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatCssImportSupports;
impl FormatNodeRule<CssImportSupports> for FormatCssImportSupports {
fn fmt_fields(&self, node: &CssImportSupports, f: &mut CssFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let CssImportSupportsFields {
supports_token,
l_paren_token,
condition,
r_paren_token,
} = node.as_fields();

write!(
f,
[
supports_token.format(),
group(&format_args![
l_paren_token.format(),
soft_block_indent(&condition.format()),
r_paren_token.format()
])
]
)
}
}
49 changes: 46 additions & 3 deletions crates/biome_css_formatter/src/css/statements/import_at_rule.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
use crate::prelude::*;
use biome_css_syntax::CssImportAtRule;
use biome_rowan::AstNode;
use biome_css_syntax::{CssImportAtRule, CssImportAtRuleFields};
use biome_formatter::write;

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatCssImportAtRule;
impl FormatNodeRule<CssImportAtRule> for FormatCssImportAtRule {
fn fmt_fields(&self, node: &CssImportAtRule, f: &mut CssFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let CssImportAtRuleFields {
import_token,
url,
layer,
supports,
media,
semicolon_token,
} = node.as_fields();

write!(f, [import_token.format(), space()])?;

// Determine if there are any modifiers present.
let has_any_modifiers = layer.is_some() || supports.is_some() || media.len() > 0;

if has_any_modifiers {
// If there are, we need to group them together and try to fill them.
let modifiers = format_once(|f| {
let separator = soft_line_break_or_space();
let mut fill = f.fill();

fill.entry(&separator, &url.format());

if let Some(layer) = layer {
fill.entry(&separator, &layer.format());
}

if let Some(supports) = supports {
fill.entry(&separator, &supports.format());
}

if media.len() > 0 {
fill.entry(&separator, &media.format());
}

fill.finish()
});
write!(f, [group(&indent(&modifiers))])?;
} else {
// If there are no modifiers, simply write the formatted `url` to the formatter `f`.
write!(f, [url.format()])?;
}

write!(f, [semicolon_token.format()])
}
}
166 changes: 166 additions & 0 deletions crates/biome_css_formatter/tests/specs/css/atrule/import.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
@import url("./style.css");
@import url('./style.css');
@import url(./style.css);
@import './style.css';
@import "./style.css";
@IMPORT url("./style.css");
@import URL(./style.css);
@import URL("./style.css");
@import"test.css";
@import "common.css" screen;
@import url('landscape.css') screen and (orientation:landscape);
@import url("theme.css") layer;
@import url("theme.css") layer ;
@import url("theme.css") LAYER;
@import url("theme.css") layer(default);
@import url("theme.css") LAYER(default);
@import url("tabs.css") layer(framework.component);
@import url("override.css") layer;
@import url("narrow.css") supports(display: flex) handheld and (max-width: 400px);
@import url("narrow.css") SUPPORTS(display: flex) handheld and (max-width: 400px);
@import url("fallback-layout.css") supports(not (display: flex));
@import url(test.css);
@import url('test.css');
@import url("test.css");
@IMPORT url(test.css);
@import URL(test.css);
@import url(test.css );
@import url( test.css);
@import url( test.css );
@import url(
test.css
);
@import url();
@import url('');
@import url("");
@import "test.css";
@import 'test.css';
@import '';
@import "";
@import " ";
@import "\
";
@import url();
@import url('');
@import url("");
@import url(test.css) screen and (orientation:landscape);
@import url(test.css) SCREEN AND (ORIENTATION: LANDSCAPE);
@import url(test.css)screen and (orientation:landscape);
@import url(test.css) screen and ( orientation : landscape ) ;
@import url(test.css) screen and (orientation:landscape);
@import url("//example.com/style.css");
@import url(~package/test.css);
@import url('https://fonts.googleapis.com/css?family=Roboto');
@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC');
@import url('https://fonts.googleapis.com/css?family=Noto+Sans+TC|Roboto');
@import url('./relative.css');
@import url('../import/top-relative.css');
@import url(~package/tilde.css);
@import url(~aliasesImport/alias.css);
@import url('./url.css');

@import url(./test.css);

@import './te\
st.css';
@import './te\
\
\
st.css';
@import url('./te\
st.css');
@import url('./te\
\
\
st.css');

@import "./te'st.css";
@import url("./te'st.css");
@import './te\'st.css';
@import url('./te\'st.css');
@import './test test.css';
@import url('./test test.css');
@import './test\ test.css';
@import url('./test\ test.css');
@import './test%20test.css';
@import url('./test%20test.css');
@import './\74\65\73\74.css';
@import url('./\74\65\73\74.css');
@import './t\65\73\74.css';
@import url('./t\65\73\74.css');
@import url(./test\ test.css);
@import url(./t\65st%20test.css);
@import url('./t\65st%20test.css');
@import url("./t\65st%20test.css");
@import "./t\65st%20test.css";
@import './t\65st%20test.css';
@import url( test.css );
@import '\
\
\
';
@import url('!!../../helpers/string-loader.js?esModule=false!~package/tilde.css');

@import url(test.css?foo=bar);
@import url(test.css?foo=bar#hash);
@import url(test.css?#hash);

@import "test.css" supports(display: flex);
@import "test.css" supports(display: flex) screen and (orientation:landscape);
@import"test.css"supports(display: flex)screen and (orientation:landscape);

@import " ./test.css ";
@import url(' ./test.css ');
@import url( ./test.css );

@import "./my.scss";

@import url(' https://fonts.googleapis.com/css?family=Roboto ');
@import url('!!../../helpers/string-loader.js?esModule=false!');
@import url(' !!../../helpers/string-loader.js?esModule=false!~package/tilde.css ');
@import url(data:text/css;charset=utf-8,a%20%7B%0D%0A%20%20color%3A%20red%3B%0D%0A%7D);

@import url(package/first.css);
@import url(package/second.css);

@import url("./test.css") supports(display: flex);
@import url("./test.css") supports(display: flex !important);
@import url("./test.css") supports(display: flex) screen and (min-width: 400px);
@import url("./test.css") layer;
@import url("./test.css") layer(default);
@import url("./test.css") layer(default) supports(display: flex) screen and (min-width: 400px);
@import url("./test.css") layer supports(display: flex) screen and (min-width: 400px);
@import url("./test.css") layer supports(display: flex) screen and (min-width: 400px);
@import url("./test.css") layer;
@import url("http://example.com/style.css") supports(display: flex) screen and (min-width: 400px);
@import url("./test.css")layer(default)supports(display: flex)screen and (min-width:400px);
@import url("./test.css")screen and (min-width: 400px);
@import url("./test.css") layer( default ) supports( display : flex ) screen and ( min-width : 400px );
@import url("./test.css") LAYER(DEFAULT) SUPPORTS(DISPLAY: FLEX) SCREEN AND (MIN-WIDTH: 400PX);
@import url("./test.css") /* Comment */ layer(/* Comment */default/* Comment */) /* Comment */ supports(/* Comment */display/* Comment */:/* Comment */ flex/* Comment */)/* Comment */ screen/* Comment */ and/* Comment */ (/* Comment */min-width/* Comment */: /* Comment */400px/* Comment */);
@import url(test.css) /* Comment */;
@import /* Comment */ url(test.css) /* Comment */;
@import url(test.css) /* Comment */ print and (orientation:landscape);
@import /* Comment */ url(test.css) /* Comment */ print and (orientation:landscape);

@import url("./deep-import-with-media.css") (prefers-color-scheme: dark);
@import url("./import-with-supports.css") supports(display: flex);
@import url("./import-with-supports.css") supports(((display: flex)));
@import url("./deep-import-with-supports.css") supports(display: flex);
@import url('./test.css') supports(display: grid);
@import url('./test.css') supports( display : grid );
@import url("./import-with-supports-and-media.css") supports(display: flex) screen and (min-width: 400px);
@import url("./test.css") layer(framework);
@import url("./import-multiple-with-layer.css") layer(default);
@import url("./import-unnamed-layer.css") layer(base);
@import url("./import-with-layer-and-supports.css") layer(default) supports(display: flex);

@import url(bootstrap-base.css) layer(base);
@import url(base-headings.css) layer;
@import url("tabs.css") layer(framework.component);
@import url("override.css") layer;
@import url("fallback-layout.css") supports(not (display: flex));
@import url("narrow.css") supports(display: flex) screen and (max-width: 400px);

@import "test.css" supports( display: flex );
@import url("tabs.css") layer( framework.component );
Loading
Loading