From bf8d00cd459fce6f8ac916573dbbfa67863ebb79 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Thu, 12 Mar 2015 21:22:45 +0100 Subject: [PATCH 1/7] added RendererSpec to unify Renderer Tests for different Template Engines --- pom.xml | 716 +++++++++--------- .../groovy/org/jbake/app/RendererSpec.groovy | 332 ++++++++ .../org/jbake/app/GroovyRendererTest.java | 213 ------ src/test/java/org/jbake/app/RendererTest.java | 228 ------ .../org/jbake/app/ThymeleafRendererTest.java | 215 ------ .../resources/groovyTemplates/allcontent.gsp | 9 + .../thymeleafTemplates/allcontent.thyme | 7 + 7 files changed, 726 insertions(+), 994 deletions(-) create mode 100644 src/test/groovy/org/jbake/app/RendererSpec.groovy delete mode 100644 src/test/java/org/jbake/app/GroovyRendererTest.java delete mode 100644 src/test/java/org/jbake/app/RendererTest.java delete mode 100644 src/test/java/org/jbake/app/ThymeleafRendererTest.java create mode 100644 src/test/resources/groovyTemplates/allcontent.gsp create mode 100644 src/test/resources/thymeleafTemplates/allcontent.thyme diff --git a/pom.xml b/pom.xml index a26f29f68..820a3c105 100644 --- a/pom.xml +++ b/pom.xml @@ -1,77 +1,79 @@ - - 4.0.0 + + 4.0.0 - - org.sonatype.oss - oss-parent - 7 - + + org.sonatype.oss + oss-parent + 7 + - org.jbake - jbake-core - 2.3.3-SNAPSHOT - jar + org.jbake + jbake-core + 2.3.3-SNAPSHOT + jar - jbake - JBake is a Java based open source static site/blog generator for developers. - http://jbake.org - - - jonbullock - Jonathan Bullock - jonbullock@gmail.com - http://jonathanbullock.com - 0 - - + jbake + JBake is a Java based open source static site/blog generator for developers. + http://jbake.org + + + jonbullock + Jonathan Bullock + jonbullock@gmail.com + http://jonathanbullock.com + 0 + + - - https://github.com/jbake-org/jbake/ - scm:git:git@github.com:jbake-org/jbake.git - scm:git:https://github.com/jbake-org/jbake.git - - - - GitHub Issues - https://github.com/jbake-org/jbake/issues - + + https://github.com/jbake-org/jbake/ + scm:git:git@github.com:jbake-org/jbake.git + scm:git:https://github.com/jbake-org/jbake.git + - - - jbake-dev - jbake-dev@googlegroups.com - jbake-dev+unsubscribe@googlegroups.com - http://groups.google.com/group/jbake-dev - - - jbake-user - jbake-user@googlegroups.com - jbake-user+unsubscribe@googlegroups.com - http://groups.google.com/group/jbake-user - - + + GitHub Issues + https://github.com/jbake-org/jbake/issues + - - - The MIT License (MIT) - http://opensource.org/licenses/MIT - - + + + jbake-dev + jbake-dev@googlegroups.com + jbake-dev+unsubscribe@googlegroups.com + http://groups.google.com/group/jbake-dev + + + jbake-user + jbake-user@googlegroups.com + jbake-user+unsubscribe@googlegroups.com + http://groups.google.com/group/jbake-user + + - - UTF-8 - ${maven.build.timestamp} - yyyy-MM-dd HH:mm:ssa - - 1.5.1 - 2.4 - 1.9 - 2.0.26 - 2.3.20 - 4.11 - 1.4.2 - 8.1.12.v20130726 + + + The MIT License (MIT) + http://opensource.org/licenses/MIT + + + + + UTF-8 + ${maven.build.timestamp} + yyyy-MM-dd HH:mm:ssa + + 1.5.1 + 2.4 + 1.9 + 2.0.26 + 2.3.20 + 4.11 + 1.0-groovy-2.4 + 1.4.2 + 8.1.12.v20130726 1.6.4 2.3.6 1.7.6 @@ -81,239 +83,271 @@ 1.1.1 - - ${project.artifactId} - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-eclipse-plugin - 2.9 - - true - - - - org.apache.maven.plugins - maven-scm-plugin - 1.1 - - - checkout-example-project-freemarker - prepare-package - - checkout - - - ${project.build.directory}/example-project-freemarker - scm:git:git://github.com/jbake-org/jbake-example-project-freemarker.git - - - - checkout-example-project-groovy - prepare-package - - checkout - - - ${project.build.directory}/example-project-groovy - scm:git:git://github.com/jbake-org/jbake-example-project-groovy.git - - - - checkout-example-project-thymeleaf - prepare-package - - checkout - - - ${project.build.directory}/example-project-thymeleaf - scm:git:git://github.com/jbake-org/jbake-example-project-thymeleaf.git - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - - true - lib/ - org.jbake.launcher.Main - org.jbake.launcher - - - lib/ - - - - - - org.apache.maven.plugins - maven-clean-plugin - 2.4.1 - - - - dist - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.4 - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/lib - test - compile - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.4 - - - zip-example-project-freemarker - package - - single - - - example_project_freemarker - false - - src/main/assembly/assembly-example-project-freemarker.xml - - false - - - - zip-example-project-groovy - package - - single - - - example_project_groovy - false - - src/main/assembly/assembly-example-project-groovy.xml - - false - - - - zip-example-project-thymeleaf - package - - single - - - example_project_thymeleaf - false - - src/main/assembly/assembly-example-project-thymeleaf.xml - - false - - - - make-assembly - package - - single - - - dist - jbake-${project.version} - - src/main/assembly/assembly.xml - - false - - - - - - org.jacoco - jacoco-maven-plugin - 0.7.2.201409121644 - - - prepare-agent - - prepare-agent - - - - - - org.eluder.coveralls - coveralls-maven-plugin - 2.0.1 - - - - - - - - - src/main/resources - true - - - - - - commons-io - commons-io - ${commons.io.version} - - - commons-configuration - commons-configuration - ${commons.configuration.version} - - - com.googlecode.json-simple - json-simple - ${json-simple.version} - - - args4j - args4j - ${args4j.version} - - - org.freemarker - freemarker - ${freemarker.version} + + ${project.artifactId} + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.9 + + true + + + + org.apache.maven.plugins + maven-scm-plugin + 1.1 + + + checkout-example-project-freemarker + prepare-package + + checkout + + + ${project.build.directory}/example-project-freemarker + scm:git:git://github.com/jbake-org/jbake-example-project-freemarker.git + + + + + checkout-example-project-groovy + prepare-package + + checkout + + + ${project.build.directory}/example-project-groovy + scm:git:git://github.com/jbake-org/jbake-example-project-groovy.git + + + + + checkout-example-project-thymeleaf + prepare-package + + checkout + + + ${project.build.directory}/example-project-thymeleaf + scm:git:git://github.com/jbake-org/jbake-example-project-thymeleaf.git + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + true + lib/ + org.jbake.launcher.Main + org.jbake.launcher + + + lib/ + + + + + + org.apache.maven.plugins + maven-clean-plugin + 2.4.1 + + + + dist + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/lib + test + compile + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.4 + + + zip-example-project-freemarker + package + + single + + + example_project_freemarker + false + + src/main/assembly/assembly-example-project-freemarker.xml + + false + + + + zip-example-project-groovy + package + + single + + + example_project_groovy + false + + src/main/assembly/assembly-example-project-groovy.xml + + false + + + + zip-example-project-thymeleaf + package + + single + + + example_project_thymeleaf + false + + src/main/assembly/assembly-example-project-thymeleaf.xml + + false + + + + make-assembly + package + + single + + + dist + jbake-${project.version} + + src/main/assembly/assembly.xml + + false + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.2.201409121644 + + + prepare-agent + + prepare-agent + + + + + + org.eluder.coveralls + coveralls-maven-plugin + 2.0.1 + + + + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 1.5 + + + + compile + testCompile + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18.1 + + + **/*Test.class + **/*Spec.class + + + + + + + + src/main/resources + true + + + + + + commons-io + commons-io + ${commons.io.version} + + + commons-configuration + commons-configuration + ${commons.configuration.version} + + + com.googlecode.json-simple + json-simple + ${json-simple.version} + + + args4j + args4j + ${args4j.version} + + + org.freemarker + freemarker + ${freemarker.version} true - + com.orientechnologies orient-commons @@ -325,41 +359,47 @@ ${orientdb.version} - - junit - junit - ${junit.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - - org.pegdown - pegdown - ${pegdown.version} + + junit + junit + ${junit.version} + test + + + org.spockframework + spock-core + ${spock.version} + test + + + org.assertj + assertj-core + ${assertj.version} + test + + + + org.pegdown + pegdown + ${pegdown.version} true - - - org.asciidoctor - asciidoctorj - ${asciidoctorj.version} + + + org.asciidoctor + asciidoctorj + ${asciidoctorj.version} true - - - org.eclipse.jetty - jetty-server - ${jetty.version} + + + org.eclipse.jetty + jetty-server + ${jetty.version} true - + org.codehaus.groovy groovy @@ -371,19 +411,19 @@ groovy-templates ${groovy.version} true - + org.thymeleaf thymeleaf ${thymeleaf.version} true - - - org.slf4j - slf4j-api - ${slf4j.version} - + + + org.slf4j + slf4j-api + ${slf4j.version} + ch.qos.logback @@ -398,5 +438,5 @@ ${logback.version} true - + diff --git a/src/test/groovy/org/jbake/app/RendererSpec.groovy b/src/test/groovy/org/jbake/app/RendererSpec.groovy new file mode 100644 index 000000000..78d983ea4 --- /dev/null +++ b/src/test/groovy/org/jbake/app/RendererSpec.groovy @@ -0,0 +1,332 @@ +package org.jbake.app + +import org.apache.commons.configuration.CompositeConfiguration +import org.apache.commons.io.FileUtils +import org.jbake.model.DocumentTypes +import org.junit.Assert +import org.junit.Rule +import org.junit.rules.TemporaryFolder +import spock.lang.Shared +import spock.lang.Specification +import spock.lang.Unroll + +/** + * Created by frank on 12.03.15. + */ +class RendererSpec extends Specification { + @Rule + public TemporaryFolder folder = new TemporaryFolder() + + @Shared + def templateMap = [ + 'groovyTemplates': '.gsp', + 'thymeleafTemplates': '.thyme', + 'templates' : '.tfl' + ] + + File sourceFolder + File destinationFolder + CompositeConfiguration config + ContentStore db + Crawler crawler + + + def setup(){ + + setupFolders() + loadConfig() + + db = DBUtil.createDB("memory", "documents"+System.currentTimeMillis()) + } + + def cleanup(){ + db.drop() + db.close() + } + + def setupFolders(){ + sourceFolder = new File(this.class.getResource("/").getFile()) + if (!sourceFolder.exists()) { + throw new Exception("Cannot find sample data structure!") + } + + destinationFolder = folder.getRoot() + + } + + def loadConfig(){ + config = ConfigUtil.load(sourceFolder) + Assert.assertEquals(".html", config.getString(ConfigUtil.Keys.OUTPUT_EXTENSION)) + } + + def getTemplateFolder(String templateFolderName){ + def templateFolder = new File(sourceFolder, templateFolderName) + if (!templateFolder.exists()) { + throw new Exception("Cannot find template folder!") + } + templateFolder + } + + def Map crawlContentAndProcessFile(File sampleFile, String templateSuffix) { + + crawlContent(templateSuffix) + + def content = processFile(sampleFile) + content + } + + def crawlContent(String templateSuffix){ + modifyConfiguration(templateSuffix) + crawler = new Crawler(db, sourceFolder, config) + crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")) + } + + def modifyConfiguration(String templateSuffix){ + + if ( templateSuffix != null ) { + Iterator keys = config.getKeys() + while (keys.hasNext()) { + String key = keys.next() + if (key.startsWith("template") && key.endsWith(".file")) { + String old = (String) config.getProperty(key) + config.setProperty(key, old.substring(0, old.length() - 4) + templateSuffix) + } + } + } + + } + + def processFile(def sampleFile){ + Parser parser = new Parser(config, sourceFolder.getPath()) + def content = parser.processFile(sampleFile) + content.put("uri", "/" + sampleFile.name) + content + } + + def getOutput(String fileName){ + FileUtils.readFileToString( new File(destinationFolder, fileName) ) + } + + @Unroll + def "should render a Post with template Folder #templateFolderName and suffix #templateSuffix"(){ + + given: + String filename = "second-post.html" + String filePath = sourceFolder.getPath() + File.separator + "content" + File.separator + "blog" + File.separator + "2013" + File.separator + filename + File sampleFile = new File(filePath) + + Map content = crawlContentAndProcessFile(sampleFile, templateSuffix) + def templateFolder = getTemplateFolder(templateFolderName) + def renderer = new Renderer(db, destinationFolder, templateFolder, config) + + when: + renderer.render(content) + + + then: + + String output = getOutput(filename) + output.contains("

Second Post

") + output.contains("

28") + output.contains("2013

") + output.contains("Lorem ipsum dolor sit amet") + output.contains("
Published Posts
") + output.contains("blog/2012/first-post.html") + + where: + + templateFolderName << templateMap.keySet() + templateSuffix << templateMap.keySet().collect { templateMap."$it" } + } + + @Unroll + def "should render a Page with template Folder #templateFolderName and suffix #templateSuffix"(){ + + given: + String filename = "about.html" + String filePath = sourceFolder.getPath() + File.separator + "content" + File.separator + filename + File sampleFile = new File(filePath) + + def content = crawlContentAndProcessFile(sampleFile,templateSuffix) + def templateFolder = getTemplateFolder(templateFolderName) + def renderer = new Renderer(db, destinationFolder, templateFolder, config) + + when: + renderer.render(content) + + then: + String output = getOutput(filename) + + output.contains("

About

") + output.contains("All about stuff!") + output.contains("
Published Pages
") + output.contains("/projects.html"); + + where: + + templateFolderName << templateMap.keySet() + templateSuffix << templateMap.keySet().collect { templateMap."$it" } + + } + + @Unroll + def "should render allcontent Page with template Folder #templateFolderName and suffix #templateSuffix"(){ + given: + DocumentTypes.addDocumentType("paper"); + DBUtil.updateSchema(db); + + String filename = "allcontent.html" + String filePath = sourceFolder.getPath() + File.separator + "content" + File.separator + filename + File sampleFile = new File(filePath) + + def content = crawlContentAndProcessFile(sampleFile,templateSuffix) + def templateFolder = getTemplateFolder(templateFolderName) + def renderer = new Renderer(db, destinationFolder, templateFolder, config) + + when: + renderer.render(content) + + then: + String output = getOutput(filename) + output.contains("blog/2013/second-post.html") + output.contains("blog/2012/first-post.html") + output.contains("papers/published-paper.html") + output.contains("papers/draft-paper.html"); + + + where: + + templateFolderName << templateMap.keySet() + templateSuffix << templateMap.keySet().collect { templateMap."$it" } + + + } + + @Unroll + def "should render Index with tempalte Folder #templateFolderName and suffix #templateSuffix"(){ + given: + String fileName = "index.html" + + crawlContent(templateSuffix) + def templateFolder = getTemplateFolder(templateFolderName) + def renderer = new Renderer(db, destinationFolder, templateFolder, config) + + when: + //exec + renderer.renderIndex(fileName); + + then: + def output = getOutput(fileName) + output.contains("

My corner of the Internet") + output.contains("Second Post") + output.contains("First Post"); + + where: + + templateFolderName << templateMap.keySet() + templateSuffix << templateMap.keySet().collect { templateMap."$it" } + + } + @Unroll + def "should render Archive with tempalte Folder #templateFolderName and suffix #templateSuffix"(){ + given: + String fileName = "archive.html" + + crawlContent(templateSuffix) + def templateFolder = getTemplateFolder(templateFolderName) + def renderer = new Renderer(db, destinationFolder, templateFolder, config) + + when: + //exec + renderer.renderIndex(fileName); + + then: + def output = getOutput(fileName) + output.contains(" keys = config.getKeys(); - while (keys.hasNext()) { - String key = keys.next(); - if (key.startsWith("template") && key.endsWith(".file")) { - String old = (String)config.getProperty(key); - config.setProperty(key, old.substring(0, old.length()-4)+".gsp"); - } - } - Assert.assertEquals(".html", config.getString(Keys.OUTPUT_EXTENSION)); - db = DBUtil.createDB("memory", "documents"+System.currentTimeMillis()); - } - - @After - public void cleanup() throws InterruptedException { - db.drop(); - db.close(); - } - - @Test - public void renderPost() throws Exception { - // setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - String filename = "second-post.html"; - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + "blog" + File.separator + "2013" + File.separator + filename); - Map content = parser.processFile(sampleFile); - content.put("uri", "/" + filename); - renderer.render(content); - File outputFile = new File(destinationFolder, filename); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

Second Post

") - .contains("

28") - .contains("2013

") - .contains("Lorem ipsum dolor sit amet") - .contains("
Published Posts
") - .contains("blog/2012/first-post.html"); - } - - @Test - public void renderPage() throws Exception { - // setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - String filename = "about.html"; - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + filename); - Map content = parser.processFile(sampleFile); - content.put("uri", "/" + filename); - renderer.render(content); - File outputFile = new File(destinationFolder, filename); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

About

") - .contains("All about stuff!") - .contains("
Published Pages
") - .contains("/projects.html"); - } - - @Test - public void renderIndex() throws Exception { - //setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - //exec - renderer.renderIndex("index.html"); - - //validate - File outputFile = new File(destinationFolder, "index.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

First Post

") - .contains("

Second Post

"); - } - - @Test - public void renderFeed() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderFeed("feed.xml"); - File outputFile = new File(destinationFolder, "feed.xml"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("My corner of the Internet") - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderArchive() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderArchive("archive.html"); - File outputFile = new File(destinationFolder, "archive.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderTags() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderTags(crawler.getTags(), "tags"); - - // verify - File outputFile = new File(destinationFolder + File.separator + "tags" + File.separator + "blog.html"); - Assert.assertTrue(outputFile.exists()); - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderSitemap() throws Exception { - DocumentTypes.addDocumentType("paper"); - DBUtil.updateSchema(db); - - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderSitemap("sitemap.xml"); - File outputFile = new File(destinationFolder, "sitemap.xml"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("blog/2013/second-post.html") - .contains("blog/2012/first-post.html") - .contains("papers/published-paper.html") - .doesNotContain("draft-paper.html"); - } -} diff --git a/src/test/java/org/jbake/app/RendererTest.java b/src/test/java/org/jbake/app/RendererTest.java deleted file mode 100644 index c41546572..000000000 --- a/src/test/java/org/jbake/app/RendererTest.java +++ /dev/null @@ -1,228 +0,0 @@ -package org.jbake.app; - -import org.jbake.app.ConfigUtil.Keys; -import org.jbake.model.DocumentTypes; -import org.junit.After; - -import java.io.File; - -import static org.assertj.core.api.Assertions.*; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Map; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -public class RendererTest { - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - private File sourceFolder; - private File destinationFolder; - private File templateFolder; - private CompositeConfiguration config; - private ContentStore db; - - @Before - public void setup() throws Exception, IOException, URISyntaxException { - URL sourceUrl = this.getClass().getResource("/"); - - sourceFolder = new File(sourceUrl.getFile()); - if (!sourceFolder.exists()) { - throw new Exception("Cannot find sample data structure!"); - } - - destinationFolder = folder.getRoot(); - - templateFolder = new File(sourceFolder, "templates"); - if (!templateFolder.exists()) { - throw new Exception("Cannot find template folder!"); - } - - config = ConfigUtil.load(new File(this.getClass().getResource("/").getFile())); - Assert.assertEquals(".html", config.getString(Keys.OUTPUT_EXTENSION)); - db = DBUtil.createDB("memory", "documents"+System.currentTimeMillis()); - } - - @After - public void cleanup() throws InterruptedException { - db.drop(); - db.close(); - } - - @Test - public void renderPost() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + "blog" + File.separator + "2013" + File.separator + "second-post.html"); - Map content = parser.processFile(sampleFile); - content.put("uri", "/second-post.html"); - renderer.render(content); - File outputFile = new File(destinationFolder, "second-post.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

Second Post

") - .contains("

28") - .contains("2013

") - .contains("Lorem ipsum dolor sit amet") - .contains("
Published Posts
") - .contains("blog/2012/first-post.html") - .contains(""); - } - - @Test - public void renderPage() throws Exception { - // setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - String filename = "about.html"; - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + filename); - Map content = parser.processFile(sampleFile); - content.put("uri", "/" + filename); - renderer.render(content); - File outputFile = new File(destinationFolder, filename); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

About

") - .contains("All about stuff!") - .contains("
Published Pages
") - .contains("/projects.html"); - } - - @Test - public void renderIndex() throws Exception { - //setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - //exec - renderer.renderIndex("index.html"); - - //validate - File outputFile = new File(destinationFolder, "index.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

First Post

") - .contains("

Second Post

"); - } - - @Test - public void renderFeed() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderFeed("feed.xml"); - File outputFile = new File(destinationFolder, "feed.xml"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("My corner of the Internet") - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderArchive() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderArchive("archive.html"); - File outputFile = new File(destinationFolder, "archive.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderTags() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderTags(crawler.getTags(), "tags"); - - // verify - File outputFile = new File(destinationFolder + File.separator + "tags" + File.separator + "blog.html"); - Assert.assertTrue(outputFile.exists()); - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderSitemap() throws Exception { - DocumentTypes.addDocumentType("paper"); - DBUtil.updateSchema(db); - - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderSitemap("sitemap.xml"); - File outputFile = new File(destinationFolder, "sitemap.xml"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("blog/2013/second-post.html") - .contains("blog/2012/first-post.html") - .contains("papers/published-paper.html") - .doesNotContain("draft-paper.html"); - } - - @Test - public void renderAllContent() throws Exception { - DocumentTypes.addDocumentType("paper"); - DBUtil.updateSchema(db); - - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + "allcontent.html"); - Map content = parser.processFile(sampleFile); - content.put("uri", "/allcontent.html"); - renderer.render(content); - File outputFile = new File(destinationFolder, "allcontent.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("blog/2013/second-post.html") - .contains("blog/2012/first-post.html") - .contains("papers/published-paper.html") - .contains("draft-paper.html"); - } -} diff --git a/src/test/java/org/jbake/app/ThymeleafRendererTest.java b/src/test/java/org/jbake/app/ThymeleafRendererTest.java deleted file mode 100644 index fed656e95..000000000 --- a/src/test/java/org/jbake/app/ThymeleafRendererTest.java +++ /dev/null @@ -1,215 +0,0 @@ -package org.jbake.app; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.io.FileUtils; -import org.jbake.app.ConfigUtil.Keys; -import org.jbake.model.DocumentTypes; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Iterator; -import java.util.Map; -import java.util.Scanner; - -public class ThymeleafRendererTest { - - @Rule - public TemporaryFolder folder = new TemporaryFolder(); - - private File sourceFolder; - private File destinationFolder; - private File templateFolder; - private CompositeConfiguration config; - private ContentStore db; - - @Before - public void setup() throws Exception, IOException, URISyntaxException { - URL sourceUrl = this.getClass().getResource("/"); - - sourceFolder = new File(sourceUrl.getFile()); - if (!sourceFolder.exists()) { - throw new Exception("Cannot find sample data structure!"); - } - - destinationFolder = folder.getRoot(); - - templateFolder = new File(sourceFolder, "thymeleafTemplates"); - if (!templateFolder.exists()) { - throw new Exception("Cannot find template folder!"); - } - - config = ConfigUtil.load(new File(this.getClass().getResource("/").getFile())); - Iterator keys = config.getKeys(); - while (keys.hasNext()) { - String key = keys.next(); - if (key.startsWith("template") && key.endsWith(".file")) { - String old = (String)config.getProperty(key); - config.setProperty(key, old.substring(0, old.length()-4)+".thyme"); - } - } - Assert.assertEquals(".html", config.getString(Keys.OUTPUT_EXTENSION)); - db = DBUtil.createDB("memory", "documents"+System.currentTimeMillis()); - - } - - @After - public void cleanup() throws InterruptedException { - db.drop(); - db.close(); - } - - @Test - public void renderPost() throws Exception { - // setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - String filename = "second-post.html"; - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + "blog" + File.separator + "2013" + File.separator + filename); - Map content = parser.processFile(sampleFile); - content.put("uri", "/" + filename); - renderer.render(content); - File outputFile = new File(destinationFolder, filename); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

Second Post

") - .contains("

28") - .contains("2013

") - .contains("Lorem ipsum dolor sit amet") - .contains("
Published Posts
") - .contains("blog/2012/first-post.html"); - } - - @Test - public void renderPage() throws Exception { - // setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Parser parser = new Parser(config, sourceFolder.getPath()); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - String filename = "about.html"; - - File sampleFile = new File(sourceFolder.getPath() + File.separator + "content" + File.separator + filename); - Map content = parser.processFile(sampleFile); - content.put("uri", "/" + filename); - renderer.render(content); - File outputFile = new File(destinationFolder, filename); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

About

") - .contains("All about stuff!") - .contains("
Published Pages
") - .contains("/projects.html"); - } - - @Test - public void renderIndex() throws Exception { - //setup - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - //exec - renderer.renderIndex("index.html"); - - //validate - File outputFile = new File(destinationFolder, "index.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("

First Post

") - .contains("

Second Post

"); - } - - @Test - public void renderFeed() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderFeed("feed.xml"); - File outputFile = new File(destinationFolder, "feed.xml"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("My corner of the Internet") - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderArchive() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderArchive("archive.html"); - File outputFile = new File(destinationFolder, "archive.html"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderTags() throws Exception { - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderTags(crawler.getTags(), "tags"); - - // verify - File outputFile = new File(destinationFolder + File.separator + "tags" + File.separator + "blog.html"); - Assert.assertTrue(outputFile.exists()); - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("Second Post") - .contains("First Post"); - } - - @Test - public void renderSitemap() throws Exception { - // cannot be put in @Before as ThmyeLeaf can't lazy load from DB, and expects content there under this type - DocumentTypes.addDocumentType("paper"); - DBUtil.updateSchema(db); - - Crawler crawler = new Crawler(db, sourceFolder, config); - crawler.crawl(new File(sourceFolder.getPath() + File.separator + "content")); - Renderer renderer = new Renderer(db, destinationFolder, templateFolder, config); - renderer.renderSitemap("sitemap.xml"); - File outputFile = new File(destinationFolder, "sitemap.xml"); - Assert.assertTrue(outputFile.exists()); - - // verify - String output = FileUtils.readFileToString(outputFile); - assertThat(output) - .contains("blog/2013/second-post.html") - .contains("blog/2012/first-post.html") - .contains("papers/published-paper.html") - .doesNotContain("draft-paper.html"); - } -} diff --git a/src/test/resources/groovyTemplates/allcontent.gsp b/src/test/resources/groovyTemplates/allcontent.gsp new file mode 100644 index 000000000..4762cbc9f --- /dev/null +++ b/src/test/resources/groovyTemplates/allcontent.gsp @@ -0,0 +1,9 @@ + + + <% all_content.each { content -> %> + + ${config.site_host}${content.uri} + ${content.date.format("yyyy-MM-dd")} + + <%}%> + diff --git a/src/test/resources/thymeleafTemplates/allcontent.thyme b/src/test/resources/thymeleafTemplates/allcontent.thyme new file mode 100644 index 000000000..97e258efb --- /dev/null +++ b/src/test/resources/thymeleafTemplates/allcontent.thyme @@ -0,0 +1,7 @@ + + + + /blog/content.html + + + From 751c7bb7076d765f3ade70577f17e307df8ec57a Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 13 Mar 2015 12:56:51 +0100 Subject: [PATCH 2/7] added Groovy MarkupTemplate Engine The Template Engine is registered for template files with suffix '.tpl' It is basically a clone of GroovyTemplateEngine using the Groovy MarkupTemplateEngine. Because there are refactoring pull-requests out there, I skipped refactoring those two Engines for now. --- .../template/GroovyMarkupTemplateEngine.java | 131 ++++++++++++++++++ .../jbake/template/GroovyTemplateEngine.java | 5 - ...rg.jbake.parser.TemplateEngines.properties | 1 + .../groovy/org/jbake/app/RendererSpec.groovy | 1 + .../groovyMarkupTemplates/allcontent.tpl | 9 ++ .../groovyMarkupTemplates/archive.tpl | 26 ++++ .../resources/groovyMarkupTemplates/feed.tpl | 22 +++ .../groovyMarkupTemplates/footer.tpl | 8 ++ .../groovyMarkupTemplates/header.tpl | 59 ++++++++ .../resources/groovyMarkupTemplates/index.tpl | 13 ++ .../groovyMarkupTemplates/layout/main.tpl | 28 ++++ .../resources/groovyMarkupTemplates/menu.tpl | 9 ++ .../resources/groovyMarkupTemplates/page.tpl | 22 +++ .../resources/groovyMarkupTemplates/post.tpl | 20 +++ .../groovyMarkupTemplates/sitemap.tpl | 12 ++ .../resources/groovyMarkupTemplates/tags.tpl | 29 ++++ 16 files changed, 390 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java create mode 100644 src/test/resources/groovyMarkupTemplates/allcontent.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/archive.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/feed.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/footer.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/header.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/index.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/layout/main.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/menu.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/page.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/post.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/sitemap.tpl create mode 100644 src/test/resources/groovyMarkupTemplates/tags.tpl diff --git a/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java new file mode 100644 index 000000000..57d8e53ea --- /dev/null +++ b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java @@ -0,0 +1,131 @@ +package org.jbake.template; + +import com.orientechnologies.orient.core.record.impl.ODocument; +import groovy.lang.GString; +import groovy.lang.Writable; +import groovy.text.Template; +import groovy.text.TemplateEngine; +import groovy.text.XmlTemplateEngine; +import groovy.text.markup.MarkupTemplateEngine; +import groovy.text.markup.TemplateConfiguration; +import org.apache.commons.configuration.CompositeConfiguration; +import org.codehaus.groovy.runtime.MethodClosure; +import org.jbake.app.ConfigUtil.Keys; +import org.jbake.app.ContentStore; +import org.jbake.app.DBUtil; +import org.jbake.app.DocumentList; +import org.jbake.model.DocumentTypes; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.*; +import java.util.*; + +/** + * Renders documents using the GroovyMarkupTemplateEngine. + * + * @see Groovy MarkupTemplateEngine Documentation + * + * The file extension to activate this Engine is .tpl + */ +public class GroovyMarkupTemplateEngine extends AbstractTemplateEngine { + + private final Map cachedTemplates = new HashMap(); + + public GroovyMarkupTemplateEngine(final CompositeConfiguration config, final ContentStore db, final File destination, final File templatesPath) { + super(config, db, destination, templatesPath); + } + + @Override + public void renderDocument(final Map model, final String templateName, final Writer writer) throws RenderingException { + try { + Template template = findTemplate(templateName); + Map wrappedModel = wrap(model); + Writable writable = template.make(wrappedModel); + writable.writeTo(writer); + } catch (Exception e) { + throw new RenderingException(e); + } + } + + private Template findTemplate(final String templateName) throws SAXException, ParserConfigurationException, ClassNotFoundException, IOException { + + TemplateConfiguration templateConfiguration = new TemplateConfiguration(); + templateConfiguration.setUseDoubleQuotes(true); + templateConfiguration.setAutoIndent(true); + templateConfiguration.setAutoNewLine(true); + templateConfiguration.setAutoEscape(true); + + TemplateEngine ste = new MarkupTemplateEngine(MarkupTemplateEngine.class.getClassLoader(),templatesPath,templateConfiguration); + File sourceTemplate = new File(templatesPath, templateName); + Template template = cachedTemplates.get(templateName); + if (template == null) { + template = ste.createTemplate(new InputStreamReader(new BufferedInputStream(new FileInputStream(sourceTemplate)), config.getString(Keys.TEMPLATE_ENCODING))); + cachedTemplates.put(templateName, template); + } + return template; + } + + private Map wrap(final Map model) { + return new HashMap(model) { + @Override + public Object get(final Object property) { + if (property instanceof String || property instanceof GString) { + String key = property.toString(); + if ("published_posts".equals(key)) { + List query = db.getPublishedPosts(); + return DocumentList.wrap(query.iterator()); + } + if ("published_pages".equals(key)) { + List query = db.getPublishedPages(); + return DocumentList.wrap(query.iterator()); + } + if ("published_content".equals(key)) { + List publishedContent = new ArrayList(); + String[] documentTypes = DocumentTypes.getDocumentTypes(); + for (String docType : documentTypes) { + List query = db.getPublishedContent(docType); + publishedContent.addAll(query); + } + return DocumentList.wrap(publishedContent.iterator()); + } + if ("all_content".equals(key)) { + List allContent = new ArrayList(); + String[] documentTypes = DocumentTypes.getDocumentTypes(); + for (String docType : documentTypes) { + List query = db.getAllContent(docType); + allContent.addAll(query); + } + return DocumentList.wrap(allContent.iterator()); + } + if ("alltags".equals(key)) { + List query = db.getAllTagsFromPublishedPosts(); + Set result = new HashSet(); + for (ODocument document : query) { + String[] tags = DBUtil.toStringArray(document.field("tags")); + Collections.addAll(result, tags); + } + return result; + } + String[] documentTypes = DocumentTypes.getDocumentTypes(); + for (String docType : documentTypes) { + if ((docType+"s").equals(key)) { + return DocumentList.wrap(db.getAllContent(docType).iterator()); + } + } + if ("tag_posts".equals(key)) { + String tag = model.get("tag").toString(); + // fetch the tag posts from db + List query = db.getPublishedPostsByTag(tag); + return DocumentList.wrap(query.iterator()); + } + if ("published_date".equals(key)) { + return new Date(); + } + } + + return super.get(property); + } + }; + } +} diff --git a/src/main/java/org/jbake/template/GroovyTemplateEngine.java b/src/main/java/org/jbake/template/GroovyTemplateEngine.java index 0217f37a3..7524604f6 100644 --- a/src/main/java/org/jbake/template/GroovyTemplateEngine.java +++ b/src/main/java/org/jbake/template/GroovyTemplateEngine.java @@ -1,8 +1,6 @@ package org.jbake.template; -import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx; import com.orientechnologies.orient.core.record.impl.ODocument; -import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery; import groovy.lang.GString; import groovy.lang.Writable; @@ -22,13 +20,10 @@ import javax.xml.parsers.ParserConfigurationException; import java.io.BufferedInputStream; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties b/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties index e1ba0e56e..25f262e95 100644 --- a/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties +++ b/src/main/resources/META-INF/org.jbake.parser.TemplateEngines.properties @@ -1,3 +1,4 @@ org.jbake.template.FreemarkerTemplateEngine=ftl org.jbake.template.GroovyTemplateEngine=groovy,gsp,gxml +org.jbake.template.GroovyMarkupTemplateEngine=tpl org.jbake.template.ThymeleafTemplateEngine=thyme,html \ No newline at end of file diff --git a/src/test/groovy/org/jbake/app/RendererSpec.groovy b/src/test/groovy/org/jbake/app/RendererSpec.groovy index 78d983ea4..b55349378 100644 --- a/src/test/groovy/org/jbake/app/RendererSpec.groovy +++ b/src/test/groovy/org/jbake/app/RendererSpec.groovy @@ -20,6 +20,7 @@ class RendererSpec extends Specification { @Shared def templateMap = [ 'groovyTemplates': '.gsp', + 'groovyMarkupTemplates': '.tpl', 'thymeleafTemplates': '.thyme', 'templates' : '.tfl' ] diff --git a/src/test/resources/groovyMarkupTemplates/allcontent.tpl b/src/test/resources/groovyMarkupTemplates/allcontent.tpl new file mode 100644 index 000000000..907fcaa1a --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/allcontent.tpl @@ -0,0 +1,9 @@ +xmlDeclaration() +list{ + all_content.each { cntnt -> + content { + uri("${config.site_host}${cntnt.uri}") + date(${cntnt.date.format("yyyy-MM-dd")}) + } + } +} diff --git a/src/test/resources/groovyMarkupTemplates/archive.tpl b/src/test/resources/groovyMarkupTemplates/archive.tpl new file mode 100644 index 000000000..cf2f4b852 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/archive.tpl @@ -0,0 +1,26 @@ +layout 'layout/main.tpl', + bodyContents: contents { + div(class:"row-fluid marketing"){ + div(class:"span12"){ + h2('Archive') + + def last_month + posts.each {post -> + if (last_month) { + if (post.date.format("MMMM yyyy") != last_month) { + h3("${post.date.format("MMMM yyyy")}") + } + } + else { + h3("${post.date.format("MMMM yyyy")}") + } + + h4 { + yield "${post.date.format("dd MMMM")} - " + a(href:"${post.uri}","${post.title}") + } + last_month = post.date.format("MMMM yyyy") + } + } + } + } \ No newline at end of file diff --git a/src/test/resources/groovyMarkupTemplates/feed.tpl b/src/test/resources/groovyMarkupTemplates/feed.tpl new file mode 100644 index 000000000..de1494133 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/feed.tpl @@ -0,0 +1,22 @@ +xmlDeclaration() +rss(version:"2.0", 'xmlns:atom':'http://www.w3.org/2005/Atom') { + channel { + title('JonathanBullock.com') + link('http://jonathanbullock.com/') + atom:link(href:"http://jonathanbullock.com/feed.xml", rel:"self", type:"application/rss+xml") + description('My corner of the Internet') + language('en-gb') + pubDate("${published_date.format("EEE, d MMM yyyy HH:mm:ss Z")}") + lastBuildDate("${published_date.format("EEE, d MMM yyyy HH:mm:ss Z")}") + + posts.each { post -> + item{ + title("${post.title}") + link("http://jonathanbullock.com${post.uri}") + pubDate("${post.date.format("EEE, d MMM yyyy HH:mm:ss Z")}") + guid(isPermaLink:"false","${post.uri}") + description("${post.body}") + } + } + } +} diff --git a/src/test/resources/groovyMarkupTemplates/footer.tpl b/src/test/resources/groovyMarkupTemplates/footer.tpl new file mode 100644 index 000000000..ffd301b38 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/footer.tpl @@ -0,0 +1,8 @@ +div(class:"footer"){ + p{ + yieldUnescaped '© Jonathan Bullock 2013 | Mixed with ' + a(href:"http://twitter.github.com/bootstrap/",'Bootstrap v2.3.1') + yieldUnescaped '| Baked with ' + a(href:"http://jbake.org","JBake ${version}") + } +} diff --git a/src/test/resources/groovyMarkupTemplates/header.tpl b/src/test/resources/groovyMarkupTemplates/header.tpl new file mode 100644 index 000000000..0ce16f508 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/header.tpl @@ -0,0 +1,59 @@ +meta(charset:'utf-8') +title('Jonathan Bullock') +meta(name:"viewport", content:"width=device-width, initial-scale=1.0") +meta(name:"description", content:"") +meta(name:"author", content:"Jonathan Bullock") + +yieldUnescaped '' +link(href:"/css/bootstrap.min.css", rel:"stylesheet") +style(type:"text/css") { + yieldUnescaped """body { + padding-top: 20px; + padding-bottom: 40px; + } + + /* Custom container */ + .container-narrow { + margin: 0 auto; + max-width: 700px; + } + .container-narrow > hr { + margin: 30px 0; + } + + /* Main marketing message and sign up button */ + .jumbotron { + margin: 60px 0; + text-align: center; + } + .jumbotron h1 { + font-size: 72px; + line-height: 1; + } + .jumbotron .btn { + font-size: 21px; + padding: 14px 24px; + } + + /* Supporting marketing content */ + .marketing { + margin: 60px 0; + } + .marketing p + h4 { + margin-top: 28px; + }""" +} +link(href:"/css/bootstrap-responsive.min.css", rel:"stylesheet") + +yieldUnescaped '' +yieldUnescaped '' + +yieldUnescaped '' +yieldUnescaped '' diff --git a/src/test/resources/groovyMarkupTemplates/index.tpl b/src/test/resources/groovyMarkupTemplates/index.tpl new file mode 100644 index 000000000..d57bb41e5 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/index.tpl @@ -0,0 +1,13 @@ +layout 'layout/main.tpl', + bodyContents: contents { + + div(class:"row-fluid marketing"){ + div(class:"span12"){ + posts[0..<2].each { post -> + h4 { a(href:"${post.uri}","${post.title}") } + p("${post.date.format("dd MMMM yyyy")} - ${post.body.substring(0, 150)}...") + } + a(href:"/archive.html",'Archive') + } + } + } \ No newline at end of file diff --git a/src/test/resources/groovyMarkupTemplates/layout/main.tpl b/src/test/resources/groovyMarkupTemplates/layout/main.tpl new file mode 100644 index 000000000..449a699d1 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/layout/main.tpl @@ -0,0 +1,28 @@ +yieldUnescaped '' +html(lang:'en'){ + + head { + include template: "header.tpl" + } + + body { + div(class:"container-narrow"){ + + include template: 'menu.tpl' + + hr() + + bodyContents() + + hr() + + include template: 'footer.tpl' + + } + + script(src:"/js/jquery-1.9.1.min.js"){} + newLine() + script(src:"/js/bootstrap.min.js"){} + } +} +newLine() diff --git a/src/test/resources/groovyMarkupTemplates/menu.tpl b/src/test/resources/groovyMarkupTemplates/menu.tpl new file mode 100644 index 000000000..30837e9d6 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/menu.tpl @@ -0,0 +1,9 @@ +div(class:"masthead"){ + ul(class:"nav nav-pills pull-right"){ + li { a(href:"/",'Home') } + li { a(href:"/about.html",'About') } + li { a(href:"/projects.html",'Projects') } + li { a(href:"/feed.xml",'Subscribe') } + } + h3(class:"muted",'Jonathan Bullock') +} \ No newline at end of file diff --git a/src/test/resources/groovyMarkupTemplates/page.tpl b/src/test/resources/groovyMarkupTemplates/page.tpl new file mode 100644 index 000000000..d01d7f057 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/page.tpl @@ -0,0 +1,22 @@ +layout 'layout/main.tpl', + bodyContents: contents { + + div(class:"row-fluid marketing"){ + div(class:"span12"){ + h4("${content.title}") + p("${content.body}") + } + } + + hr() + + h5('Published Pages') + published_pages.each {page -> + a(href:"${config.site_host}${page.uri}","${page.title}") + } + + } + + + + diff --git a/src/test/resources/groovyMarkupTemplates/post.tpl b/src/test/resources/groovyMarkupTemplates/post.tpl new file mode 100644 index 000000000..fe3755855 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/post.tpl @@ -0,0 +1,20 @@ +layout 'layout/main.tpl', + bodyContents: contents { + + div(class:"row-fluid marketing"){ + div(class:"span12"){ + h2("${content.title}") + p(class:"post-date", "${content.date.format("dd MMMM yyyy")}") + p("${content.body}") + } + } + + hr() + + h5('Published Posts') + + published_posts.each { post -> + a(href:"${config.site_host}${post.uri}","${post.title}") + } + + } \ No newline at end of file diff --git a/src/test/resources/groovyMarkupTemplates/sitemap.tpl b/src/test/resources/groovyMarkupTemplates/sitemap.tpl new file mode 100644 index 000000000..f44e48531 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/sitemap.tpl @@ -0,0 +1,12 @@ +xmlDeclaration() +urlset( xmlns:"http://www.sitemaps.org/schemas/sitemap/0.9", + 'xmlns:xsi':"http://www.w3.org/2001/XMLSchema-instance", + 'xsi:schemaLocation':"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"){ + + published_content.each { content -> + url { + loc("${config.site_host}${content.uri}") + lastmod("${content.date.format("yyyy-MM-dd")}") + } + } +} \ No newline at end of file diff --git a/src/test/resources/groovyMarkupTemplates/tags.tpl b/src/test/resources/groovyMarkupTemplates/tags.tpl new file mode 100644 index 000000000..3d44b5ab7 --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/tags.tpl @@ -0,0 +1,29 @@ +layout 'layout/main.tpl', + bodyContents: contents { + + div(class:"row-fluid marketing"){ + div(class:"span12"){ + h2('Tags') + def last_month + + posts.each { post -> + if (last_month) { + if (post.date.format("MMMM yyyy") != last_month) { + h3("${post.date.format("MMMM yyyy")}") + } + } + else { + h3("${post.date.format("MMMM yyyy")}") + } + + h4 { + yield "${post.date.format("dd MMMM")} - " + a(href:"${post.uri}","${post.title}") + } + last_month = post.date.format("MMMM yyyy") + } + } + } + + hr() + } \ No newline at end of file From b8cebe5567fb2dbf4b8fb15da727f5bfc93fba18 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 13 Mar 2015 15:35:51 +0100 Subject: [PATCH 3/7] Fixed Test to cover renderArchive --- src/test/groovy/org/jbake/app/RendererSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/groovy/org/jbake/app/RendererSpec.groovy b/src/test/groovy/org/jbake/app/RendererSpec.groovy index b55349378..3abafe426 100644 --- a/src/test/groovy/org/jbake/app/RendererSpec.groovy +++ b/src/test/groovy/org/jbake/app/RendererSpec.groovy @@ -264,7 +264,7 @@ class RendererSpec extends Specification { when: //exec - renderer.renderIndex(fileName); + renderer.renderArchive(fileName); then: def output = getOutput(fileName) From 564a1a5761a68e9fb15589ade992fdf57a7a0ecc Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 13 Mar 2015 16:22:29 +0100 Subject: [PATCH 4/7] use 'alltags' and 'tag_posts' model in templates --- pom.xml | 2 +- .../groovy/org/jbake/app/RendererSpec.groovy | 2 ++ .../resources/groovyMarkupTemplates/tags.tpl | 16 +++++++++++++++- src/test/resources/groovyTemplates/tags.gsp | 17 +++++++++++++++-- src/test/resources/templates/tags.ftl | 17 +++++++++++++++-- .../resources/thymeleafTemplates/tags.thyme | 12 +++++++++++- 6 files changed, 59 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 820a3c105..a6c4cfc0f 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ 1.4.2 8.1.12.v20130726 1.6.4 - 2.3.6 + 2.4.1 1.7.6 1.1.1 1.7.0 diff --git a/src/test/groovy/org/jbake/app/RendererSpec.groovy b/src/test/groovy/org/jbake/app/RendererSpec.groovy index 3abafe426..98449bc6d 100644 --- a/src/test/groovy/org/jbake/app/RendererSpec.groovy +++ b/src/test/groovy/org/jbake/app/RendererSpec.groovy @@ -292,6 +292,8 @@ class RendererSpec extends Specification { def output = FileUtils.readFileToString(new File(destinationFolder.toString() + File.separator + "tags" + File.separator + "blog.html")) output.contains(" + span{ + a(href:"tags/${tag.replace(' ', '-')}.html", class:"label"){ + ${tag} + } + } + } + } + } + div(class:"span12"){ h2('Tags') def last_month - posts.each { post -> + tag_posts.each { post -> if (last_month) { if (post.date.format("MMMM yyyy") != last_month) { h3("${post.date.format("MMMM yyyy")}") diff --git a/src/test/resources/groovyTemplates/tags.gsp b/src/test/resources/groovyTemplates/tags.gsp index 29466cb2f..a04d9533b 100644 --- a/src/test/resources/groovyTemplates/tags.gsp +++ b/src/test/resources/groovyTemplates/tags.gsp @@ -9,10 +9,23 @@
-->
-
+ + + +

Tags

<%def last_month=null;%> - <%posts.each {post ->%> + <%tag_posts.each {post ->%> <%if (last_month) {%> <%if (post.date.format("MMMM yyyy") != last_month) {%>

${post.date.format("MMMM yyyy")}

diff --git a/src/test/resources/templates/tags.ftl b/src/test/resources/templates/tags.ftl index 0b7305992..f9c0aca13 100644 --- a/src/test/resources/templates/tags.ftl +++ b/src/test/resources/templates/tags.ftl @@ -9,9 +9,22 @@
-->
-
+ +
+

Taglist

+ <#list alltags as tag> +
+ + ${tag} + +
+ +
+ + +

Tags

- <#list posts as post> + <#list tag_posts as post> <#if (last_month)??> <#if post.date?string("MMMM yyyy") != last_month>

${post.date?string("MMMM yyyy")}

diff --git a/src/test/resources/thymeleafTemplates/tags.thyme b/src/test/resources/thymeleafTemplates/tags.thyme index 52dc573d5..322025d8f 100644 --- a/src/test/resources/thymeleafTemplates/tags.thyme +++ b/src/test/resources/thymeleafTemplates/tags.thyme @@ -7,9 +7,19 @@
+ +
+

Taglist

+
+ + blog + +
+
+

Tags

-
+

June 2014

- Post title

From 74e259b46ad9f71bccf92a9cc58b738759651930 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 13 Mar 2015 16:51:36 +0100 Subject: [PATCH 5/7] setup and initialize MarkupTemplateEngine once only --- .../template/GroovyMarkupTemplateEngine.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java index 57d8e53ea..e9b85ae4e 100644 --- a/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java +++ b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java @@ -30,10 +30,25 @@ */ public class GroovyMarkupTemplateEngine extends AbstractTemplateEngine { - private final Map cachedTemplates = new HashMap(); + private TemplateConfiguration templateConfiguration; + private TemplateEngine templateEngine; public GroovyMarkupTemplateEngine(final CompositeConfiguration config, final ContentStore db, final File destination, final File templatesPath) { super(config, db, destination, templatesPath); + setupTemplateConfiguration(); + initializeTemplateEngine(); + } + + private void setupTemplateConfiguration() { + templateConfiguration = new TemplateConfiguration(); + templateConfiguration.setUseDoubleQuotes(true); + templateConfiguration.setAutoIndent(true); + templateConfiguration.setAutoNewLine(true); + templateConfiguration.setAutoEscape(true); + } + + private void initializeTemplateEngine() { + templateEngine = new MarkupTemplateEngine(MarkupTemplateEngine.class.getClassLoader(),templatesPath,templateConfiguration); } @Override @@ -49,20 +64,9 @@ public void renderDocument(final Map model, final String templat } private Template findTemplate(final String templateName) throws SAXException, ParserConfigurationException, ClassNotFoundException, IOException { - - TemplateConfiguration templateConfiguration = new TemplateConfiguration(); - templateConfiguration.setUseDoubleQuotes(true); - templateConfiguration.setAutoIndent(true); - templateConfiguration.setAutoNewLine(true); - templateConfiguration.setAutoEscape(true); - - TemplateEngine ste = new MarkupTemplateEngine(MarkupTemplateEngine.class.getClassLoader(),templatesPath,templateConfiguration); File sourceTemplate = new File(templatesPath, templateName); - Template template = cachedTemplates.get(templateName); - if (template == null) { - template = ste.createTemplate(new InputStreamReader(new BufferedInputStream(new FileInputStream(sourceTemplate)), config.getString(Keys.TEMPLATE_ENCODING))); - cachedTemplates.put(templateName, template); - } + + Template template = templateEngine.createTemplate(new InputStreamReader(new BufferedInputStream(new FileInputStream(sourceTemplate)), config.getString(Keys.TEMPLATE_ENCODING))); return template; } From b58f43da99abd8fb9012b432390901e365976133 Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 13 Mar 2015 17:30:21 +0100 Subject: [PATCH 6/7] fixed tags.tpl to create proper links --- src/test/groovy/org/jbake/app/RendererSpec.groovy | 2 +- src/test/resources/groovyMarkupTemplates/tags.tpl | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/groovy/org/jbake/app/RendererSpec.groovy b/src/test/groovy/org/jbake/app/RendererSpec.groovy index 98449bc6d..4bf3b15c2 100644 --- a/src/test/groovy/org/jbake/app/RendererSpec.groovy +++ b/src/test/groovy/org/jbake/app/RendererSpec.groovy @@ -293,7 +293,7 @@ class RendererSpec extends Specification { output.contains("blog<\/a>/ where: diff --git a/src/test/resources/groovyMarkupTemplates/tags.tpl b/src/test/resources/groovyMarkupTemplates/tags.tpl index 5b0f9d67d..807b6a5db 100644 --- a/src/test/resources/groovyMarkupTemplates/tags.tpl +++ b/src/test/resources/groovyMarkupTemplates/tags.tpl @@ -8,9 +8,7 @@ layout 'layout/main.tpl', div{ alltags.sort().each { tag -> span{ - a(href:"tags/${tag.replace(' ', '-')}.html", class:"label"){ - ${tag} - } + a(href:"tags/${tag.replace(' ', '-')}.html", class:"label", "${tag}") } } } From 2bc97b6a672257ec40c6001eb5277fffd01a2b3e Mon Sep 17 00:00:00 2001 From: Frank Becker Date: Fri, 13 Mar 2015 19:11:18 +0100 Subject: [PATCH 7/7] using createTemplateByPath to use MTP caching mechanism. createTemplateByPath is the preferred method to parse templates. see http://docs.groovy-lang.org/docs/next/html/documentation/template-engines.html#_creation_of_a_template_engine --- .../jbake/template/GroovyMarkupTemplateEngine.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java index e9b85ae4e..fe1445438 100644 --- a/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java +++ b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java @@ -31,7 +31,7 @@ public class GroovyMarkupTemplateEngine extends AbstractTemplateEngine { private TemplateConfiguration templateConfiguration; - private TemplateEngine templateEngine; + private MarkupTemplateEngine templateEngine; public GroovyMarkupTemplateEngine(final CompositeConfiguration config, final ContentStore db, final File destination, final File templatesPath) { super(config, db, destination, templatesPath); @@ -54,7 +54,7 @@ private void initializeTemplateEngine() { @Override public void renderDocument(final Map model, final String templateName, final Writer writer) throws RenderingException { try { - Template template = findTemplate(templateName); + Template template = templateEngine.createTemplateByPath(templateName); Map wrappedModel = wrap(model); Writable writable = template.make(wrappedModel); writable.writeTo(writer); @@ -63,13 +63,6 @@ public void renderDocument(final Map model, final String templat } } - private Template findTemplate(final String templateName) throws SAXException, ParserConfigurationException, ClassNotFoundException, IOException { - File sourceTemplate = new File(templatesPath, templateName); - - Template template = templateEngine.createTemplate(new InputStreamReader(new BufferedInputStream(new FileInputStream(sourceTemplate)), config.getString(Keys.TEMPLATE_ENCODING))); - return template; - } - private Map wrap(final Map model) { return new HashMap(model) { @Override