Skip to content

fix: preserve multiline scalar content and formatting idempotence - #332

Open
TyceHerrman wants to merge 2 commits into
google:mainfrom
TyceHerrman:fix/scalar-content-preservation
Open

TyceHerrman wants to merge 2 commits into
google:mainfrom
TyceHerrman:fix/scalar-content-preservation

Conversation

@TyceHerrman

@TyceHerrman TyceHerrman commented Oct 19, 2026 •

Copy link
Copy Markdown

Retaining blank lines can insert #magic___^_^___line into multiline scalar values, and trailing whitespace can force block scalars into quoted output. Folded scalars with more-indented lines can also gain newlines on successive formatting passes.

This change protects scalar content using scanner-derived ranges, preserves structural blank separators and unlimited line scanning, retains block style with trailing whitespace, and corrects folded-scalar look-ahead.

Fixes #86.
Fixes #313.
Related: #280 (already closed).

Commit organization and provenance

  1. Preserve scalar content when retaining line breaks: scanner ranges, block style, blank separators and unlimited line scanning, with regression tests. Adapts Michael Tingley's fork, excluding additive indentation and its output-scan shortcut. The separator and line-size regressions found during reevaluation are folded into this commit.
  2. Preserve folded scalar values during emission: the core correction from @ultimateanu's existing Fix newline bug on folded scalar #322, without unrelated cleanup, plus value/idempotence tests and folded keep-chomping separator coverage.

This PR overlaps #322 and does not claim its correction as new work. Both sources are credited in the commit messages. Google's CLA check passes for the submitted commits; the original sources' contributors' CLA status has not been independently verified.

Validation

The revised tree passes on cloud Linux with Go 1.25.1:

  • make test, make vet, make integrationtest, and make addlicense_check.
  • New regressions fail on the previous PR head and pass here: blank separators after block scalars, LF/CRLF, both retention modes, and lines exceeding 10 MiB.
  • 396/396 external YAML 1.2 value-preservation/idempotence cases, using ruamel.yaml as an independent parser.
  • 384/384 nh file/configuration comparisons: eight YAML files across 48 configurations, preserving values and producing stable second passes.
  • Actual formatting/lint/second-pass/Deno checks on disposable nh worktrees. The closest configuration changes only one document-start marker; all original blank separators remain. Normal-folding/80-column configuration also passes preservation and compatibility checks.

The first commit passes the full Go test suite independently. Earlier Go 1.24.8/1.27.1 results apply to the previous revision; this revised tree was tested with Go 1.25.1. External matrices are broader than the committed focused tests. Intentional trailing whitespace in fixtures exercises the bug.

Existing limitations outside this change remain: marker-prefix comments can collide with the placeholder, empty YAML documents can be lost, and %YAML 1.2 directives are rejected. These inputs do not occur in the tested nh corpus. Windows, macOS, and Nix integration were not tested.

AI disclosure: Codex extracted, adjusted, validated these changes and prepared this PR in an isolated cloud environment. Results come from that execution, not an independent manual reproduction.

Protect multiline scalar content using scanner-derived ranges and preserve block
style for trailing whitespace. Track the end of content separately from trailing
breaks discarded by block chomping, retaining structural blank separators without
changing scalar values. Use the existing unlimited line scanner in both passes.

Derived from Michael Tingley's yamlfmt fork at
3e76013, including 5a4c612, 70c137d
and 3e76013. Exclude additive indentation and the output-scan shortcut.

Add regressions for literal sentinel text, scalar separators, LF/CRLF, both
retention modes, and lines beyond 10 MiB. The tests expose both regressions on
the previous PR head. Full Go tests pass at this commit on Go 1.25.1.

Related: google#86 and google#280.
AI assistance: Codex extracted, adjusted and validated this patch in cloud Linux.
Start folded-scalar look-ahead at the current byte offset and bound-check it.
Take the core correction from ultimateanu's google#322 without its
unrelated cleanup. Add decoded-value and idempotence regression coverage across
retention modes, folded scanning settings and width limits. Extend separator
tests to folded keep-chomping styles, which depend on this correction.

The combined patch passes 396 independent YAML 1.2 preservation cases, 384 nh
file/configuration cases, full tests, vet, CLI integration and license checks
on Go 1.25.1. The closest nh configuration changes only one document marker.

Source: google#322
Related: google#86 and google#313.
AI assistance: Codex integrated and validated the patch in cloud Linux.
@TyceHerrman
TyceHerrman force-pushed the fix/scalar-content-preservation branch from 81f75e1 to 7228b20 Compare October 20, 2026 02:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-deterministic output for indented multiline strings Folded block scalars with whitespace at the end causes problems

1 participant