-
-
Notifications
You must be signed in to change notification settings - Fork 476
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
32 changed files
with
1,486 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[package] | ||
authors.workspace = true | ||
categories.workspace = true | ||
edition.workspace = true | ||
homepage.workspace = true | ||
keywords.workspace = true | ||
license.workspace = true | ||
name = "biome_html_formatter" | ||
repository.workspace = true | ||
version = "0.0.0" | ||
|
||
[dependencies] | ||
biome_diagnostics_categories = { workspace = true } | ||
biome_formatter = { workspace = true } | ||
biome_html_syntax = { workspace = true } | ||
biome_rowan = { workspace = true } | ||
biome_suppression = { workspace = true } | ||
|
||
[lints] | ||
workspace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use biome_diagnostics_categories::category; | ||
use biome_formatter::{ | ||
comments::{ | ||
is_alignable_comment, CommentKind, CommentPlacement, CommentStyle, Comments, | ||
DecoratedComment, SourceComment, | ||
}, | ||
prelude::*, | ||
write, FormatRule, | ||
}; | ||
use biome_html_syntax::HtmlLanguage; | ||
use biome_rowan::{SyntaxTriviaPieceComments, TextLen}; | ||
use biome_suppression::parse_suppression_comment; | ||
|
||
use crate::context::HtmlFormatContext; | ||
|
||
pub type HtmlComments = Comments<HtmlLanguage>; | ||
|
||
#[derive(Default)] | ||
pub struct FormatHtmlLeadingComment; | ||
|
||
impl FormatRule<SourceComment<HtmlLanguage>> for FormatHtmlLeadingComment { | ||
type Context = HtmlFormatContext; | ||
|
||
fn fmt( | ||
&self, | ||
comment: &SourceComment<HtmlLanguage>, | ||
f: &mut Formatter<Self::Context>, | ||
) -> FormatResult<()> { | ||
if is_alignable_comment(comment.piece()) { | ||
let mut source_offset = comment.piece().text_range().start(); | ||
|
||
let mut lines = comment.piece().text().lines(); | ||
|
||
// SAFETY: Safe, `is_alignable_comment` only returns `true` for multiline comments | ||
let first_line = lines.next().unwrap(); | ||
write!(f, [dynamic_text(first_line.trim_end(), source_offset)])?; | ||
|
||
source_offset += first_line.text_len(); | ||
|
||
// Indent the remaining lines by one space so that all `*` are aligned. | ||
write!( | ||
f, | ||
[&format_once(|f| { | ||
for line in lines { | ||
write!( | ||
f, | ||
[ | ||
hard_line_break(), | ||
text(" "), | ||
dynamic_text(line.trim(), source_offset) | ||
] | ||
)?; | ||
|
||
source_offset += line.text_len(); | ||
} | ||
|
||
Ok(()) | ||
})] | ||
) | ||
} else { | ||
write!(f, [comment.piece().as_piece()]) | ||
} | ||
} | ||
} | ||
|
||
#[derive(Eq, PartialEq, Copy, Clone, Debug, Default)] | ||
pub struct HtmlCommentStyle; | ||
|
||
impl CommentStyle for HtmlCommentStyle { | ||
type Language = HtmlLanguage; | ||
|
||
fn is_suppression(text: &str) -> bool { | ||
parse_suppression_comment(text) | ||
.filter_map(Result::ok) | ||
.flat_map(|suppression| suppression.categories) | ||
.any(|(key, _)| key == category!("format")) | ||
} | ||
|
||
fn get_comment_kind(_comment: &SyntaxTriviaPieceComments<HtmlLanguage>) -> CommentKind { | ||
CommentKind::Block | ||
} | ||
|
||
fn place_comment( | ||
&self, | ||
_comment: DecoratedComment<Self::Language>, | ||
) -> CommentPlacement<Self::Language> { | ||
todo!(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
use std::{fmt, rc::Rc}; | ||
|
||
use biome_formatter::{ | ||
printer::PrinterOptions, AttributePosition, CstFormatContext, FormatContext, FormatOptions, | ||
IndentStyle, IndentWidth, LineEnding, LineWidth, TransformSourceMap, | ||
}; | ||
use biome_html_syntax::HtmlLanguage; | ||
|
||
use crate::comments::{FormatHtmlLeadingComment, HtmlCommentStyle, HtmlComments}; | ||
|
||
#[derive(Debug, Clone, Default)] | ||
pub struct HtmlFormatOptions { | ||
/// The indent style. | ||
indent_style: IndentStyle, | ||
|
||
/// The indent width. | ||
indent_width: IndentWidth, | ||
|
||
/// The type of line ending. | ||
line_ending: LineEnding, | ||
|
||
/// What's the max width of a line. Defaults to 80. | ||
line_width: LineWidth, | ||
|
||
/// Attribute position style. By default auto. | ||
attribute_position: AttributePosition, | ||
} | ||
|
||
impl HtmlFormatOptions { | ||
pub fn new() -> Self { | ||
Self { | ||
..Default::default() | ||
} | ||
} | ||
|
||
pub fn with_indent_style(mut self, indent_style: IndentStyle) -> Self { | ||
self.indent_style = indent_style; | ||
self | ||
} | ||
|
||
pub fn with_indent_width(mut self, indent_width: IndentWidth) -> Self { | ||
self.indent_width = indent_width; | ||
self | ||
} | ||
|
||
pub fn with_line_ending(mut self, line_ending: LineEnding) -> Self { | ||
self.line_ending = line_ending; | ||
self | ||
} | ||
|
||
pub fn with_line_width(mut self, line_width: LineWidth) -> Self { | ||
self.line_width = line_width; | ||
self | ||
} | ||
|
||
pub fn with_attribute_position(mut self, attribute_position: AttributePosition) -> Self { | ||
self.attribute_position = attribute_position; | ||
self | ||
} | ||
|
||
pub fn indent_style(&self) -> IndentStyle { | ||
self.indent_style | ||
} | ||
|
||
pub fn indent_width(&self) -> IndentWidth { | ||
self.indent_width | ||
} | ||
|
||
pub fn line_ending(&self) -> LineEnding { | ||
self.line_ending | ||
} | ||
|
||
pub fn line_width(&self) -> LineWidth { | ||
self.line_width | ||
} | ||
|
||
pub fn attribute_position(&self) -> AttributePosition { | ||
self.attribute_position | ||
} | ||
|
||
pub fn set_indent_style(&mut self, indent_style: IndentStyle) { | ||
self.indent_style = indent_style; | ||
} | ||
|
||
pub fn set_indent_width(&mut self, indent_width: IndentWidth) { | ||
self.indent_width = indent_width; | ||
} | ||
|
||
pub fn set_line_ending(&mut self, line_ending: LineEnding) { | ||
self.line_ending = line_ending; | ||
} | ||
|
||
pub fn set_line_width(&mut self, line_width: LineWidth) { | ||
self.line_width = line_width; | ||
} | ||
|
||
pub fn set_attribute_position(&mut self, attribute_position: AttributePosition) { | ||
self.attribute_position = attribute_position; | ||
} | ||
} | ||
|
||
impl fmt::Display for HtmlFormatOptions { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
writeln!(f, "Indent style: {}", self.indent_style)?; | ||
writeln!(f, "Indent width: {}", self.indent_width.value())?; | ||
writeln!(f, "Line ending: {}", self.line_ending)?; | ||
writeln!(f, "Line width: {}", self.line_width.value())?; | ||
writeln!(f, "Attribute Position: {}", self.attribute_position) | ||
} | ||
} | ||
|
||
impl FormatOptions for HtmlFormatOptions { | ||
fn indent_style(&self) -> IndentStyle { | ||
self.indent_style | ||
} | ||
|
||
fn indent_width(&self) -> IndentWidth { | ||
self.indent_width | ||
} | ||
|
||
fn line_ending(&self) -> LineEnding { | ||
self.line_ending | ||
} | ||
|
||
fn line_width(&self) -> LineWidth { | ||
self.line_width | ||
} | ||
|
||
fn attribute_position(&self) -> AttributePosition { | ||
self.attribute_position | ||
} | ||
|
||
fn bracket_spacing(&self) -> biome_formatter::BracketSpacing { | ||
todo!("Bracket spacing doesn't really make sense for HTML") | ||
} | ||
|
||
fn as_print_options(&self) -> biome_formatter::prelude::PrinterOptions { | ||
PrinterOptions::from(self) | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct HtmlFormatContext { | ||
options: HtmlFormatOptions, | ||
|
||
/// The comments of the nodes and tokens in the document. | ||
comments: Rc<HtmlComments>, | ||
|
||
source_map: Option<TransformSourceMap>, | ||
} | ||
|
||
impl HtmlFormatContext { | ||
pub fn new(options: HtmlFormatOptions, comments: HtmlComments) -> Self { | ||
Self { | ||
options, | ||
comments: Rc::new(comments), | ||
source_map: None, | ||
} | ||
} | ||
|
||
pub fn with_source_map(mut self, source_map: Option<TransformSourceMap>) -> Self { | ||
self.source_map = source_map; | ||
self | ||
} | ||
} | ||
|
||
impl FormatContext for HtmlFormatContext { | ||
type Options = HtmlFormatOptions; | ||
|
||
fn options(&self) -> &Self::Options { | ||
&self.options | ||
} | ||
|
||
fn source_map(&self) -> Option<&TransformSourceMap> { | ||
self.source_map.as_ref() | ||
} | ||
} | ||
|
||
impl CstFormatContext for HtmlFormatContext { | ||
type Language = HtmlLanguage; | ||
type Style = HtmlCommentStyle; | ||
type CommentRule = FormatHtmlLeadingComment; | ||
|
||
fn comments(&self) -> &HtmlComments { | ||
&self.comments | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use biome_formatter::{Format, FormatOwnedWithRule, FormatRefWithRule, FormatResult}; | ||
|
||
use crate::{AsFormat, HtmlFormatContext, HtmlFormatter, IntoFormat}; | ||
use biome_html_syntax::{map_syntax_node, HtmlSyntaxNode}; | ||
|
||
#[derive(Debug, Copy, Clone, Default)] | ||
pub struct FormatHtmlSyntaxNode; | ||
|
||
impl biome_formatter::FormatRule<HtmlSyntaxNode> for FormatHtmlSyntaxNode { | ||
type Context = HtmlFormatContext; | ||
|
||
fn fmt(&self, node: &HtmlSyntaxNode, f: &mut HtmlFormatter) -> FormatResult<()> { | ||
map_syntax_node!(node.clone(), node => node.format().fmt(f)) | ||
} | ||
} | ||
|
||
impl AsFormat<HtmlFormatContext> for HtmlSyntaxNode { | ||
type Format<'a> = FormatRefWithRule<'a, HtmlSyntaxNode, FormatHtmlSyntaxNode>; | ||
|
||
fn format(&self) -> Self::Format<'_> { | ||
FormatRefWithRule::new(self, FormatHtmlSyntaxNode) | ||
} | ||
} | ||
|
||
impl IntoFormat<HtmlFormatContext> for HtmlSyntaxNode { | ||
type Format = FormatOwnedWithRule<HtmlSyntaxNode, FormatHtmlSyntaxNode>; | ||
|
||
fn into_format(self) -> Self::Format { | ||
FormatOwnedWithRule::new(self, FormatHtmlSyntaxNode) | ||
} | ||
} |
Oops, something went wrong.