feat(formatter_htmlish): format end tags of omitted html, head and body (#28388)

Some HTML tags can be written with ommiting it's opening tag.
This commit is contained in:
Yuji Sugiura authored and GitHub committed 2026-10-30 08:50:14 +00:00
1 parent 01ed68ac81
commit 0a42af6086
5 files changed
+37 -4

No files matched your search

@@ -252,8 +252,10 @@ impl Builder<'_> {
}
// CDATA reads as text, merged with the texts around it,
// and prints as written (DIVERGENCES.md#cdata-as-written).
let text_like =
matches!(node.kind, NodeKind::Text(_) | NodeKind::Comment(_) | NodeKind::Cdata);
let text_like = matches!(
node.kind,
NodeKind::Text(_) | NodeKind::Comment(_) | NodeKind::Cdata | NodeKind::EndTag(_)
);
let display = self.display(id);
let facts = self.facts(id);
facts.self_closing = self_closing;
@@ -1,7 +1,7 @@
//! Whitespace sensitivity: which gaps between nodes render, from CSS display and the options,
//! past hidden elements and Angular blocks.
use oxc_htmlish_parser::ast::{Element, Namespace, NodeId};
use oxc_htmlish_parser::ast::{Element, Namespace, NodeId, NodeKind};
use super::{Builder, is_pre_like, is_whitespace_text};
use crate::{
@@ -14,6 +14,10 @@ impl Builder<'_> {
/// a `<!-- display: -->` comment overrides it in `children`.
pub(super) fn display(&self, id: NodeId) -> Display {
let Some(el) = self.tree.element(id) else {
// An omitted element's end tag (`</body>`): no whitespace around it renders
if matches!(self.tree.kind(id), NodeKind::EndTag(_)) {
return Display::Block;
}
// Text, comments and the document: only the option applies
return match self.sensitivity {
WhitespaceSensitivity::Ignore => Display::Block,
+1 -1
View File
@@ -33,7 +33,7 @@ pub struct Facts {
pub first_child: Option<NodeId>,
pub last_child: Option<NodeId>,
pub display: Display,
/// Text and comments: printed without tags whose markers could be borrowed.
/// Text, comments and an omitted element's end tag: printed without tags whose markers could be borrowed.
pub text_like: bool,
/// No children and no end tag: the start tag closes the node.
/// Text-like nodes count too.
@@ -0,0 +1 @@
<!doctype html><title>t</title></head><p>x</p>y<!-- display: inline --></body></html>
@@ -0,0 +1,26 @@
---
source: crates/oxc_formatter_htmlish/tests/fixtures/mod.rs
---
==================== Input ====================
<!doctype html><title>t</title></head><p>x</p>y<!-- display: inline --></body></html>
==================== Output ====================
------------------
{ printWidth: 80 }
------------------
<!doctype html><title>t</title>
</head>
<p>x</p>
y<!-- display: inline --></body>
</html>
-------------------
{ printWidth: 100 }
-------------------
<!doctype html><title>t</title>
</head>
<p>x</p>
y<!-- display: inline --></body>
</html>
===================== End =====================