From 0d1d29a5597ad04a1bfcf633d026c428551c732f Mon Sep 17 00:00:00 2001 From: Jonathan Bullock Date: Tue, 5 Feb 2019 23:53:05 +0000 Subject: [PATCH 1/2] Fixes #246 --- build.gradle | 3 +- jbake-core/build.gradle | 1 + .../jbake/template/PebbleTemplateEngine.java | 79 +++++++++++++++++++ ...rg.jbake.parser.TemplateEngines.properties | 2 +- .../PebbleTemplateEngineRenderingTest.java | 36 +++++++++ .../fixture/pebbleTemplates/archive.pebble | 29 +++++++ .../fixture/pebbleTemplates/base.pebble | 54 +++++++++++++ .../fixture/pebbleTemplates/feed.pebble | 25 ++++++ .../fixture/pebbleTemplates/footer.pebble | 5 ++ .../fixture/pebbleTemplates/header.pebble | 79 +++++++++++++++++++ .../fixture/pebbleTemplates/index.pebble | 18 +++++ .../fixture/pebbleTemplates/menu.pebble | 33 ++++++++ .../fixture/pebbleTemplates/page.pebble | 18 +++++ .../fixture/pebbleTemplates/post.pebble | 18 +++++ .../fixture/pebbleTemplates/sitemap.pebble | 9 +++ .../fixture/pebbleTemplates/tags-index.pebble | 15 ++++ .../fixture/pebbleTemplates/tags.pebble | 26 ++++++ 17 files changed, 448 insertions(+), 2 deletions(-) create mode 100644 jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java create mode 100644 jbake-core/src/test/java/org/jbake/app/template/PebbleTemplateEngineRenderingTest.java create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/archive.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/base.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/feed.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/footer.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/header.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/index.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/menu.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/page.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/post.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/sitemap.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/tags-index.pebble create mode 100644 jbake-core/src/test/resources/fixture/pebbleTemplates/tags.pebble diff --git a/build.gradle b/build.gradle index c9119b96a..dba86959a 100644 --- a/build.gradle +++ b/build.gradle @@ -34,6 +34,7 @@ ext { jade4jVersion = '1.2.7' mockitoVersion = '2.23.4' jsoupVersion = '1.11.3' + pebbleVersion = '3.0.7' isTravis = (System.getenv("TRAVIS") == "true") isTravisPullRequest = (System.getenv("TRAVIS_PULL_REQUEST")) != "false" @@ -119,7 +120,7 @@ subprojects { compile "org.slf4j:jul-to-slf4j:$slf4jVersion" compile "ch.qos.logback:logback-classic:$logbackVersion", optional compile "ch.qos.logback:logback-core:$logbackVersion", optional - + testCompile("org.junit.jupiter:junit-jupiter-api:$junit5Version") testRuntime("org.junit.jupiter:junit-jupiter-engine:$junit5Version") testCompile("org.junit-pioneer:junit-pioneer:$junitPioneer") diff --git a/jbake-core/build.gradle b/jbake-core/build.gradle index 0bb15ea7a..3e058f912 100644 --- a/jbake-core/build.gradle +++ b/jbake-core/build.gradle @@ -23,6 +23,7 @@ dependencies { compile "com.vladsch.flexmark:flexmark:$flexmarkVersion", optional compile "com.vladsch.flexmark:flexmark-profile-pegdown:$flexmarkVersion", optional compile "org.jsoup:jsoup:$jsoupVersion" + compile "io.pebbletemplates:pebble:$pebbleVersion", optional // cli specific dependencies compile "org.eclipse.jetty:jetty-server:$jettyServerVersion", optional diff --git a/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java b/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java new file mode 100644 index 000000000..a55d1a136 --- /dev/null +++ b/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java @@ -0,0 +1,79 @@ +package org.jbake.template; + +import com.mitchellbosecke.pebble.PebbleEngine; +import com.mitchellbosecke.pebble.error.PebbleException; +import com.mitchellbosecke.pebble.extension.escaper.EscaperExtension; +import com.mitchellbosecke.pebble.loader.FileLoader; +import com.mitchellbosecke.pebble.loader.Loader; +import com.mitchellbosecke.pebble.template.PebbleTemplate; +import org.jbake.app.ContentStore; +import org.jbake.app.configuration.JBakeConfiguration; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; + +/** + * Renders pages using the Pebble template engine. + * + * @author Mitchell Bosecke + */ +public class PebbleTemplateEngine extends AbstractTemplateEngine { + private PebbleEngine engine; + + public PebbleTemplateEngine(final JBakeConfiguration config, final ContentStore db) { + super(config, db); + initializeTemplateEngine(); + } + + private void initializeTemplateEngine() { + Loader loader = new FileLoader(); + loader.setPrefix(config.getTemplateFolder().getAbsolutePath()); + + /* + * Turn off the autoescaper because I believe that we can assume all + * data is safe considering it is all statically generated. + */ + EscaperExtension escaper = new EscaperExtension(); + escaper.setAutoEscaping(false); + + engine = new PebbleEngine.Builder().loader(loader).extension(escaper).build(); + } + + @Override + public void renderDocument(final Map model, final String templateName, final Writer writer) + throws RenderingException { + + PebbleTemplate template; + try { + template = engine.getTemplate(templateName); + template.evaluate(writer, wrap(model)); + } catch (PebbleException e) { + throw new RenderingException(e); + } catch (IOException e) { + throw new RenderingException(e); + } + + } + + private Map wrap(final Map model) { + Map result = new HashMap(model) { + + private static final long serialVersionUID = -5489285491728950547L; + + @Override + public Object get(final Object property) { + String key = property.toString(); + try { + return extractors.extractAndTransform(db, key, this, new TemplateEngineAdapter.NoopAdapter()); + } catch(NoModelExtractorException e) { + // fallback to parent model + } + + return super.get(property); + } + }; + + return result; + } +} diff --git a/jbake-core/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties b/jbake-core/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties index 736d53686..f3a9758fe 100644 --- a/jbake-core/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties +++ b/jbake-core/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties @@ -2,5 +2,5 @@ org.jbake.template.FreemarkerTemplateEngine=ftl org.jbake.template.GroovyTemplateEngine=groovy,gsp,gxml org.jbake.template.GroovyMarkupTemplateEngine=tpl org.jbake.template.ThymeleafTemplateEngine=thyme,html -#org.jbake.template.PebbleTemplateEngine=pebble,peb +org.jbake.template.PebbleTemplateEngine=pebble,peb org.jbake.template.JadeTemplateEngine=jade diff --git a/jbake-core/src/test/java/org/jbake/app/template/PebbleTemplateEngineRenderingTest.java b/jbake-core/src/test/java/org/jbake/app/template/PebbleTemplateEngineRenderingTest.java new file mode 100644 index 000000000..29ce840b1 --- /dev/null +++ b/jbake-core/src/test/java/org/jbake/app/template/PebbleTemplateEngineRenderingTest.java @@ -0,0 +1,36 @@ +/* + * The MIT License + * + * Copyright 2015 jdlee. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.jbake.app.template; + +/** + * + * @author jsb + */ +public class PebbleTemplateEngineRenderingTest extends AbstractTemplateEngineRenderingTest{ + + public PebbleTemplateEngineRenderingTest() { + super("pebbleTemplates", "pebble"); + } + +} diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/archive.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/archive.pebble new file mode 100644 index 000000000..a43a6dfcd --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/archive.pebble @@ -0,0 +1,29 @@ +{% extends 'base.pebble' %} + + {% block header %}Archive{% endblock %} + + {% block primary %} + +
+
+ {% set last_month = null %} + {% for post in posts %} + {% if (last_month is not null) %} + {% if post.date | date("MMMM yyyy") != last_month %} + +

{{ post.date | date("MMMM yyyy") }}

+
    + {% endif %} + {% else %} +

    {{ post.date | date("MMMM yyyy") }}

    +
      + {% endif %} + +
    • {{ post.date | date("dd") }} - {{ post.title }}
    • + + {% set last_month = post.date | date("MMMM yyyy") %} + {% endfor %} +
+
+ + {% endblock %} diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/base.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/base.pebble new file mode 100644 index 000000000..32e10ab85 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/base.pebble @@ -0,0 +1,54 @@ + + + + + {% block title %}JBake{% endblock %} + + + + + + + + + + + + + + + + + + + +
+ + {% include 'menu.pebble' %} + +
+ + + {% block primary %}{% endblock %} +
+ +
+ +
+ + {% include 'footer.pebble' %} + + + + + + + + diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/feed.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/feed.pebble new file mode 100644 index 000000000..2a144a5d3 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/feed.pebble @@ -0,0 +1,25 @@ + + + + JBake + {{ config.site_host }} + + My corner of the Internet + en-gb + {{ published_date | date("EEE, d MMM yyyy HH:mm:ss Z") }} + {{ published_date | date("EEE, d MMM yyyy HH:mm:ss Z") }} + + {% for post in posts %} + + {{ post.title }} + {{ config.site_host }}/{{ post.uri }} + {{ post.date | date("EEE, d MMM yyyy HH:mm:ss Z") }} + {{ post.uri }} + + {{ post.body }} + + + {% endfor %} + + + diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/footer.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/footer.pebble new file mode 100644 index 000000000..5c2d5a260 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/footer.pebble @@ -0,0 +1,5 @@ + diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/header.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/header.pebble new file mode 100644 index 000000000..2b0d7379e --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/header.pebble @@ -0,0 +1,79 @@ + + + + + Jonathan Bullock + + + + + + + + + {% if content is not empty and content.og is not null %} + + {% endif %} + + + + + + + + +
+ +
+ +

Jonathan Bullock

+
+ +
diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/index.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/index.pebble new file mode 100644 index 000000000..76e874525 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/index.pebble @@ -0,0 +1,18 @@ +{% extends 'base.pebble' %} + + {% block header %}Blog{% endblock %} + + {% block primary %} + + {% for post in published_posts %} +

{{ post.title }}

+

{{ post.date | date("dd MMMM yyyy") }}

+

{{ post.body }}

+ {% endfor %} + + {{ db.getPublishedPages().size() }} +
+ +

Older posts are available in the archive.

+ + {% endblock %} diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/menu.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/menu.pebble new file mode 100644 index 000000000..72ba0a6c9 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/menu.pebble @@ -0,0 +1,33 @@ + + diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/page.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/page.pebble new file mode 100644 index 000000000..b052b6407 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/page.pebble @@ -0,0 +1,18 @@ +{% extends 'base.pebble' %} + + {% block title %}{{ content.title }}{% endblock %} +{% block header %}

{{ content.title }}

{% endblock %} + + {% block primary %} + +

{{ content.date | date("dd MMMM yyyy") }}

+ +

{{ content.body }}

+ +
+ +
Published Pages
+ {% for page in published_pages %} + {{ page.title }} + {% endfor %} +{% endblock %} diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/post.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/post.pebble new file mode 100644 index 000000000..70a6df9ae --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/post.pebble @@ -0,0 +1,18 @@ +{% extends 'base.pebble' %} + + {% block title %}{{ content.title }}{% endblock %} +{% block header %}

{{ content.title }}

{% endblock %} + + {% block primary %} + + + +

{{ content.body }}

+ +
+ +
Published Posts
+ {% for post in published_posts %} + {{ post.title }} + {% endfor %} +{% endblock %} diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/sitemap.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/sitemap.pebble new file mode 100644 index 000000000..da1464950 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/sitemap.pebble @@ -0,0 +1,9 @@ + + +{% for content in published_content %} + + {{ config.site_host }}{{ content.uri }} + {{ content.date | date("yyyy-MM-dd") }} + +{% endfor %} + diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/tags-index.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/tags-index.pebble new file mode 100644 index 000000000..961bf5d0f --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/tags-index.pebble @@ -0,0 +1,15 @@ +{% extends 'base.pebble' %} + + {% block header %}

Tags

{% endblock %} + + {% block primary %} + +
+
    + {% for tag in tags %} +

    {{ tag.name }} {{tag.tagged_posts.size}}

    + {% endfor %} +
+
+ + {% endblock %} diff --git a/jbake-core/src/test/resources/fixture/pebbleTemplates/tags.pebble b/jbake-core/src/test/resources/fixture/pebbleTemplates/tags.pebble new file mode 100644 index 000000000..84edd1e88 --- /dev/null +++ b/jbake-core/src/test/resources/fixture/pebbleTemplates/tags.pebble @@ -0,0 +1,26 @@ +{% extends 'base.pebble' %} + + {% block header %}{{ tag }}{% endblock %} + + {% block primary %} + + {% set last_month = null %} + {% for post in posts %} + {% if last_month is not null %} + {% if post.date | date("MMMM yyyy") != last_month %} + +

{{ post.date | date("MMMM yyyy") }}

+
    + {% endif %} + {% else %} +

    {{ post.date | date("MMMM yyyy") }}

    +
      + {% endif %} + +
    • {{ post.date | date("dd MMMM") }} - {{ post.title }}
    • + {% set last_month = post.date | date("MMMM yyyy") %} + + {% endfor %} +
    + + {% endblock %} From 44b6a3d6e6b238df86c2db101d3019b3351b70d2 Mon Sep 17 00:00:00 2001 From: Jonathan Bullock Date: Mon, 18 Feb 2019 22:25:38 +0000 Subject: [PATCH 2/2] Corrected checkstyle issue. --- .../src/main/java/org/jbake/template/PebbleTemplateEngine.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java b/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java index a55d1a136..07819580e 100644 --- a/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java +++ b/jbake-core/src/main/java/org/jbake/template/PebbleTemplateEngine.java @@ -11,7 +11,8 @@ import java.io.IOException; import java.io.Writer; -import java.util.*; +import java.util.HashMap; +import java.util.Map; /** * Renders pages using the Pebble template engine.