Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 5 additions & 0 deletions .changeset/vast-donuts-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@biomejs/biome": patch
---

`indentScriptAndStyle` no longer indents the frontmatter in Astro files.
48 changes: 48 additions & 0 deletions crates/biome_cli/tests/cases/handle_astro_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,51 @@ fn format_astro_with_typescript_script_tag() {
result,
));
}

#[test]
fn dont_indent_frontmatter() {
let fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

fs.insert(
"biome.json".into(),
r#"{ "html": { "formatter": {"enabled": true, "indentScriptAndStyle": true}, "linter": {"enabled": true}, "experimentalFullSupportEnabled": true } }"#.as_bytes(),
);

let astro_file_path = Utf8Path::new("file.astro");
fs.insert(
astro_file_path.into(),
r#"---
import Foo from "./Foo.astro"
const bar = 123
if (bar>1) {console.log(bar+1)}
---
<Foo>{bar}</Foo>

<style>
#id { font-family: comic-sans } .class { background: red}
</style>

<script>
function foo(){console.log("Hello")}
</script>
"#
.as_bytes(),
);

let (fs, result) = run_cli(
fs,
&mut console,
Args::from(["format", "--write", astro_file_path.as_str()].as_slice()),
);

assert!(result.is_ok(), "run_cli returned {result:?}");

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"dont_indent_frontmatter",
fs,
console,
result,
));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: redactor(content)
---
## `biome.json`

```json
{
"html": {
"formatter": { "enabled": true, "indentScriptAndStyle": true },
"linter": { "enabled": true },
"experimentalFullSupportEnabled": true
}
}
```

## `file.astro`

```astro
---
import Foo from "./Foo.astro";
const bar = 123;
if (bar > 1) {
console.log(bar + 1);
}
---
<Foo>{bar}</Foo>

<style>
#id {
font-family: comic-sans;
}
.class {
background: red;
}
</style>

<script>
function foo() {
console.log("Hello");
}
</script>

```

# Emitted Messages

```block
Formatted 1 file in <TIME>. Fixed 1 file.
```
14 changes: 11 additions & 3 deletions crates/biome_js_syntax/src/file_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ impl Language {
Debug, Clone, Default, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum EmbeddingKind {
Astro,
Astro {
frontmatter: bool,
},
Vue,
Svelte,
#[default]
Expand All @@ -129,7 +131,10 @@ pub enum EmbeddingKind {

impl EmbeddingKind {
pub const fn is_astro(&self) -> bool {
matches!(self, Self::Astro)
matches!(self, Self::Astro { frontmatter: false })
}
pub const fn is_astro_frontmatter(&self) -> bool {
matches!(self, Self::Astro { frontmatter: true })
}
pub const fn is_vue(&self) -> bool {
matches!(self, Self::Vue)
Expand Down Expand Up @@ -201,7 +206,10 @@ impl JsFileSource {
}

pub fn astro() -> Self {
Self::ts().with_embedding_kind(EmbeddingKind::Astro)
Self::ts().with_embedding_kind(EmbeddingKind::Astro { frontmatter: false })
}
pub fn astro_frontmatter() -> Self {
Self::ts().with_embedding_kind(EmbeddingKind::Astro { frontmatter: true })
}

/// Vue file definition
Expand Down
21 changes: 13 additions & 8 deletions crates/biome_service/src/file_handlers/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ pub(crate) fn parse_astro_embedded_script(
settings: &Settings,
) -> Option<(EmbeddedSnippet<JsLanguage>, DocumentFileSource)> {
let content = element.content_token()?;
let file_source = JsFileSource::ts().with_embedding_kind(EmbeddingKind::Astro);
let file_source =
JsFileSource::ts().with_embedding_kind(EmbeddingKind::Astro { frontmatter: true });
let document_file_source = DocumentFileSource::Js(file_source);
let options = settings.parse_options::<JsLanguage>(path, &document_file_source);
let parse = parse_js_with_offset_and_cache(
Expand Down Expand Up @@ -493,7 +494,7 @@ pub(crate) fn parse_embedded_script(
}
file_source
} else if html_file_source.is_astro() {
JsFileSource::ts().with_embedding_kind(EmbeddingKind::Astro)
JsFileSource::ts().with_embedding_kind(EmbeddingKind::Astro { frontmatter: false })
} else {
let is_module = element.is_javascript_module().unwrap_or_default();
if is_module {
Expand Down Expand Up @@ -672,8 +673,8 @@ fn format_embedded(
let mut iter = embedded_nodes.iter();
let node = iter.find(|node| node.range == range)?;

let wrap_document = |document: Document| {
if indent_script_and_style {
let wrap_document = |document: Document, should_indent: bool| {
if indent_script_and_style && should_indent {
let elements = vec![
FormatElement::Line(LineMode::Hard),
FormatElement::Tag(Tag::StartIndent),
Expand All @@ -693,27 +694,31 @@ fn format_embedded(
};

match node.source {
DocumentFileSource::Js(_) => {
DocumentFileSource::Js(file_source) => {
let js_options = settings.format_options::<JsLanguage>(biome_path, &node.source);
let node = node.node.clone().embedded_syntax::<JsLanguage>().clone();
let formatted =
biome_js_formatter::format_node_with_offset(js_options, &node).ok()?;
Some(wrap_document(formatted.into_document()))

Some(wrap_document(
formatted.into_document(),
!file_source.as_embedding_kind().is_astro_frontmatter(),
))
}
DocumentFileSource::Json(_) => {
let json_options =
settings.format_options::<JsonLanguage>(biome_path, &node.source);
let node = node.node.clone().embedded_syntax::<JsonLanguage>().clone();
let formatted =
biome_json_formatter::format_node_with_offset(json_options, &node).ok()?;
Some(wrap_document(formatted.into_document()))
Some(wrap_document(formatted.into_document(), true))
}
DocumentFileSource::Css(_) => {
let css_options = settings.format_options::<CssLanguage>(biome_path, &node.source);
let node = node.node.clone().embedded_syntax::<CssLanguage>();
let formatted =
biome_css_formatter::format_node_with_offset(css_options, &node).ok()?;
Some(wrap_document(formatted.into_document()))
Some(wrap_document(formatted.into_document(), true))
}
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_service/src/file_handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ impl Features {
match language_hint {
// TODO: remove match once we remove vue/astro/svelte handlers
DocumentFileSource::Js(source) => match source.as_embedding_kind() {
EmbeddingKind::Astro => self.astro.capabilities(),
EmbeddingKind::Astro { .. } => self.astro.capabilities(),
EmbeddingKind::Vue => self.vue.capabilities(),
EmbeddingKind::Svelte => self.svelte.capabilities(),
EmbeddingKind::None => self.js.capabilities(),
Expand Down
7 changes: 6 additions & 1 deletion packages/@biomejs/backend-jsonrpc/src/workspace.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion xtask/rules_check/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ fn assert_lint(
DocumentFileSource::Js(file_source) => {
// Temporary support for astro, svelte and vue code blocks
let (code, file_source) = match file_source.as_embedding_kind() {
EmbeddingKind::Astro => (
EmbeddingKind::Astro { .. } => (
biome_service::file_handlers::AstroFileHandler::input(code),
JsFileSource::ts(),
),
Expand Down