com.github.jknack.handlebars.internal.MustacheSpec.java Source code

Java tutorial

Introduction

Here is the source code for com.github.jknack.handlebars.internal.MustacheSpec.java

Source

/**
 * 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.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;

/**
 * Remove space and lines according to the Mustache Spec.
 *
 * @author edgar.espina
 * @since 0.10.0
 */
public class MustacheSpec extends HbsParserBaseListener {

    /**
     * Track if the current line has real text (not spaces).
     */
    private boolean nonSpace = false;

    /**
     * Track if the current line has mustache instruction.
     */
    private Boolean hasTag;

    /**
     * Track the current line.
     */
    protected StringBuilder line = new StringBuilder();

    /**
     * Track the spaces/lines that need to be excluded.
     */
    private List<CommonToken> spaces = new ArrayList<CommonToken>();

    @Override
    public void enterSpaces(final SpacesContext ctx) {
        CommonToken space = (CommonToken) ctx.SPACE().getSymbol();
        line.append(space.getText());
        spaces.add(space);
    }

    @Override
    public void enterNewline(final NewlineContext ctx) {
        CommonToken newline = (CommonToken) ctx.NL().getSymbol();
        spaces.add(newline);
        stripSpaces();
    }

    @Override
    public void exitTemplate(final TemplateContext ctx) {
        stripSpaces();
    }

    /**
     * Move tokens to the hidden channel if necessary.
     */
    private void stripSpaces() {
        boolean hasTag = this.hasTag == null ? false : this.hasTag.booleanValue();
        if (hasTag && !nonSpace) {
            for (CommonToken space : spaces) {
                space.setChannel(Token.HIDDEN_CHANNEL);
            }
        } else {
            spaces.clear();
        }

        this.hasTag = null;
        nonSpace = false;
        line.setLength(0);
    }

    @Override
    public void enterText(final TextContext ctx) {
        nonSpace = true;
    }

    @Override
    public void enterBlock(final BlockContext ctx) {
        hasTag(true);
    }

    @Override
    public void exitBlock(final BlockContext ctx) {
        hasTag(true);
    }

    @Override
    public void enterComment(final CommentContext ctx) {
        hasTag(true);
    }

    @Override
    public void exitPartial(final PartialContext ctx) {
        hasTag(true);
    }

    @Override
    public void enterDelimiters(final DelimitersContext ctx) {
        hasTag(true);
    }

    @Override
    public void enterUnless(final UnlessContext ctx) {
        hasTag(true);
    }

    @Override
    public void exitUnless(final UnlessContext ctx) {
        hasTag(true);
    }

    @Override
    public void enterAmpvar(final AmpvarContext ctx) {
        hasTag(false);
    }

    @Override
    public void enterTvar(final TvarContext ctx) {
        hasTag(false);
    }

    @Override
    public void enterVar(final VarContext ctx) {
        hasTag(false);
    }

    /**
     * Mark the current line with a mustache instruction.
     *
     * @param hasTag True, to indicate there is a mustache instruction.
     */
    private void hasTag(final boolean hasTag) {
        if (this.hasTag != Boolean.FALSE) {
            this.hasTag = hasTag;
        }
    }
}