Skip to content

Commit b5870fa

Browse files
committed
Whitespace is discarded in token stream
- fix #1168 - keep text as it is
1 parent 7cac15f commit b5870fa

15 files changed

Lines changed: 323 additions & 113 deletions

File tree

handlebars/src/main/java/com/github/jknack/handlebars/internal/Block.java

Lines changed: 6 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ class Block extends HelperResolver {
8383
/** True, if this block has decorators. */
8484
private boolean decorate;
8585

86+
private final String source;
87+
8688
/**
8789
* Creates a new {@link Block}.
8890
*
@@ -101,7 +103,8 @@ class Block extends HelperResolver {
101103
final String type,
102104
final List<Param> params,
103105
final Map<String, Param> hash,
104-
final List<String> blockParams) {
106+
final List<String> blockParams,
107+
final String source) {
105108
super(handlebars);
106109
this.name = notNull(name, "The name is required.");
107110
this.path = PathCompiler.compile(name, handlebars.parentScopeResolution());
@@ -111,6 +114,7 @@ class Block extends HelperResolver {
111114
hash(hash);
112115
this.blockParams = blockParams;
113116
this.tagType = TagType.SECTION;
117+
this.source = source;
114118
postInit();
115119
}
116120

@@ -298,56 +302,7 @@ public Template body() {
298302

299303
@Override
300304
public String text() {
301-
return text(true, true);
302-
}
303-
304-
/**
305-
* Build a text version of this block.
306-
*
307-
* @param complete True if the inner block should be added.
308-
* @param close If we must close the block.
309-
* @return A string version of this block.
310-
*/
311-
private String text(final boolean complete, final boolean close) {
312-
StringBuilder buffer = new StringBuilder();
313-
buffer.append(startDelimiter).append(type).append(name);
314-
String params = paramsToString(this.params);
315-
if (params.length() > 0) {
316-
buffer.append(" ").append(params);
317-
}
318-
String hash = hashToString();
319-
if (hash.length() > 0) {
320-
buffer.append(" ").append(hash);
321-
}
322-
if (blockParams.size() > 0) {
323-
buffer.append(" as |").append(paramsToString(this.blockParams)).append("|");
324-
}
325-
buffer.append(endDelimiter);
326-
if (complete) {
327-
buffer.append(body == null ? "" : body.text());
328-
if (inverse != EMPTY) {
329-
if (inverse instanceof Block) {
330-
String elseif = ((Block) inverse).text(true, false);
331-
buffer.append(elseif);
332-
} else {
333-
buffer
334-
.append(startDelimiter)
335-
.append(inverseLabel)
336-
.append(endDelimiter)
337-
.append(inverse.text());
338-
}
339-
}
340-
} else {
341-
buffer.append("\n...\n");
342-
}
343-
if (close) {
344-
buffer.append(startDelimiter);
345-
if (type.equals("{{")) {
346-
buffer.append("{{");
347-
}
348-
buffer.append('/').append(name).append(endDelimiter);
349-
}
350-
return buffer.toString();
305+
return source;
351306
}
352307

353308
/**

handlebars/src/main/java/com/github/jknack/handlebars/internal/BlockDecorator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ public BlockDecorator(
4949
final List<Param> params,
5050
final Map<String, Param> hash,
5151
final List<String> blockParams,
52-
final boolean root) {
53-
super(handlebars, name, inverted, "#*", params, hash, blockParams);
52+
final boolean root,
53+
final String source) {
54+
super(handlebars, name, inverted, "#*", params, hash, blockParams, source);
5455
this.root = root;
5556
this.tagType = TagType.START_SECTION;
5657
}

handlebars/src/main/java/com/github/jknack/handlebars/internal/Partial.java

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class Partial extends HelperResolver {
7070
/** Used to clear context after partial block got executed. See #655. */
7171
private boolean decorate;
7272

73+
private String source;
74+
7375
/**
7476
* Creates a new {@link Partial}.
7577
*
@@ -82,13 +84,15 @@ class Partial extends HelperResolver {
8284
final Handlebars handlebars,
8385
final Template path,
8486
final String context,
85-
final Map<String, Param> hash) {
87+
final Map<String, Param> hash,
88+
final String source) {
8689
super(handlebars);
8790
this.path = notNull(path, "The path is required.");
8891
this.context = context;
8992
this.scontext = context == null ? "this" : context;
9093
this.hash(hash);
9194
this.loader = handlebars.getLoader();
95+
this.source = source;
9296
}
9397

9498
@Override
@@ -340,32 +344,7 @@ private String partialInput(final String input, final String indent) {
340344

341345
@Override
342346
public String text() {
343-
String path = this.path.text();
344-
StringBuilder buffer = new StringBuilder(startDelimiter).append('>').append(path);
345-
346-
if (context != null) {
347-
buffer.append(' ').append(context);
348-
}
349-
String params = paramsToString(this.params);
350-
if (params.length() > 0) {
351-
buffer.append(" ").append(params);
352-
}
353-
String hash = hashToString();
354-
if (hash.length() > 0) {
355-
buffer.append(" ").append(hash);
356-
}
357-
358-
buffer.append(endDelimiter);
359-
360-
if (this.partial != null) {
361-
buffer
362-
.append(this.partial.text())
363-
.append(startDelimiter, 0, startDelimiter.length() - 1)
364-
.append("/")
365-
.append(path)
366-
.append(endDelimiter);
367-
}
368-
return buffer.toString();
347+
return source;
369348
}
370349

371350
/**

handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateBuilder.java

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
import java.util.Map;
1717

1818
import org.antlr.v4.runtime.CommonToken;
19+
import org.antlr.v4.runtime.ParserRuleContext;
1920
import org.antlr.v4.runtime.Token;
21+
import org.antlr.v4.runtime.misc.Interval;
2022
import org.antlr.v4.runtime.tree.ParseTree;
2123
import org.antlr.v4.runtime.tree.TerminalNode;
2224
import org.apache.commons.lang3.StringUtils;
@@ -154,7 +156,8 @@ public Template visitRawBlock(final RawBlockContext ctx) {
154156
"{{",
155157
params(sexpr.param()),
156158
hash(sexpr.hash()),
157-
Collections.emptyList());
159+
Collections.emptyList(),
160+
source(ctx));
158161

159162
if (block.paramSize > 0) {
160163
paramStack.addLast(block.params.get(0).toString());
@@ -183,6 +186,13 @@ public Template visitRawBlock(final RawBlockContext ctx) {
183186
return block;
184187
}
185188

189+
private String source(ParserRuleContext ctx) {
190+
var start = ctx.getStart();
191+
var stop = ctx.getStop();
192+
var tokens = start.getInputStream();
193+
return tokens.getText(Interval.of(start.getStartIndex(), stop.getStopIndex()));
194+
}
195+
186196
@Override
187197
public Template visitBlock(final BlockContext ctx) {
188198
level += 1;
@@ -211,7 +221,8 @@ public Template visitBlock(final BlockContext ctx) {
211221
params(sexpr.param()),
212222
hash(sexpr.hash()),
213223
blockParams(ctx.blockParams()),
214-
level == 1);
224+
level == 1,
225+
source(ctx));
215226
} else {
216227
block =
217228
new Block(
@@ -221,7 +232,8 @@ public Template visitBlock(final BlockContext ctx) {
221232
"#",
222233
params(sexpr.param()),
223234
hash(sexpr.hash()),
224-
blockParams(ctx.blockParams()));
235+
blockParams(ctx.blockParams()),
236+
source(ctx));
225237
}
226238
if (block.paramSize > 0) {
227239
paramStack.addLast(block.params.get(0).toString());
@@ -260,7 +272,8 @@ public Template visitBlock(final BlockContext ctx) {
260272
type,
261273
params(elseexpr.param()),
262274
hash(elseexpr.hash()),
263-
blockParams(elseStmtChainContext.blockParams()));
275+
blockParams(elseStmtChainContext.blockParams()),
276+
source(elseStmtChainContext));
264277
elseblock.filename(source.filename());
265278
elseblock.position(elsenameStart.getLine(), elsenameStart.getCharPositionInLine());
266279
elseblock.startDelimiter(startDelim);
@@ -322,7 +335,8 @@ public Template visitUnless(final UnlessContext ctx) {
322335
"^",
323336
Collections.emptyList(),
324337
Collections.emptyMap(),
325-
blockParams(ctx.blockParams()));
338+
blockParams(ctx.blockParams()),
339+
source(ctx));
326340
block.filename(source.filename());
327341
block.position(nameStart.getLine(), nameStart.getCharPositionInLine());
328342
String startDelim = ctx.start.getText();
@@ -343,6 +357,7 @@ public Template visitVar(final VarContext ctx) {
343357
hasTag(false);
344358
SexprContext sexpr = ctx.sexpr();
345359
return newVar(
360+
ctx,
346361
sexpr.QID().getSymbol(),
347362
TagType.VAR,
348363
params(sexpr.param()),
@@ -366,6 +381,7 @@ public Template visitTvar(final TvarContext ctx) {
366381
hasTag(false);
367382
SexprContext sexpr = ctx.sexpr();
368383
return newVar(
384+
ctx,
369385
sexpr.QID().getSymbol(),
370386
TagType.TRIPLE_VAR,
371387
params(sexpr.param()),
@@ -380,6 +396,7 @@ public Template visitAmpvar(final AmpvarContext ctx) {
380396
hasTag(false);
381397
SexprContext sexpr = ctx.sexpr();
382398
return newVar(
399+
ctx,
383400
sexpr.QID().getSymbol(),
384401
TagType.AMP_VAR,
385402
params(sexpr.param()),
@@ -402,6 +419,7 @@ public Template visitAmpvar(final AmpvarContext ctx) {
402419
* @return A new {@link Variable}.
403420
*/
404421
private Variable newVar(
422+
final ParserRuleContext ctx,
405423
final Token name,
406424
final TagType varType,
407425
final List<Param> params,
@@ -467,8 +485,9 @@ private Variable newVar(
467485
}
468486
Variable var =
469487
decorator
470-
? new VarDecorator(handlebars, varName, TagType.STAR_VAR, params, hash, level == 0)
471-
: new Variable(handlebars, varName, varType, params, hash);
488+
? new VarDecorator(
489+
handlebars, varName, TagType.STAR_VAR, params, hash, level == 0, source(ctx))
490+
: new Variable(handlebars, varName, varType, params, hash, source(ctx));
472491
var.startDelimiter(startDelimiter)
473492
.endDelimiter(endDelimiter)
474493
.filename(source.filename())
@@ -541,6 +560,7 @@ public Object visitSubParamExpr(final SubParamExprContext ctx) {
541560
SexprContext sexpr = ctx.sexpr();
542561
return new VarParam(
543562
newVar(
563+
ctx,
544564
sexpr.QID().getSymbol(),
545565
TagType.SUB_EXPRESSION,
546566
params(sexpr.param()),
@@ -641,7 +661,7 @@ public Template visitPartial(final PartialContext ctx) {
641661

642662
String startDelim = ctx.start.getText();
643663
Template partial =
644-
new Partial(handlebars, info.path, info.context, info.hash)
664+
new Partial(handlebars, info.path, info.context, info.hash, source(ctx))
645665
.startDelimiter(startDelim.substring(0, startDelim.length() - 1))
646666
.endDelimiter(ctx.stop.getText())
647667
.indent(indent)
@@ -669,7 +689,7 @@ public Object visitPartialBlock(final PartialBlockContext ctx) {
669689

670690
String startDelim = ctx.start.getText();
671691
Template partial =
672-
new Partial(handlebars, info.path, info.context, info.hash)
692+
new Partial(handlebars, info.path, info.context, info.hash, source(ctx))
673693
.setDecorate(true)
674694
.setPartial(fn)
675695
.startDelimiter(startDelim.substring(0, startDelim.length() - 1))
@@ -725,6 +745,7 @@ public PartialInfo visitDynamicPath(final DynamicPathContext ctx) {
725745
TerminalNode qid = sexpr.QID();
726746
Template expression =
727747
newVar(
748+
ctx,
728749
qid.getSymbol(),
729750
TagType.SUB_EXPRESSION,
730751
params(sexpr.param()),

handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateList.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ public final boolean decorate() {
8989

9090
@Override
9191
public String text() {
92-
StringBuilder buffer = new StringBuilder();
93-
for (Template node : nodes) {
92+
var buffer = new StringBuilder();
93+
for (var node : nodes) {
9494
buffer.append(node.text());
9595
}
9696
return buffer.toString();

handlebars/src/main/java/com/github/jknack/handlebars/internal/VarDecorator.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ public VarDecorator(
4848
final TagType type,
4949
final List<Param> params,
5050
final Map<String, Param> hash,
51-
final boolean root) {
52-
super(handlebars, name, type, params, hash);
51+
final boolean root,
52+
final String source) {
53+
super(handlebars, name, type, params, hash, source);
5354
this.root = root;
5455
}
5556

handlebars/src/main/java/com/github/jknack/handlebars/internal/Variable.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class Variable extends HelperResolver {
7070
/** Empty var. */
7171
private Template emptyVar;
7272

73+
private final String source;
74+
7375
/**
7476
* Creates a new {@link Variable}.
7577
*
@@ -84,7 +86,8 @@ class Variable extends HelperResolver {
8486
final String name,
8587
final TagType type,
8688
final List<Param> params,
87-
final Map<String, Param> hash) {
89+
final Map<String, Param> hash,
90+
final String source) {
8891
super(handlebars);
8992
this.name = name.trim();
9093
this.path = PathCompiler.compile(name, handlebars.parentScopeResolution());
@@ -95,6 +98,7 @@ class Variable extends HelperResolver {
9598
this.escapingStrategy =
9699
type == TagType.VAR ? handlebars.getEscapingStrategy() : EscapingStrategy.NOOP;
97100
this.formatter = handlebars.getFormatter();
101+
this.source = source;
98102
postInit();
99103
}
100104

@@ -225,17 +229,7 @@ protected CharSequence formatAndEscape(final Object value, final Formatter.Chain
225229

226230
@Override
227231
public String text() {
228-
StringBuilder buffer = new StringBuilder();
229-
buffer.append(startDelimiter).append(suffix()).append(name);
230-
String params = paramsToString(this.params);
231-
if (params.length() > 0) {
232-
buffer.append(" ").append(params);
233-
}
234-
String hash = hashToString();
235-
if (hash.length() > 0) {
236-
buffer.append(" ").append(hash);
237-
}
238-
return buffer.append(endDelimiter).toString();
232+
return source;
239233
}
240234

241235
/**

handlebars/src/test/java/com/github/jknack/handlebars/InlinePartialsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public void shouldDefineInlinePartialsInPartialBlockCall() throws IOException {
9595
@Test
9696
public void inlinePartialText() throws IOException {
9797
assertEquals(
98-
"{{#*inline \"myPartial\"}}success{{/inline}}{{>myPartial}}",
98+
"{{#*inline \"myPartial\"}}success{{/inline}}{{> myPartial}}",
9999
compile("{{#*inline \"myPartial\"}}success{{/inline}}{{> myPartial}}").text());
100100
}
101101
}

handlebars/src/test/java/com/github/jknack/handlebars/PartialBlockTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ public class PartialBlockTest extends AbstractTest {
1616
@Test
1717
public void text() throws IOException {
1818
assertEquals(
19-
"{{#>dude}}{{#*inline \"myPartial\"}}success{{/inline}}{{/dude}}",
19+
"{{#> dude}}{{#*inline \"myPartial\"}}success{{/inline}}{{/dude}}",
2020
compile("{{#> dude}}{{#*inline \"myPartial\"}}success{{/inline}}{{/dude}}").text());
2121

22-
assertEquals("{{#>dude}}success{{/dude}}", compile("{{#> dude}}success{{/dude}}").text());
22+
assertEquals("{{#> dude}}success{{/dude}}", compile("{{#> dude}}success{{/dude}}").text());
2323
}
2424

2525
@Test

0 commit comments

Comments
 (0)