fix(oxfmt): expand Fill parts in tsx-in-vue (#26427)

Fixes #26398, closes #26399.

---

Our Rust printer knows how to expand `Fill` with `Interned`, but Prettier printer does not.
This commit is contained in:
leaysgur
2026-09-08 01:29:38 +00:00
parent 32d00c55bc
commit 876fbe30f1
2 changed files with 59 additions and 14 deletions
@@ -371,21 +371,32 @@ fn convert_elements(
}
printer.pending_space = false;
}
let key = interned_cache_key(interned);
let id = if let Some(&id) = state.interned_to_ref.get(&key) {
id
} else {
// Reserve the slot index now:
// the recursive `convert_elements` call below may push more refs,
// so `state.refs.len()` would no longer equal this Interned's slot when we go to fill it.
let id = state.refs.len();
state.refs.push(Value::Null);
state.interned_to_ref.insert(key, id);
// `fill` parts must stay a flat `[item, separator, ...]` list,
// but the formatter may wrap all entries in one `Interned` (e.g. JSX children).
// Splice them like the printer does, instead of emitting one opaque `_REF` part.
if matches!(
stack.last().and_then(|entry| entry.start_info.as_ref()),
Some(StartTagInfo::Fill)
) {
let converted = convert_shared_elements(interned, state)?;
state.refs[id] = normalize_array(converted);
id
};
current_children_mut(&mut stack)?.push(json!({ "_REF": id }));
current_children_mut(&mut stack)?.extend(converted);
} else {
let key = interned_cache_key(interned);
let id = if let Some(&id) = state.interned_to_ref.get(&key) {
id
} else {
// Reserve the slot index now:
// the recursive `convert_elements` call below may push more refs,
// so `state.refs.len()` would no longer equal this Interned's slot when we go to fill it.
let id = state.refs.len();
state.refs.push(Value::Null);
state.interned_to_ref.insert(key, id);
let converted = convert_shared_elements(interned, state)?;
state.refs[id] = normalize_array(converted);
id
};
current_children_mut(&mut stack)?.push(json!({ "_REF": id }));
}
printer.line = LineState::Content;
}
FormatElement::BestFitting(best_fitting) => {
+34
View File
@@ -149,6 +149,40 @@ export default {
expect(result.errors).toStrictEqual([]);
});
it('should fill JSX text in <script lang="tsx"> blocks, not all-or-nothing', async () => {
const input = `
<script setup lang="tsx">
const short = (
<div>
<label for="d" class={[c]}>
Please enter the scheduled payment date below
</label>
</div>
);
const long = <div>Please enter the scheduled payment date below aaa bbb ccc ddd eee fff ggg hhh</div>;
</script>
`;
const result = await format("a.vue", input, { printWidth: 80 });
expect(result.code).toBe(`<script setup lang="tsx">
const short = (
<div>
<label for="d" class={[c]}>
Please enter the scheduled payment date below
</label>
</div>
);
const long = (
<div>
Please enter the scheduled payment date below aaa bbb ccc ddd eee fff ggg
hhh
</div>
);
</script>
`);
expect(result.errors).toStrictEqual([]);
});
it('should format generic arrows in <script lang="ts"> blocks', async () => {
const input = `
<script lang="ts">