diff --git a/pom.xml b/pom.xml index aca2db795..ea8becbb5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,79 +1,81 @@ - - 4.0.0 + + 4.0.0 - - org.sonatype.oss - oss-parent - 7 - + + org.sonatype.oss + oss-parent + 7 + org.jbake jbake-core 2.5.0-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.2 - 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.2 + 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 + 2.4.1 1.7.6 1.1.1 1.7.0 @@ -82,239 +84,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 @@ -326,41 +360,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 @@ -372,7 +412,7 @@ groovy-templates ${groovy.version} true - + org.thymeleaf thymeleaf @@ -411,5 +451,5 @@ ${logback.version} true - + 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..fe1445438 --- /dev/null +++ b/src/main/java/org/jbake/template/GroovyMarkupTemplateEngine.java @@ -0,0 +1,128 @@ +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 TemplateConfiguration templateConfiguration; + private MarkupTemplateEngine 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 + public void renderDocument(final Map model, final String templateName, final Writer writer) throws RenderingException { + try { + Template template = templateEngine.createTemplateByPath(templateName); + Map wrappedModel = wrap(model); + Writable writable = template.make(wrappedModel); + writable.writeTo(writer); + } catch (Exception e) { + throw new RenderingException(e); + } + } + + 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/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 new file mode 100644 index 000000000..d9b349555 --- /dev/null +++ b/src/test/groovy/org/jbake/app/RendererSpec.groovy @@ -0,0 +1,335 @@ +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', + 'groovyMarkupTemplates': '.tpl', + 'thymeleafTemplates': '.thyme', + 'templates' : '.tfl' + ] + + File sourceFolder + File destinationFolder + CompositeConfiguration config + ContentStore db + Crawler crawler + + + def setup(){ + + setupFolders() + loadConfig() + + db = DBUtil.createDataStore("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.renderArchive(fileName); + + then: + def output = getOutput(fileName) + output.contains("blog<\/a>/ + + where: + + templateFolderName << templateMap.keySet() + templateSuffix << templateMap.keySet().collect { templateMap."$it" } + + } + @Unroll + def "should render Sitemap with tempalte Folder #templateFolderName and suffix #templateSuffix"(){ + given: + + DocumentTypes.addDocumentType("paper"); + DBUtil.updateSchema(db); + + String fileName = "sitemap.xml" + + crawlContent(templateSuffix) + def templateFolder = getTemplateFolder(templateFolderName) + def renderer = new Renderer(db, destinationFolder, templateFolder, config) + + when: + //exec + renderer.renderSitemap(fileName); + + then: + def 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("draft-paper.html"); + + where: + + templateFolderName << templateMap.keySet() + templateSuffix << templateMap.keySet().collect { templateMap."$it" } + + } + +} diff --git a/src/test/java/org/jbake/app/FreemarkerRendererTest.java b/src/test/java/org/jbake/app/FreemarkerRendererTest.java index 21c8aec54..441425165 100644 --- a/src/test/java/org/jbake/app/FreemarkerRendererTest.java +++ b/src/test/java/org/jbake/app/FreemarkerRendererTest.java @@ -1,26 +1,3 @@ -/* - * 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; import java.io.File; diff --git a/src/test/java/org/jbake/app/RendererTest.java b/src/test/java/org/jbake/app/RendererTest.java index 1f75745f1..ff8cb5eb5 100644 --- a/src/test/java/org/jbake/app/RendererTest.java +++ b/src/test/java/org/jbake/app/RendererTest.java @@ -3,16 +3,11 @@ 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; @@ -20,6 +15,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import static org.assertj.core.api.Assertions.*; public class RendererTest { diff --git a/src/test/java/org/jbake/app/template/AbstractTemplateEngineRenderingTest.java b/src/test/java/org/jbake/app/template/AbstractTemplateEngineRenderingTest.java index 610ae37ae..fb1d09066 100644 --- a/src/test/java/org/jbake/app/template/AbstractTemplateEngineRenderingTest.java +++ b/src/test/java/org/jbake/app/template/AbstractTemplateEngineRenderingTest.java @@ -244,5 +244,6 @@ public void renderSitemap() throws Exception { private List getOutputStrings(String type) { return outputStrings.get(type); + } } 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..807b6a5db --- /dev/null +++ b/src/test/resources/groovyMarkupTemplates/tags.tpl @@ -0,0 +1,41 @@ +layout 'layout/main.tpl', + bodyContents: contents { + + div(class:"row-fluid marketing"){ + + div(class:"span12"){ + h1("Taglist") + div{ + alltags.sort().each { tag -> + span{ + a(href:"tags/${tag.replace(' ', '-')}.html", class:"label", "${tag}") + } + } + } + } + + div(class:"span12"){ + h2('Tags') + def last_month + + tag_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 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/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/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 + + + 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