Skip to content
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
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.
```
15 changes: 12 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,10 @@ impl Language {
Debug, Clone, Default, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum EmbeddingKind {
Astro,
Astro {
/// Whether the script is inside Astro frontmatter
frontmatter: bool,
},
Vue,
Svelte,
#[default]
Expand All @@ -129,7 +132,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 +207,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
13 changes: 12 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
Loading