mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
docs(oxfmt,formatter_htmlish,formatter): clean up behavior comments (#28384)
We do not need to note about Prettier internals.
This commit is contained in:
1 parent
a5b0c0a054
commit
01ed68ac81
21 files changed
+40
-42
No files matched your search
@@ -342,8 +342,7 @@ pub fn build_dispatcher(
|
||||
dispatch_config.toml_options(),
|
||||
),
|
||||
NativeLanguage::Html(variant) => {
|
||||
// Every part is embedded in its parent (Prettier's `parentParser`),
|
||||
// but a JSDoc code block, formatted on its own
|
||||
// Every part is embedded in its parent, but a JSDoc code block, formatted on its own
|
||||
let embedded_in =
|
||||
if let Some(c) = request.parent_context_as::<HtmlInJsTemplate>() {
|
||||
Some(HtmlishEmbeddedIn {
|
||||
|
||||
@@ -17,7 +17,7 @@ use oxc_formatter_core::{
|
||||
use super::dispatcher::ResolvedDispatchConfig;
|
||||
|
||||
/// Parent→child context for a JSDoc fenced code block:
|
||||
/// a part formatted on its own, as Prettier formats it (`prettier.format`, no `parentParser`),
|
||||
/// a part formatted on its own, as a file is,
|
||||
/// where every other dispatched part is embedded in its parent.
|
||||
pub struct XxxInJsdocFence;
|
||||
|
||||
|
||||
@@ -284,9 +284,8 @@ describe("Embedded languages", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
// (css-in-html)-in-js: For now, HTML is handled by Prettier, so CSS is also handled by Prettier too.
|
||||
// The CSS `Doc` carries a trailing space after `prop: ` that only materializes when the value fits flat;
|
||||
// when the value breaks, it must not leak (the Doc→IR conversion maps it to a pending space, dropped at the break).
|
||||
// (css-in-html)-in-js: the space after `prop:` belongs to a value that fits on the line,
|
||||
// so a value that breaks must not leave it at the end of the line.
|
||||
it("should not leak a trailing space when a css-in-html declaration value breaks", async () => {
|
||||
const input = `\
|
||||
export const BaseStyles = html\`
|
||||
|
||||
@@ -39,7 +39,7 @@ pub const HTML_PLACEHOLDER_SUFFIX: &str = "_IN_JS";
|
||||
|
||||
/// `name` is an html-in-js placeholder, of any depth.
|
||||
/// One in a `<script>` stands in for an expression of any precedence (`f((${a + b}) / 2)`),
|
||||
/// so the parens around it in the source stay (Prettier's `parentheses/identifier.js`).
|
||||
/// so the parens around it in the source stay.
|
||||
pub fn is_html_placeholder(name: &str) -> bool {
|
||||
name.strip_prefix(HTML_PLACEHOLDER_PREFIX)
|
||||
.and_then(|id| id.strip_suffix(HTML_PLACEHOLDER_SUFFIX))
|
||||
|
||||
@@ -258,7 +258,7 @@ impl<'ast> JsFormatContext<'ast> {
|
||||
self.embedded_in == Some(JsEmbeddedIn::HtmlEventHandler)
|
||||
}
|
||||
|
||||
/// The quote a string prints in (Prettier's `printString`), the formatter's own too (a quoted property key):
|
||||
/// The quote a string prints in, the formatter's own too (a quoted property key):
|
||||
/// the configured one, but `'` in an HTML attribute.
|
||||
/// A JSX attribute and a directive have their own (`FormatLiteralStringToken`).
|
||||
pub(crate) fn string_quote_style(&self) -> QuoteStyle {
|
||||
|
||||
@@ -184,7 +184,7 @@ pub fn format_fragment<'a>(
|
||||
// this may not be enough for all cases.
|
||||
// But it seems fine for almost all cases, so leave it for now.
|
||||
// TODO: When Vue formats natively, share the HTML event handler's rule instead
|
||||
// (`JsFormatContext::string_quote_style`, forced `'` as Prettier's `__isInHtmlAttribute`):
|
||||
// (`JsFormatContext::string_quote_style`, `'` whatever the string holds):
|
||||
// a string holding more `'` than `"` prints `"` here, which the attribute escapes as `"`.
|
||||
let options = JsFormatOptions { quote_style: QuoteStyle::Single, ..options };
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ impl NeedsParentheses<'_> for AstNode<'_, '_, IdentifierReference<'_>> {
|
||||
return false;
|
||||
}
|
||||
// An html-in-js placeholder (reaching JS through HTML's `<script>` or `on*` attributes)
|
||||
// stands in for an expression of any precedence, as Prettier's `parentheses/identifier.js` does
|
||||
// stands in for an expression of any precedence: the parens around it in the source stay
|
||||
if is_html_placeholder(self.name.as_str()) {
|
||||
return is_parenthesized_in_source(self, f);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ impl<'a> FormatLiteralStringToken<'a> {
|
||||
let options = f.options();
|
||||
let source_type = f.context().source_type();
|
||||
|
||||
// In an HTML attribute, `'` always (Prettier's `__isInHtmlAttribute`), but a directive as usual
|
||||
// In an HTML attribute, `'` whatever the string holds, but a directive as usual
|
||||
let (chosen_quote_style, force_chosen_quote) = if self.jsx {
|
||||
(options.jsx_quote_style, false)
|
||||
} else if self.parent_kind == StringLiteralParentKind::Directive {
|
||||
|
||||
@@ -177,7 +177,7 @@ pub enum CssEmbeddedIn {
|
||||
/// A css-in-js template: SCSS grammar with `${}` placeholder markers ([`CssRoot::CssInJsTemplate`]).
|
||||
CssInJsTemplate,
|
||||
/// An HTML `style` attribute's value: its declarations print on one line when they fit,
|
||||
/// the last `;` only when they do not (Prettier's `__isHTMLStyleAttribute`).
|
||||
/// the last `;` only when they do not.
|
||||
HtmlStyleAttribute,
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ a dialect adds a field there, not a `Dialect` check at the use site.
|
||||
|
||||
### Preprocess
|
||||
|
||||
The facts Prettier's `print-preprocess` computes (CSS display, whitespace sensitivity, kept children, borrowed tag markers)
|
||||
The facts the printer needs besides the AST (CSS display, whitespace sensitivity, kept children, borrowed tag markers)
|
||||
are a table keyed by `NodeId` (`src/tree/`).
|
||||
The AST is never rewritten.
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ pub fn format_to_ir<'a>(
|
||||
///
|
||||
/// The host translates the parent's request into this;
|
||||
/// `None` is a part formatted on its own (e.g. a JSDoc code block).
|
||||
/// Embedded HTML leaves `class` and `allow` values as written (as Prettier does with a `parentParser`).
|
||||
/// Embedded HTML leaves `style`, `on*`, `class` and `allow` values as written, as Prettier does.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct HtmlishEmbeddedIn {
|
||||
/// Indent the content when more than one node prints at the root
|
||||
|
||||
@@ -220,7 +220,7 @@ pub(super) fn quoted_piece<'a>(piece: &'a str, f: &HtmlishFormatter<'_, 'a>) ->
|
||||
arena_cow_str(&piece.cow_replace('"', """), f)
|
||||
}
|
||||
|
||||
/// Prettier's `printExpand`: `content` on its own indented lines when the group breaks.
|
||||
/// `content` in quotes, on its own indented lines when the group breaks.
|
||||
pub(super) fn write_expanded<'a>(
|
||||
content: &impl Format<'a, HtmlishFormatContext<'a>>,
|
||||
f: &mut HtmlishFormatter<'_, 'a>,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! What separates siblings (Prettier's `printChildren`), and the line break facts it reads from the source.
|
||||
//! What separates siblings, and the line break facts it reads from the source.
|
||||
|
||||
use oxc_formatter_core::{
|
||||
Format, GroupId,
|
||||
@@ -16,7 +16,7 @@ use super::{
|
||||
};
|
||||
use crate::{context::HtmlishFormatContext, tree::Tree};
|
||||
|
||||
/// What separates two siblings (Prettier's `printBetweenLine`).
|
||||
/// What separates two siblings.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Between {
|
||||
Nothing,
|
||||
@@ -218,7 +218,7 @@ pub fn write_children<'a>(
|
||||
}
|
||||
|
||||
/// A separator between siblings; a kept blank line is `empty_line`
|
||||
/// (Prettier's two `hardline`s, which would collapse into one here).
|
||||
/// (two hard line breaks would collapse into one).
|
||||
fn write_between(between: Between, blank: bool, f: &mut HtmlishFormatter<'_, '_>) {
|
||||
match between {
|
||||
Between::Nothing => {}
|
||||
|
||||
@@ -175,7 +175,7 @@ fn should_preserve_content(t: &Tree<'_>, id: NodeId) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// The source between the tags, adjusted for markers the edges borrow (Prettier's `getNodeContent`).
|
||||
/// The source between the tags, adjusted for markers the edges borrow.
|
||||
fn node_content<'a>(t: &'a Tree<'a>, id: NodeId) -> &'a str {
|
||||
let item = &t[id];
|
||||
let mut start = t.content_start(id) as usize;
|
||||
|
||||
@@ -163,7 +163,7 @@ pub fn write_embedded_content<'a>(
|
||||
f: &mut HtmlishFormatter<'_, 'a>,
|
||||
) -> bool {
|
||||
let Some(language) = content_language(t, id) else { return false };
|
||||
// A Markdown body starts at the line after the tag, dedented (Prettier's `dedentString`)
|
||||
// A Markdown body starts at the line after the tag, dedented
|
||||
let value = if language == "markdown" {
|
||||
let value = value
|
||||
.find('\n')
|
||||
@@ -213,8 +213,8 @@ fn escape_script_end<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
/// The language of the body of `<script>` / `<style>` element `id`, a name the dispatcher resolves
|
||||
/// (Prettier's `inferScriptParser` / `inferStyleParser`); `None` for none (`<script src>`, a template type).
|
||||
/// The language of the body of `<script>` / `<style>` element `id`, a name the dispatcher resolves;
|
||||
/// `None` for none (`<script src>`, a template type).
|
||||
fn content_language<'a>(t: &'a Tree<'a>, id: NodeId) -> Option<&'a str> {
|
||||
let el = t.element(id)?;
|
||||
let attribute = |name: &str| {
|
||||
@@ -235,7 +235,7 @@ fn content_language<'a>(t: &'a Tree<'a>, id: NodeId) -> Option<&'a str> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A `<script type>` (Prettier's `inferParserByTypeAttribute`).
|
||||
/// The language a `<script type>` names.
|
||||
fn script_type_language(kind: &str) -> Option<&str> {
|
||||
Some(match kind {
|
||||
"module" | "text/javascript" | "application/javascript" => "js",
|
||||
|
||||
@@ -73,7 +73,7 @@ fn write_child<'a>(t: &'a Tree<'a>, id: NodeId, f: &mut HtmlishFormatter<'_, 'a>
|
||||
write!(f, [opening_tag_prefix(t, id), text(raw), closing_tag_suffix(t, id)]);
|
||||
}
|
||||
|
||||
/// Prettier's `getEndLocation`: an unclosed element extends to its last child.
|
||||
/// Where an ignored node's source ends: an unclosed element extends to its last child.
|
||||
fn ignored_end(t: &Tree<'_>, id: NodeId) -> u32 {
|
||||
let end = t.source_end(id);
|
||||
match t.kind(id) {
|
||||
|
||||
@@ -63,7 +63,7 @@ pub fn write_text<'a>(t: &'a Tree<'a>, id: NodeId, f: &mut HtmlishFormatter<'_,
|
||||
fill.finish();
|
||||
}
|
||||
|
||||
/// Writes `value`'s lines, trimmed and dedented (Prettier's `htmlTrimPreserveIndentation` + `dedentString`),
|
||||
/// Writes `value`'s lines, trimmed and dedented ([`trim_preserving_indentation`], [`dedent`]),
|
||||
/// joined by line breaks: every blank line is kept, and prints without indentation.
|
||||
pub fn write_dedented_lines<'a>(value: &'a str, f: &mut HtmlishFormatter<'_, 'a>) {
|
||||
let mut breaks = 0;
|
||||
@@ -102,7 +102,7 @@ fn words(value: &str, cdata: bool) -> impl Iterator<Item = &str> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Prettier's `htmlTrimPreserveIndentation`: trailing whitespace and leading blank lines go.
|
||||
/// `value` without its trailing whitespace and leading blank lines.
|
||||
fn trim_preserving_indentation(value: &str) -> &str {
|
||||
let value = value.trim_ascii_end();
|
||||
let mut start = 0;
|
||||
@@ -132,7 +132,7 @@ pub fn dedent_string<'a>(value: &'a str, f: &HtmlishFormatter<'_, 'a>) -> &'a st
|
||||
out.into_str()
|
||||
}
|
||||
|
||||
/// Prettier's `dedentString`: the lines with their common indentation removed.
|
||||
/// The lines of `value` with their common indentation removed.
|
||||
fn dedent(value: &str) -> impl Iterator<Item = &str> {
|
||||
dedent_by(value, common_indentation(value))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use oxc_htmlish_parser::ast::NodeId;
|
||||
use super::Builder;
|
||||
|
||||
impl Builder<'_> {
|
||||
/// Texts and CDATA sections next to each other print as one text (Prettier's `mergeCdataIntoText`);
|
||||
/// Texts and CDATA sections next to each other print as one text;
|
||||
/// the source between them, whitespace included, is the merged value.
|
||||
pub(super) fn merge_cdata(&mut self, parent: NodeId) {
|
||||
let mut next = self.tree[parent].first_child;
|
||||
@@ -38,7 +38,7 @@ impl Builder<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// `a<b>x</b>c` prints as one text (Prettier's `mergeSimpleElementIntoText`):
|
||||
/// `a<b>x</b>c` prints as one text:
|
||||
/// the text before absorbs the element and the text after.
|
||||
pub(super) fn merge_simple_elements(&mut self, parent: NodeId) {
|
||||
let mut next = self.tree[parent].first_child;
|
||||
|
||||
@@ -218,7 +218,7 @@ impl Builder<'_> {
|
||||
}
|
||||
|
||||
/// `<!--[if IE]><!--><html><!--<![endif]-->`: for the start comment, the element whose start tag absorbs it
|
||||
/// together with the end comment, its first child (Prettier's `mergeIfConditionalStartEndCommentIntoElementOpeningTag`).
|
||||
/// together with the end comment, its first child.
|
||||
fn absorbing_element(&self, id: NodeId) -> Option<NodeId> {
|
||||
let root = self.tree.root;
|
||||
let start = &root[id];
|
||||
@@ -250,8 +250,8 @@ impl Builder<'_> {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// CDATA is text to Prettier (`mergeCdataIntoText`),
|
||||
// printed as written here (DIVERGENCES.md#cdata-as-written).
|
||||
// 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 display = self.display(id);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// The CSS `display` an element gets from the UA stylesheet (Prettier's table, `constants.evaluate.js`).
|
||||
/// The CSS `display` an element gets from the UA stylesheet, as Prettier tabulates it.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub enum Display {
|
||||
#[default]
|
||||
@@ -30,7 +30,7 @@ impl Display {
|
||||
}
|
||||
}
|
||||
|
||||
/// `<!-- display: block -->` (Prettier's `/^\s*display:\s*([a-z]+)\s*$/`).
|
||||
/// `<!-- display: block -->`: `display:` and a lowercase word, whitespace around them.
|
||||
pub fn display_comment(content: &str) -> Option<Display> {
|
||||
let value = content.trim().strip_prefix("display:")?.trim_start();
|
||||
if value.is_empty() || !value.bytes().all(|b| b.is_ascii_lowercase()) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! The facts Prettier's `print-preprocess` attaches to its tree, as a table keyed by the parser's [`NodeId`].
|
||||
//! The facts the printer needs besides the AST, as a table keyed by the parser's [`NodeId`].
|
||||
//!
|
||||
//! The AST is not rewritten; names, kinds and the tag table's verdict are read from it.
|
||||
//! What the table adds:
|
||||
@@ -24,7 +24,7 @@ pub use display::Display;
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct Facts {
|
||||
/// Prettier's `sourceSpan`: a text in a whitespace-insensitive parent is trimmed.
|
||||
/// The span the node prints: a text in a whitespace-insensitive parent is trimmed.
|
||||
pub span: Span,
|
||||
/// The parent, siblings and children that print.
|
||||
pub parent: Option<NodeId>,
|
||||
@@ -35,7 +35,7 @@ pub struct Facts {
|
||||
pub display: Display,
|
||||
/// Text and comments: printed without tags whose markers could be borrowed.
|
||||
pub text_like: bool,
|
||||
/// No children and no end tag: the start tag closes the node (Prettier's `isSelfClosing`).
|
||||
/// No children and no end tag: the start tag closes the node.
|
||||
/// Text-like nodes count too.
|
||||
pub self_closing: bool,
|
||||
/// CSS `white-space: pre*`: `pre`, `textarea`, `listing`, `plaintext`, `xmp`, outside SVG;
|
||||
@@ -160,7 +160,7 @@ impl<'a> Tree<'a> {
|
||||
matches!(self.kind(id), NodeKind::Interpolation(_))
|
||||
}
|
||||
|
||||
/// A text or a CDATA section, which Prettier merges into text (`mergeCdataIntoText`).
|
||||
/// A text or a CDATA section, which print as one text next to each other.
|
||||
pub fn is_text(&self, id: NodeId) -> bool {
|
||||
matches!(self.kind(id), NodeKind::Text(_) | NodeKind::Cdata)
|
||||
}
|
||||
@@ -245,7 +245,7 @@ impl<'a> Tree<'a> {
|
||||
std::iter::successors(self[id].first_child, move |&child| self[child].next)
|
||||
}
|
||||
|
||||
/// Where the content between the tags starts (Prettier's `startSourceSpan.end`).
|
||||
/// Where the content between the tags starts.
|
||||
pub fn content_start(&self, id: NodeId) -> u32 {
|
||||
if self[id].condition.is_some()
|
||||
&& let Some(end) = self.root[id].first_child
|
||||
@@ -260,7 +260,7 @@ impl<'a> Tree<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Where the end tag starts, when there is one (Prettier's `endSourceSpan.start`).
|
||||
/// Where the end tag starts, when there is one.
|
||||
pub fn end_tag_start(&self, id: NodeId) -> Option<u32> {
|
||||
match &self.root[id].kind {
|
||||
NodeKind::Element(el) => el.end_tag.map(|tag| tag.span.start),
|
||||
@@ -276,7 +276,7 @@ impl<'a> Tree<'a> {
|
||||
self.element(id).is_some_and(|el| el.end_tag.is_none()) && !self[id].self_closing
|
||||
}
|
||||
|
||||
/// Where Prettier's `sourceSpan` of the node ends:
|
||||
/// Where the node's own source ends:
|
||||
/// an element without an end tag ends at its start tag, children aside.
|
||||
pub fn source_end(&self, id: NodeId) -> u32 {
|
||||
match &self.root[id].kind {
|
||||
@@ -286,7 +286,7 @@ impl<'a> Tree<'a> {
|
||||
}
|
||||
|
||||
/// Line breaks in `[from, to)`, counted up to 2:
|
||||
/// Prettier compares line numbers, so a gap is on the same line, the next line, or further.
|
||||
/// a gap is on the same line, the next line, or further.
|
||||
pub fn line_breaks(&self, from: u32, to: u32) -> usize {
|
||||
if from >= to {
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user