com.github.jknack.handlebars.internal.WhiteSpaceControl Maven / Gradle / Ivy
/**
* Copyright (c) 2012-2013 Edgar Espina
*
* This file is part of Handlebars.java.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.jknack.handlebars.internal;
import java.util.ArrayList;
import java.util.List;
import org.antlr.v4.runtime.CommonToken;
import org.antlr.v4.runtime.Token;
import com.github.jknack.handlebars.internal.HbsParser.AmpvarContext;
import com.github.jknack.handlebars.internal.HbsParser.BlockContext;
import com.github.jknack.handlebars.internal.HbsParser.CommentContext;
import com.github.jknack.handlebars.internal.HbsParser.DelimitersContext;
import com.github.jknack.handlebars.internal.HbsParser.ElseBlockContext;
import com.github.jknack.handlebars.internal.HbsParser.NewlineContext;
import com.github.jknack.handlebars.internal.HbsParser.PartialContext;
import com.github.jknack.handlebars.internal.HbsParser.SpacesContext;
import com.github.jknack.handlebars.internal.HbsParser.TemplateContext;
import com.github.jknack.handlebars.internal.HbsParser.TextContext;
import com.github.jknack.handlebars.internal.HbsParser.TvarContext;
import com.github.jknack.handlebars.internal.HbsParser.UnlessContext;
import com.github.jknack.handlebars.internal.HbsParser.VarContext;
/**
* Implementation of white-space control. It trims output on left/right of mustache expressions or
* text.
*
* @author edgar.espina
* @since 0.10.0
*/
public class WhiteSpaceControl extends HbsParserBaseListener {
/**
* Track the spaces/lines that need to be excluded.
*/
private List spaces = new ArrayList();
/** Greater than zero, if a trim-right operation is required. */
private int pending = 0;
@Override
public void enterSpaces(final SpacesContext ctx) {
CommonToken space = (CommonToken) ctx.SPACE().getSymbol();
spaces.add(space);
}
@Override
public void enterNewline(final NewlineContext ctx) {
CommonToken newline = (CommonToken) ctx.NL().getSymbol();
spaces.add(newline);
}
@Override
public void exitTemplate(final TemplateContext ctx) {
trimRight();
}
/** Trim-left operation. */
private void trimLeft() {
hideSpaces();
}
/** Move space tokens to the hidden channel. */
private void hideSpaces() {
for (CommonToken space : spaces) {
space.setChannel(Token.HIDDEN_CHANNEL);
}
}
/** Trim-right, if ONLY if pending > 0. */
private void trimRight() {
if (pending > 0) {
hideSpaces();
pending -= 1;
}
}
@Override
public void enterText(final TextContext ctx) {
trim(ctx.start, ctx.stop);
}
@Override
public void enterBlock(final BlockContext ctx) {
trim(ctx.start, ctx.END(0).getSymbol());
}
@Override
public void enterElseBlock(final ElseBlockContext ctx) {
trim(ctx.start, ctx.END().getSymbol());
}
@Override
public void exitBlock(final BlockContext ctx) {
trim(ctx.END_BLOCK().getSymbol(), ctx.END(1).getSymbol());
}
@Override
public void enterComment(final CommentContext ctx) {
trim(ctx.start, ctx.stop);
}
@Override
public void enterPartial(final PartialContext ctx) {
trim(ctx.start, ctx.stop);
}
@Override
public void enterDelimiters(final DelimitersContext ctx) {
trim(ctx.start, ctx.stop);
}
@Override
public void enterUnless(final UnlessContext ctx) {
trim(ctx.start, ctx.END().get(0).getSymbol());
}
@Override
public void enterAmpvar(final AmpvarContext ctx) {
trim(ctx.start, ctx.stop);
}
@Override
public void enterTvar(final TvarContext ctx) {
trim(ctx.start, ctx.stop);
}
@Override
public void enterVar(final VarContext ctx) {
trim(ctx.start, ctx.stop);
}
/**
* Trim on left/right is required.
*
* @param startToken The start token.
* @param endToken The end token.
*/
private void trim(final Token startToken, final Token endToken) {
trimRight();
String start = text(startToken);
if (start.indexOf("~") > 0) {
trimLeft();
}
String end = text(endToken);
if (end.indexOf("~") == 0) {
pending += 1;
}
// clear tokens
spaces.clear();
}
/**
* @param token The candidate token.
* @return Text of the candidate token.
*/
private String text(final Token token) {
return token.getText();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy