fix: preserve partial indentation (issue #614)#635
Merged
Conversation
e752970 to
a2feeef
Compare
When a partial invocation ({{> partial}}) is the only non-whitespace
content on a line, the leading whitespace is now captured as an indent
string and prepended to every line of the rendered partial output.
This matches Handlebars.js / Mustache standalone-partial behaviour.
Implementation:
- PartialExpression gains an Indent property
- WhitespaceRemover.ProcessTokens extracts the leading whitespace from
the preceding static token and stores it on a new PartialExpression
before discarding the whitespace from the token stream
- PartialBinder.InvokePartial* renders into a temporary StringWriter
and calls WriteWithIndent to prefix every line with the captured
indent before writing to the real output writer
- Two pre-existing tests updated to reflect the new correct output
(StandalonePartials and TestNestedPartials)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
a2feeef to
b2c1ca1
Compare
… output Templates with \r\n line endings (Windows CRLF source files or explicit \r\n in string literals) now always produce \n in rendered output. Previously WriteWithIndent normalized the captured partial content but the surrounding static template text was written verbatim, producing mixed \r\n/\n output on Windows and breaking tests that expected \n. The root was that normalization happened too late and only in one path. Fix: normalize \r\n → \n once in StaticConverter, the single point where all StaticToken values become StaticExpression nodes. This runs after WhitespaceRemover (which already uses \r?\n in all its regexes) and ensures every static text segment emitted to the writer uses \n regardless of the source file's line endings. Update affected tests to use \n in both template strings and expected values: ViewEngineTests, ReadmeTests, ComplexIntegrationTests, BasicIntegrationTests (split separator), and IssueTests. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This was referenced Jun 20, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #614
Summary
{{> partial}}is the only non-whitespace content on a line, the leading spaces/tabs are now captured as an indentation prefix and prepended to every line of the rendered partial output.Changes
PartialExpression.csIndentpropertyHandlebarsExpression.csPartial()acceptingindentWhitespaceRemover.csPartialExpressionbefore discarding it from the token streamPartialBinder.csStringWriterwhenIndentis set, then callsWriteWithIndentto prefix every line before forwarding to the real writerStaticConverter.cs\r\n→\nfor all static template text at compile time, making output platform-independentWhitespaceTests.StandalonePartialsIssueTests.TestNestedPartials@partial-blockIssues/Issue614Tests.cs\r\n→\nin template strings and expected values to match the new normalised outputRoot cause of the Windows test failures (third attempt — solved)
The first two attempts both tried to normalise
\r\nat render time in a specific call path (WriteWithIndent). That only covered the partial's own captured output; the surrounding template's static text was still written verbatim, producing mixed\r\n/\noutput on Windows/macOS (CRLF source files).The fix is to normalise once at compile time in
StaticConverter— the single point where allStaticTokenvalues becomeStaticExpressionnodes.WhitespaceRemover(which runs earlier) already uses\r?\nin all its regexes and is unaffected.WriteWithIndentkeeps its own normalisation to handle\r\nin data values (dynamic content from bindings), which are outside the compile-time path.Test plan
dotnet test source/Handlebars.Test/Handlebars.Test.csproj— all 1796 tests pass (6 new)source/Handlebars.Test/Issues/Issue614Tests.csconfirm the spec example (" {{> p}}"+"line1\nline2"→" line1\n line2")PartialWithCrLfLineEndingsNormalisedToLfconfirms that\r\npartial source → normalised\noutput🤖 Generated with Claude Code