Skip to content

fix(text): preserve indent inside substituted values in dedent (#6830)#7160

Open
LeSingh1 wants to merge 1 commit into
denoland:mainfrom
LeSingh1:fix/6830-dedent-preserve-substitution-indent
Open

fix(text): preserve indent inside substituted values in dedent (#6830)#7160
LeSingh1 wants to merge 1 commit into
denoland:mainfrom
LeSingh1:fix/6830-dedent-preserve-substitution-indent

Conversation

@LeSingh1
Copy link
Copy Markdown

Fixes #6830 (and the residual cases from #6665).

Problem

dedent computed the common indent using the template joined with a single-char \"x\" placeholder, then stripped that indent from the fully substituted input string. When a multi-line substitution's lines happened to start with whitespace matching the outer template's computed indent, those leading spaces were stripped too — silently breaking the substituted value.

Reproduction from the issue: inner dedents correctly to \" [\\n ...\\n...\\n ]\". Interpolating it back into an outer dedent with 6-space outer indent eats the 6 leading spaces from inner's \" ...\" line, rendering it as \"...\". V1 and V2 in the issue body diverge even though they should be identical.

Fix

Restructure the tagged-template branch to apply indent stripping per literal template part (the entries in input.raw), then interleave substitution values verbatim. The first literal part also gets a start-of-template strip for templates that begin with content (no leading newline). String-input mode is unchanged.

Concretely, instead of building the full substituted string and running replaceAll(^indent/gmu, \"\") on it, the new code runs replaceAll(\\n${indent}/gu, \"\\n\") (plus a once-only ^${indent} for the very first part) on each input.raw[i] and then concatenates the substitution value after each processed part.

Tests

Two new cases in text/unstable_dedent_test.ts:

  • preserves indentation inside multi-line substitution values (#6830) — the exact V1/V2 reproducer from the issue. Both must equal \a\n b\n${inner}``.
  • does not strip indent that originated inside a substituted value — narrower regression: ${\" leading-four-spaces\"} inside a 6-space outer template must keep its 4 leading spaces.
$ deno test --allow-read text/unstable_dedent_test.ts
ok | 13 passed (84 steps) | 0 failed (19ms)

$ deno fmt text/unstable_dedent.ts text/unstable_dedent_test.ts
Checked 2 files

$ deno lint text/unstable_dedent.ts text/unstable_dedent_test.ts && deno check text/unstable_dedent.ts text/unstable_dedent_test.ts
Checked 2 files
Check text/unstable_dedent.ts
Check text/unstable_dedent_test.ts

…and#6830)

`dedent` computed the common indent from the joined template (with a
single-char placeholder for each substitution) and then stripped that
indent from the FULLY substituted string. When a multi-line
substitution's lines happened to start with whitespace matching the
outer template's indent, those leading spaces were stripped too —
breaking the substituted value.

Reproduction from denoland#6830 (and denoland#6665 partially): `inner` is dedented
correctly, but interpolating it back into an outer dedent with
6-space outer indent eats the 6 spaces from `inner`'s
`      ...` line, turning the rendered substitution into `...`.

Restructure the tagged-template branch to apply indent stripping per
literal template part (the entries in `input.raw`), then interleave
substitution values verbatim. The first literal part also gets a
start-of-template strip for templates that begin with content
(no leading newline). String-input mode is unchanged.

Two new tests cover the issue's exact V1/V2 reproducer and a
narrower regression where a substituted value begins with whitespace
that matches the outer indent. Full dedent suite (13 tests / 84 steps)
stays green.
@github-actions github-actions Bot added the text label May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

text/unstable-dedent still gives poor results when interpolating multi-line text into tagged template in certain edge cases

1 participant