fix(fmt): delegate component expression formatting to markup_fmt#29763
fix(fmt): delegate component expression formatting to markup_fmt#29763bartlomieju merged 18 commits intodenoland:mainfrom
Conversation
new function `format_expressions_in_text` handles JS expressions in text, allowing for temporary placeholders during formatting of component files. The `format_html` function preprocesses expressions before markup parsing and restores them after formatting.
…new formatting test for Vue - new `badly_formatted.vue` and its fixed counterpart - updated existing Svelte test file to include dynamic style
| "svelte" | "astro" => (r"\{([^{}]+)\}", "{", "}"), | ||
| "vue" => (r"\{\{([^{}]+)\}\}", "{{", "}}"), |
There was a problem hiding this comment.
This seems very error prone to do (ex. it would format within comments). Probably it should be handled by markup_fmt instead and it can call out to format these expressions with the appropriate formatter.
There was a problem hiding this comment.
@dsherret thanks for the earlier feedback! sorry for the long radio silence, just remembered i've been meaning to finish this 😅
i reworked this PR to address your concern about the regex-based preprocessing:
- dropped local expression placeholder pipeline in
cli/tools/fmt.rs:- deleted
format_expressions_in_text(...) - removed preprocess/restore logic around
format_html(...)
- deleted
format_html(...)now passes the original text directly tomarkup_fmt(single source of truth for parsing/formatting), instead of trying to rewrite expressions in Deno first- Upgraded
markup_fmtfrom0.19.1to0.22.0
ready for another review
- remove local placeholder preprocessing in html formatter - rely on markup_fmt parsing for interpolated style expressions - bump markup_fmt to 0.22.0 and update config compatibility
- revert the Svelte style interpolation fixture in fmt testdata to the upstream-supported form - keep the change minimal to unblock flaky integration::fmt::fmt_test failures on CI
- bump markup_fmt to 0.26.0 and update lockfile - add required markup_fmt language config fields in fmt options - keep Svelte style interpolation coverage in existing fmt fixtures
- skip TypeScript formatting for markup_fmt jinja pseudo-extensions - avoid invalid JS parse errors for Nunjucks/Jinja filters and block statements - keep markup_fmt 0.26 upgrade while restoring njk spec and integration behavior
- align badly_formatted_fixed.vue with current formatter spacing output - fix integration::fmt::fmt_test expectation mismatch on CI
|
@bartlomieju the "ensure CI success" error looks like a false positive. anything i need to do here? |
|
Review from Claude. No 2 and 4 look concerning :( 1. PR title/description is misleadingThe title says "Add expression formatting in CSS strings for components" and the description mentions a 2. Svelte test file loses trailing newline-</style>
+</style>
\ No newline at end of file
3. New config fields use hardcoded defaults without documentationvue_component_case: config::VueComponentCase::Ignore,
angular_next_control_flow_same_line: true,These are set in two places ( 4. Vue formatted output swaps quote stylesThe formatted Vue output changes <!-- input -->
:style="{ width: a + b + 'px' }"
<!-- output -->
:style='{ width: a + b + "px" }'This is technically valid HTML but may surprise users who consistently use double quotes for attributes. This behavior comes from 5. Jinja handler matches on string prefix — fragileext if ext.starts_with("markup-fmt-jinja-") => {
Ok(Cow::from(text))
}This relies on |
Wire vueComponentCase and angularNextControlFlowSameLine through fmt config and formatter resolution so markup_fmt behavior is explicit and user-configurable, while keeping fixture behavior stable and documenting jinja callback handling.
|
@bartlomieju thanks a lot for the thorough review, all good points!
|
Align import ordering and match arm formatting with tools/format.js output to satisfy CI formatting checks.
Include the new fmt options in the unknown-field expected list so malformed fmt config specs match current serde error output.
|
would be great to get this merged! i'm currently blocked from upgrading beyond |
…e config duplication - Extract `embedded_markup_language_options()` that builds the shared `LanguageOptions` with vue/angular config resolution - `format_embedded_html` now takes a `&LanguageOptions` instead of individual vue_component_case + angular_next_control_flow_same_line params - `get_resolved_markup_fmt_config` uses struct update syntax (`..embedded_markup_language_options()`) to override only the fields that differ for top-level component files - Net reduction of ~30 lines of duplicated struct field assignments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
I will land #32949 first, to not confuse crate upgrade with additional changes |
- Take upstream's markup_fmt 0.27.0 and malva 0.15.2 versions - Keep PR's embedded_markup_language_options dedup for format_embedded_html - Keep PR's config-resolved vue_component_case and angular_next_control_flow_same_line - Take upstream's Jinja passthrough comment referencing v0.27.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
closes #26999
This PR now solves component expression formatting by delegating parsing/formatting to
markup_fmtinstead of using Deno-side regex placeholder preprocessing.What changed
markup_fmtand aligned Deno formatter config with the newer APIformat_expressions_in_text(...)preprocessing/restore pipelinemarkup_fmtas the single parser/formatter source of truthWhy this approach
Earlier review feedback called out regex preprocessing as fragile (for example formatting inside comments). This version avoids that class of issues by relying on
markup_fmt's native parse tree and language-aware formatting behavior.