/********************************************************************** * Copyright (c) 2014 HubSpot Inc. * * 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.hubspot.jinjava.lib.tag; import java.io.IOException; import com.hubspot.jinjava.doc.annotations.JinjavaDoc; import com.hubspot.jinjava.doc.annotations.JinjavaParam; import com.hubspot.jinjava.doc.annotations.JinjavaSnippet; import com.hubspot.jinjava.interpret.InterpretException; import com.hubspot.jinjava.interpret.JinjavaInterpreter; import com.hubspot.jinjava.interpret.TemplateSyntaxException; import com.hubspot.jinjava.tree.Node; import com.hubspot.jinjava.tree.TagNode; import com.hubspot.jinjava.util.HelperStringTokenizer; @JinjavaDoc( value = "Template inheritance allows you to build a base “skeleton” template that contains all the " + "common elements of your site and defines blocks that child templates can override.", params = { @JinjavaParam(value = "path", desc = "Design Manager file path to parent template") }, snippets = { @JinjavaSnippet( desc = "This template, which we’ll call base.html, defines a simple HTML skeleton document that you might " + "use for a simple two-column page. It’s the job of “child” templates to fill the empty blocks with content.\n\n" + "In this example, the {% block %} tags define four blocks that child templates can fill in. All the block tag " + "does is tell the template engine that a child template may override those placeholders in the template.", code = "<!DOCTYPE html>\n" + "<html lang=\"en\">\n" + "<head>\n" + " {% block head %}\n" + " <link rel=\"stylesheet\" href=\"style.css\" />\n" + " <title>{% block title %}{% endblock %} - My Webpage</title>\n" + " {% endblock %}\n" + "</head>\n" + "<body>\n" + " <div id=\"content\">{% block content %}{% endblock %}</div>\n" + " <div id=\"footer\">\n" + " {% block footer %}\n" + " © Copyright 2008 by <a href=\"http://domain.invalid/\">you</a>.\n" + " {% endblock %}\n" + " </div>\n" + "</body>\n" + "</html>"), @JinjavaSnippet( desc = "The {% extends %} tag is the key here. It tells the template engine that this template “extends” another template. " + "When the template system evaluates this template, it first locates the parent. The extends tag should be the first " + "tag in the template. Everything before it is printed out normally and may cause confusion.", code = "{% extends \"custom/page/web_page_basic/my_template.html\" %}\n" + "{% block title %}Index{% endblock %}\n" + "{% block head %}\n" + " {{ super() }}\n" + " <style type=\"text/css\">\n" + " .important { color: #336699; }\n" + " </style>\n" + "{% endblock %}\n" + "{% block content %}\n" + " <h1>Index</h1>\n" + " <p class=\"important\">\n" + " Welcome to my awesome homepage.\n" + " </p>\n" + "{% endblock %}") }) public class ExtendsTag implements Tag { private static final long serialVersionUID = 4692863362280761393L; @Override public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) { HelperStringTokenizer tokenizer = new HelperStringTokenizer(tagNode.getHelpers()); if (!tokenizer.hasNext()) { throw new TemplateSyntaxException(tagNode.getMaster().getImage(), "Tag 'extends' expects template path", tagNode.getLineNumber()); } String path = interpreter.resolveString(tokenizer.next(), tagNode.getLineNumber()); interpreter.getContext().getExtendPathStack().push(path, tagNode.getLineNumber()); try { String template = interpreter.getResource(path); Node node = interpreter.parse(template); interpreter.getContext().addDependency("coded_files", path); interpreter.addExtendParentRoot(node); return ""; } catch (IOException e) { throw new InterpretException(e.getMessage(), e, tagNode.getLineNumber()); } } @Override public String getEndTagName() { return null; } @Override public String getName() { return "extends"; } }