From c77dd86301b251af53dac40d61d9d5cf770a680e Mon Sep 17 00:00:00 2001 From: Serbroda Date: Tue, 17 Oct 2017 21:30:29 +0200 Subject: [PATCH 01/39] Update version --- pom.xml | 94 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index 7a27ace..0e8ab61 100644 --- a/pom.xml +++ b/pom.xml @@ -1,47 +1,47 @@ - - - 4.0.0 - - de.morphbit - thymeleaf-component-dialect - 0.0.3-alpha-SNAPSHOT - jar - - thymeleaf-component-dialect - Thymeleaf Layout Dialect - - - UTF-8 - UTF-8 - 1.8 - 1.8 - 1.8 - - - - - org.thymeleaf - thymeleaf - 3.0.7.RELEASE - - - - - - - true - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar-no-fork - - - - - - - + + + 4.0.0 + + de.morphbit + thymeleaf-component-dialect + 0.0.4-alpha-SNAPSHOT + jar + + thymeleaf-component-dialect + Thymeleaf Layout Dialect + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + org.thymeleaf + thymeleaf + 3.0.7.RELEASE + + + + + + + true + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + + jar-no-fork + + + + + + + From 4cff18d8ccac1a40f204172e2e7d1e46b75eabf2 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 09:20:51 +0200 Subject: [PATCH 02/39] Rename variables --- .../ComponentNamedElementProcessor.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java index 6922057..7c9f714 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java @@ -73,27 +73,27 @@ public ComponentNamedElementProcessor(final String dialectPrefix, protected void doProcess(ITemplateContext context, IModel model, IElementModelStructureHandler structureHandler) { IProcessableElementTag tag = processElementTag(context, model); - Map attrMap = processAttribute(tag); + Map attributes = processAttribute(tag); - String param = attrMap.get("params"); + String param = attributes.get("params"); - IModel base = model.cloneModel(); - base.remove(0); + IModel componentModel = model.cloneModel(); + componentModel.remove(0); - if (base.size() > 1) { - base.remove(base.size() - 1); + if (componentModel.size() > 1) { + componentModel.remove(componentModel.size() - 1); } - IModel frag = FragmentHelper.getFragmentModel(context, + IModel fragmentModel = FragmentHelper.getFragmentModel(context, fragmentName + (param == null ? "" : "(" + param + ")"), structureHandler, StandardDialect.PREFIX, FRAGMENT_ATTRIBUTE); model.reset(); - IModel replaced = replaceAllAttributeValues(attrMap, context, frag); - model.addModel(mergeModels(replaced, base, REPLACE_CONTENT_TAG)); + IModel replacedFragmentModel = replaceAllAttributeValues(attributes, context, fragmentModel); + model.addModel(mergeModels(replacedFragmentModel, componentModel, REPLACE_CONTENT_TAG)); - processVariables(attrMap, context, structureHandler, excludeAttributes); + processVariables(attributes, context, structureHandler, excludeAttributes); } private IProcessableElementTag processElementTag(ITemplateContext context, @@ -113,36 +113,36 @@ private boolean locationMatches(ITemplateEvent a, ITemplateEvent b) { && Objects.equals(a.getCol(), b.getCol()); } - private void processVariables(Map attrMap, + private void processVariables(Map attributes, ITemplateContext context, IElementModelStructureHandler structureHandler, Set excludeAttr) { - for (Map.Entry entry : attrMap.entrySet()) { + for (Map.Entry entry : attributes.entrySet()) { if (excludeAttr.contains(entry.getKey()) || isDynamicAttribute( entry.getKey(), this.getDialectPrefix())) { continue; } - String val = entry.getValue(); - if (val == null) { - val = "${true}"; + String attributeValue = entry.getValue(); + if (attributeValue == null) { + attributeValue = "${true}"; } - WithHelper.processWith(context, entry.getKey() + "=" + val, + WithHelper.processWith(context, entry.getKey() + "=" + attributeValue, structureHandler); } } private Map processAttribute(IProcessableElementTag tag) { - Map attMap = new HashMap<>(); + Map attributes = new HashMap<>(); if (tag != null) { for (final IAttribute attribute : tag.getAllAttributes()) { String completeName = attribute.getAttributeCompleteName(); if (!isDynamicAttribute(completeName, StandardDialect.PREFIX)) { - attMap.put(completeName, attribute.getValue()); + attributes.put(completeName, attribute.getValue()); } } } - return attMap; + return attributes; } private boolean isDynamicAttribute(String attribute, String prefix) { @@ -159,7 +159,7 @@ private IModel mergeModels(IModel base, IModel insert, String replaceTag) { private IModel insertModel(IModel base, IModel insert, String replaceTag) { IModel clonedModel = base.cloneModel(); - int index = findTag(base, replaceTag, IElementTag.class); + int index = findTagIndex(base, replaceTag, IElementTag.class); if (index > -1) { clonedModel.insertModel(index, insert); } @@ -168,14 +168,14 @@ private IModel insertModel(IModel base, IModel insert, String replaceTag) { private IModel removeTag(IModel model, final String tag) { IModel clonedModel = model.cloneModel(); - int index = findTag(model, tag, IElementTag.class); + int index = findTagIndex(model, tag, IElementTag.class); if (index > -1) { clonedModel.remove(index); } return clonedModel; } - private int findTag(IModel model, final String search, Class clazz) { + private int findTagIndex(IModel model, final String search, Class clazz) { int size = model.size(); ITemplateEvent event = null; for (int i = 0; i < size; i++) { From 3f34d9ab277faa6828c0ec5075b9c37059518b61 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 14:51:24 +0200 Subject: [PATCH 03/39] Delete unused file --- src/main/resources/application.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/resources/application.yml diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml deleted file mode 100644 index e69de29..0000000 From e62ee8f47d1c1f838b68847bab5f4eb4a9e7945e Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:26:01 +0200 Subject: [PATCH 04/39] Add junit dependency --- pom.xml | 100 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index 0e8ab61..9d6e614 100644 --- a/pom.xml +++ b/pom.xml @@ -1,47 +1,53 @@ - - - 4.0.0 - - de.morphbit - thymeleaf-component-dialect - 0.0.4-alpha-SNAPSHOT - jar - - thymeleaf-component-dialect - Thymeleaf Layout Dialect - - - UTF-8 - UTF-8 - 1.8 - 1.8 - 1.8 - - - - - org.thymeleaf - thymeleaf - 3.0.7.RELEASE - - - - - - - true - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar-no-fork - - - - - - - + + + 4.0.0 + + de.morphbit + thymeleaf-component-dialect + 0.0.4-alpha-SNAPSHOT + jar + + thymeleaf-component-dialect + Thymeleaf Layout Dialect + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + org.thymeleaf + thymeleaf + 3.0.7.RELEASE + + + junit + junit + 4.12 + test + + + + + + + true + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + + jar-no-fork + + + + + + + From a3095859a16d74f4b32356a986d7913fea3f7f63 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:29:56 +0200 Subject: [PATCH 05/39] Remove 'Web' from gitignore and add test classes and resources --- .gitignore | 13 ------------- src/test/resources/templates/components/link.html | 15 +++++++++++++++ src/test/resources/templates/index.html | 11 +++++++++++ 3 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 src/test/resources/templates/components/link.html create mode 100644 src/test/resources/templates/index.html diff --git a/.gitignore b/.gitignore index d3153ad..bc01af2 100644 --- a/.gitignore +++ b/.gitignore @@ -198,17 +198,4 @@ buildNumber.properties # Project-level settings /.tgitconfig -### Web ### -*.asp -*.cer -*.csr -*.css -*.htm -*.html -*.js -*.jsp -*.php -*.rss -*.xhtml - # End of https://www.gitignore.io/api/web,git,java,maven,eclipse,tortoisegit,intellij+all,intellij+iml diff --git a/src/test/resources/templates/components/link.html b/src/test/resources/templates/components/link.html new file mode 100644 index 0000000..e5d6c0c --- /dev/null +++ b/src/test/resources/templates/components/link.html @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/templates/index.html b/src/test/resources/templates/index.html new file mode 100644 index 0000000..0f10976 --- /dev/null +++ b/src/test/resources/templates/index.html @@ -0,0 +1,11 @@ + + + + Test + + + + + \ No newline at end of file From 7728aa97112c4b4ee7c1059b3579314bb50f2cd3 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:30:21 +0200 Subject: [PATCH 06/39] Add tests --- ...AbstractThymeleafComponentDialectTest.java | 31 ++++++++++++++++++ .../StandardThymeleafComponentParserTest.java | 32 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java diff --git a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java new file mode 100644 index 0000000..138fefa --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java @@ -0,0 +1,31 @@ +package de.morphbit.thymeleaf.base; + +import org.junit.BeforeClass; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; + +import de.morphbit.thymeleaf.dialect.ComponentDialect; + +public class AbstractThymeleafComponentDialectTest { + + private static TemplateEngine templateEngine; + + @BeforeClass + public static void beforeClass() { + setupThymeleaf(); + } + + private static void setupThymeleaf() { + ClassLoaderTemplateResolver templateResolver = + new ClassLoaderTemplateResolver(); + templateResolver.setCacheable(false); + templateResolver.setCharacterEncoding("UTF-8"); + templateResolver.setTemplateMode(TemplateMode.HTML); + + templateEngine = new TemplateEngine(); + templateEngine.setTemplateResolver(templateResolver); + final ComponentDialect dialect = new ComponentDialect(); + templateEngine.addDialect(dialect.getPrefix(), dialect); + } +} diff --git a/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java b/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java new file mode 100644 index 0000000..b386f36 --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java @@ -0,0 +1,32 @@ +package de.morphbit.thymeleaf.parser; + +import static org.junit.Assert.assertTrue; + +import java.util.Set; + +import org.junit.Test; + +import de.morphbit.thymeleaf.model.ThymeleafComponent; + +public class StandardThymeleafComponentParserTest { + + @Test + public void testParser() { + final StandardThymeleafComponentParser parser = + new StandardThymeleafComponentParser("templates/", ".html", + "components"); + Set components = parser.parse(); + assertTrue(!components.isEmpty()); + assertTrue(containsComponent(components, "link")); + } + + private boolean containsComponent(final Set components, + final String name) { + for (ThymeleafComponent component : components) { + if (component.getName().equalsIgnoreCase(name)) { + return true; + } + } + return false; + } +} From 47db14553bd231afc453501e32922adaa7104413 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:32:21 +0200 Subject: [PATCH 07/39] Remame file --- .../templates/components/{link.html => link-component.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/resources/templates/components/{link.html => link-component.html} (100%) diff --git a/src/test/resources/templates/components/link.html b/src/test/resources/templates/components/link-component.html similarity index 100% rename from src/test/resources/templates/components/link.html rename to src/test/resources/templates/components/link-component.html From 67ee08057f72226cc418993a1e25ad3a13f0b710 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:37:38 +0200 Subject: [PATCH 08/39] Add html that doesn't contain a component --- .../templates/components/no-component.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/resources/templates/components/no-component.html diff --git a/src/test/resources/templates/components/no-component.html b/src/test/resources/templates/components/no-component.html new file mode 100644 index 0000000..c1fdac8 --- /dev/null +++ b/src/test/resources/templates/components/no-component.html @@ -0,0 +1,13 @@ + + + + + + +
+ +
+ + \ No newline at end of file From 4ad359f3036d402c5eb72f0ff8fc2f69e10d50c8 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:37:49 +0200 Subject: [PATCH 09/39] Add named component --- .../resources/templates/components/link-component.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/resources/templates/components/link-component.html b/src/test/resources/templates/components/link-component.html index e5d6c0c..d901ade 100644 --- a/src/test/resources/templates/components/link-component.html +++ b/src/test/resources/templates/components/link-component.html @@ -11,5 +11,14 @@ Test set. Value is + + + \ No newline at end of file From 8df3a5f2d782ae2de781f5a75b8a78fd7b816554 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 15:38:00 +0200 Subject: [PATCH 10/39] Add assertions --- .../parser/StandardThymeleafComponentParserTest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java b/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java index b386f36..d215694 100644 --- a/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java +++ b/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java @@ -18,6 +18,10 @@ public void testParser() { Set components = parser.parse(); assertTrue(!components.isEmpty()); assertTrue(containsComponent(components, "link")); + assertTrue(containsComponent(components, "link-named")); + assertTrue(notContainsComponent(components, "link2")); + assertTrue(notContainsComponent(components, "no-component")); + assertTrue(notContainsComponent(components, "link-component")); } private boolean containsComponent(final Set components, @@ -29,4 +33,9 @@ private boolean containsComponent(final Set components, } return false; } + + private boolean notContainsComponent( + final Set components, final String name) { + return !containsComponent(components, name); + } } From 91d08ffcc39995ae6be52cc87867b6effc7a1eb2 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 16:00:37 +0200 Subject: [PATCH 11/39] Rename file --- .../resources/templates/{index.html => link-component-test.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/resources/templates/{index.html => link-component-test.html} (100%) diff --git a/src/test/resources/templates/index.html b/src/test/resources/templates/link-component-test.html similarity index 100% rename from src/test/resources/templates/index.html rename to src/test/resources/templates/link-component-test.html From cfbe8f121f3f7f7019ea2463eb24efb1f1c9082a Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 16:25:33 +0200 Subject: [PATCH 12/39] Complete configuration --- .../base/AbstractThymeleafComponentDialectTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java index 138fefa..92337c7 100644 --- a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java +++ b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java @@ -2,13 +2,17 @@ import org.junit.BeforeClass; import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; import org.thymeleaf.templatemode.TemplateMode; import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; import de.morphbit.thymeleaf.dialect.ComponentDialect; +import de.morphbit.thymeleaf.parser.StandardThymeleafComponentParser; public class AbstractThymeleafComponentDialectTest { + private static final String BASE_PATH = "templates"; + private static TemplateEngine templateEngine; @BeforeClass @@ -16,16 +20,25 @@ public static void beforeClass() { setupThymeleaf(); } + protected String processThymeleafFile(String fileName, Context context) { + return templateEngine.process(BASE_PATH + "/" + fileName, context); + } + private static void setupThymeleaf() { ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setCacheable(false); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); + templateResolver.setSuffix(".html"); templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); final ComponentDialect dialect = new ComponentDialect(); + final StandardThymeleafComponentParser parser = + new StandardThymeleafComponentParser("", ".html", + "templates/components"); + dialect.addParser(parser); templateEngine.addDialect(dialect.getPrefix(), dialect); } } From 3123ca0d0f2d31a0e3f9a8754732ba1b9d41b5d1 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 16:30:06 +0200 Subject: [PATCH 13/39] Fix for test --- .../resources/templates/components/link-component.html | 10 +++------- src/test/resources/templates/link-component-test.html | 6 +++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/resources/templates/components/link-component.html b/src/test/resources/templates/components/link-component.html index d901ade..27ff513 100644 --- a/src/test/resources/templates/components/link-component.html +++ b/src/test/resources/templates/components/link-component.html @@ -4,19 +4,15 @@ -
- - + -
+ diff --git a/src/test/resources/templates/link-component-test.html b/src/test/resources/templates/link-component-test.html index 0f10976..eac41ba 100644 --- a/src/test/resources/templates/link-component-test.html +++ b/src/test/resources/templates/link-component-test.html @@ -6,6 +6,10 @@ Test - + + + Test + + \ No newline at end of file From 41b3764df84d962514da04f951cb59820c071394 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 16:30:14 +0200 Subject: [PATCH 14/39] Add component test --- .../thymeleaf/dialect/ComponentTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java new file mode 100644 index 0000000..bebb7e7 --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java @@ -0,0 +1,20 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class ComponentTest extends AbstractThymeleafComponentDialectTest { + + private static final String FILE = "link-component-test.html"; + + @Test + public void test() { + String html = processThymeleafFile(FILE, new Context()); + System.out.println(html); + assertNotNull(html); + } +} From e1989eb7a5860e358476a7de2071cfcec2c2e68c Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 16:33:35 +0200 Subject: [PATCH 15/39] Add assertions --- .../java/de/morphbit/thymeleaf/dialect/ComponentTest.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java index bebb7e7..65a48b9 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java @@ -1,6 +1,7 @@ package de.morphbit.thymeleaf.dialect; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import org.junit.Test; import org.thymeleaf.context.Context; @@ -14,7 +15,11 @@ public class ComponentTest extends AbstractThymeleafComponentDialectTest { @Test public void test() { String html = processThymeleafFile(FILE, new Context()); - System.out.println(html); + assertNotNull(html); + assertTrue(!html.contains("tc:link")); + assertTrue(!html.contains("tc:content")); + assertTrue(html.contains("")); + assertTrue(html.contains("Test")); } } From c560b3a093fa40d9e571afa394a8b1ccf82036fe Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 16:37:06 +0200 Subject: [PATCH 16/39] Make class abstract --- .../thymeleaf/base/AbstractThymeleafComponentDialectTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java index 92337c7..7118213 100644 --- a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java +++ b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java @@ -9,7 +9,7 @@ import de.morphbit.thymeleaf.dialect.ComponentDialect; import de.morphbit.thymeleaf.parser.StandardThymeleafComponentParser; -public class AbstractThymeleafComponentDialectTest { +public abstract class AbstractThymeleafComponentDialectTest { private static final String BASE_PATH = "templates"; From 6e0dee7180a1e9c6c0cab74a8dbd4c7c21123f5b Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 17:12:30 +0200 Subject: [PATCH 17/39] Rename html files --- .../java/de/morphbit/thymeleaf/dialect/ComponentTest.java | 2 +- .../parser/StandardThymeleafComponentParserTest.java | 4 ++-- .../components/{link-component.html => link_component.html} | 0 .../components/{no-component.html => no_component.html} | 0 ...k-component-test.html => simple_content_replace_test.html} | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename src/test/resources/templates/components/{link-component.html => link_component.html} (100%) rename src/test/resources/templates/components/{no-component.html => no_component.html} (100%) rename src/test/resources/templates/{link-component-test.html => simple_content_replace_test.html} (100%) diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java index 65a48b9..d9a8a82 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java @@ -10,7 +10,7 @@ public class ComponentTest extends AbstractThymeleafComponentDialectTest { - private static final String FILE = "link-component-test.html"; + private static final String FILE = "simple_content_replace_test.html"; @Test public void test() { diff --git a/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java b/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java index d215694..7688b81 100644 --- a/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java +++ b/src/test/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParserTest.java @@ -20,8 +20,8 @@ public void testParser() { assertTrue(containsComponent(components, "link")); assertTrue(containsComponent(components, "link-named")); assertTrue(notContainsComponent(components, "link2")); - assertTrue(notContainsComponent(components, "no-component")); - assertTrue(notContainsComponent(components, "link-component")); + assertTrue(notContainsComponent(components, "no_component")); + assertTrue(notContainsComponent(components, "link_component")); } private boolean containsComponent(final Set components, diff --git a/src/test/resources/templates/components/link-component.html b/src/test/resources/templates/components/link_component.html similarity index 100% rename from src/test/resources/templates/components/link-component.html rename to src/test/resources/templates/components/link_component.html diff --git a/src/test/resources/templates/components/no-component.html b/src/test/resources/templates/components/no_component.html similarity index 100% rename from src/test/resources/templates/components/no-component.html rename to src/test/resources/templates/components/no_component.html diff --git a/src/test/resources/templates/link-component-test.html b/src/test/resources/templates/simple_content_replace_test.html similarity index 100% rename from src/test/resources/templates/link-component-test.html rename to src/test/resources/templates/simple_content_replace_test.html From 544414316e6b1a1ec1342db82f22391645848726 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 17:18:21 +0200 Subject: [PATCH 18/39] Rename files --- .../dialect/{ComponentTest.java => ContentReplaceTest.java} | 6 +++--- src/test/resources/templates/components/link_component.html | 1 + ...ple_content_replace_test.html => link_with_content.html} | 0 3 files changed, 4 insertions(+), 3 deletions(-) rename src/test/java/de/morphbit/thymeleaf/dialect/{ComponentTest.java => ContentReplaceTest.java} (73%) rename src/test/resources/templates/{simple_content_replace_test.html => link_with_content.html} (100%) diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java similarity index 73% rename from src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java rename to src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java index d9a8a82..0a54552 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java @@ -8,12 +8,12 @@ import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; -public class ComponentTest extends AbstractThymeleafComponentDialectTest { +public class ContentReplaceTest extends AbstractThymeleafComponentDialectTest { - private static final String FILE = "simple_content_replace_test.html"; + private static final String FILE = "link_with_content.html"; @Test - public void test() { + public void itShouldNotRenderNamespaceTagsAndReplaceContent() { String html = processThymeleafFile(FILE, new Context()); assertNotNull(html); diff --git a/src/test/resources/templates/components/link_component.html b/src/test/resources/templates/components/link_component.html index 27ff513..f0d857f 100644 --- a/src/test/resources/templates/components/link_component.html +++ b/src/test/resources/templates/components/link_component.html @@ -6,6 +6,7 @@ diff --git a/src/test/resources/templates/simple_content_replace_test.html b/src/test/resources/templates/link_with_content.html similarity index 100% rename from src/test/resources/templates/simple_content_replace_test.html rename to src/test/resources/templates/link_with_content.html From 2c2e6cef72351de0067c89772c26c9dfa249e464 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 17:24:43 +0200 Subject: [PATCH 19/39] Add test --- .../thymeleaf/dialect/ContentReplaceTest.java | 20 +++++++++++++++++-- .../templates/components/link_component.html | 2 +- .../link_with_content_and_variable.html | 15 ++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/templates/link_with_content_and_variable.html diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java index 0a54552..37c8fb1 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java @@ -10,16 +10,32 @@ public class ContentReplaceTest extends AbstractThymeleafComponentDialectTest { - private static final String FILE = "link_with_content.html"; + private static final String FILE_LINK_WITH_CONTENT = + "link_with_content.html"; + private static final String FILE_LINK_WITH_CONTENT_AND_VARIABLE = + "link_with_content_and_variable.html"; @Test public void itShouldNotRenderNamespaceTagsAndReplaceContent() { - String html = processThymeleafFile(FILE, new Context()); + String html = + processThymeleafFile(FILE_LINK_WITH_CONTENT, new Context()); assertNotNull(html); assertTrue(!html.contains("tc:link")); assertTrue(!html.contains("tc:content")); assertTrue(html.contains("")); assertTrue(html.contains("Test")); + assertTrue(!html.contains(">> ")); + } + + @Test + public void itShouldNotRenderNamespaceTagsAndReplaceContentAndConsiderVariable() { + String html = processThymeleafFile(FILE_LINK_WITH_CONTENT_AND_VARIABLE, + new Context()); + + assertNotNull(html); + assertTrue(html.contains("")); + assertTrue(html.contains("Test")); + assertTrue(html.contains(">> ")); } } diff --git a/src/test/resources/templates/components/link_component.html b/src/test/resources/templates/components/link_component.html index f0d857f..22f6651 100644 --- a/src/test/resources/templates/components/link_component.html +++ b/src/test/resources/templates/components/link_component.html @@ -6,7 +6,7 @@ diff --git a/src/test/resources/templates/link_with_content_and_variable.html b/src/test/resources/templates/link_with_content_and_variable.html new file mode 100644 index 0000000..7c47ef8 --- /dev/null +++ b/src/test/resources/templates/link_with_content_and_variable.html @@ -0,0 +1,15 @@ + + + + Test + + + + + Test + + + + \ No newline at end of file From fd8e469736209d6a9d098b8a0e926e4d3d593ec1 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 17:25:09 +0200 Subject: [PATCH 20/39] Rename test --- .../java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java index 37c8fb1..c38d830 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java @@ -29,7 +29,7 @@ public void itShouldNotRenderNamespaceTagsAndReplaceContent() { } @Test - public void itShouldNotRenderNamespaceTagsAndReplaceContentAndConsiderVariable() { + public void itShouldReplaceContentAndConsiderVariable() { String html = processThymeleafFile(FILE_LINK_WITH_CONTENT_AND_VARIABLE, new Context()); From fa14f1f382282ed46a56706ea5642b153d4e7c35 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Wed, 18 Oct 2017 17:44:31 +0200 Subject: [PATCH 21/39] Add test --- .../dialect/AttributeReplaceTest.java | 47 +++++++++++++++++++ .../templates/components/valid_input.html | 22 +++++++++ src/test/resources/templates/repl_test.html | 15 ++++++ 3 files changed, 84 insertions(+) create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java create mode 100644 src/test/resources/templates/components/valid_input.html create mode 100644 src/test/resources/templates/repl_test.html diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java new file mode 100644 index 0000000..8ad1d1e --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java @@ -0,0 +1,47 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.Locale; + +import org.junit.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class AttributeReplaceTest + extends AbstractThymeleafComponentDialectTest { + + private static final String FILE = "repl_test.html"; + + public static class User { + + private String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + @Test + public void itShouldReplaceAllReplAttributes() { + String html = processThymeleafFile(FILE, new Context(Locale.ENGLISH, + Collections.singletonMap("user", new User("John")))); + + System.out.println(html); + assertNotNull(html); + assertTrue(!html.matches(".*\\?\\[([\\w|\\d|.|\\-|_]*)\\].*")); + } + +} diff --git a/src/test/resources/templates/components/valid_input.html b/src/test/resources/templates/components/valid_input.html new file mode 100644 index 0000000..8ddfbea --- /dev/null +++ b/src/test/resources/templates/components/valid_input.html @@ -0,0 +1,22 @@ + + + + + + +
+ + + + + + + + +
+ + + \ No newline at end of file diff --git a/src/test/resources/templates/repl_test.html b/src/test/resources/templates/repl_test.html new file mode 100644 index 0000000..5d28802 --- /dev/null +++ b/src/test/resources/templates/repl_test.html @@ -0,0 +1,15 @@ + + + + Test + + + +
+ + + + + \ No newline at end of file From 0b3293835432d1a7b57bbb4da546bc8f70d8965f Mon Sep 17 00:00:00 2001 From: Serbroda Date: Wed, 18 Oct 2017 20:50:41 +0200 Subject: [PATCH 22/39] Remove spring specific methods --- .../dialect/AttributeReplaceTest.java | 93 +++++++++---------- .../templates/components/valid_input.html | 36 +++---- 2 files changed, 61 insertions(+), 68 deletions(-) diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java index 8ad1d1e..68e0376 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java @@ -1,47 +1,46 @@ -package de.morphbit.thymeleaf.dialect; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Collections; -import java.util.Locale; - -import org.junit.Test; -import org.thymeleaf.context.Context; - -import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; - -public class AttributeReplaceTest - extends AbstractThymeleafComponentDialectTest { - - private static final String FILE = "repl_test.html"; - - public static class User { - - private String name; - - public User(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - } - - @Test - public void itShouldReplaceAllReplAttributes() { - String html = processThymeleafFile(FILE, new Context(Locale.ENGLISH, - Collections.singletonMap("user", new User("John")))); - - System.out.println(html); - assertNotNull(html); - assertTrue(!html.matches(".*\\?\\[([\\w|\\d|.|\\-|_]*)\\].*")); - } - -} +package de.morphbit.thymeleaf.dialect; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.Locale; + +import org.junit.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class AttributeReplaceTest + extends AbstractThymeleafComponentDialectTest { + + private static final String FILE = "repl_test.html"; + + public static class User { + + private String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + @Test + public void itShouldReplaceAllReplAttributes() { + String html = processThymeleafFile(FILE, new Context(Locale.ENGLISH, + Collections.singletonMap("user", new User("John")))); + + assertNotNull(html); + assertTrue(!html.matches(".*\\?\\[([\\w|\\d|.|\\-|_]*)\\].*")); + } + +} diff --git a/src/test/resources/templates/components/valid_input.html b/src/test/resources/templates/components/valid_input.html index 8ddfbea..9fc1069 100644 --- a/src/test/resources/templates/components/valid_input.html +++ b/src/test/resources/templates/components/valid_input.html @@ -1,22 +1,16 @@ - - - - - - -
- - - - - - - - -
- - + + + + + + +
+ + +
+ + \ No newline at end of file From 843553651ca87c55efcb924b4bb31142e36ea1ed Mon Sep 17 00:00:00 2001 From: Serbroda Date: Wed, 18 Oct 2017 21:18:35 +0200 Subject: [PATCH 23/39] Add OnceAttributeTest --- .../thymeleaf/dialect/OnceAttributeTest.java | 38 +++++++++++++++++++ .../templates/components/once_component.html | 18 +++++++++ src/test/resources/templates/once_test.html | 18 +++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java create mode 100644 src/test/resources/templates/components/once_component.html create mode 100644 src/test/resources/templates/once_test.html diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java new file mode 100644 index 0000000..0aaf83a --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java @@ -0,0 +1,38 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class OnceAttributeTest extends AbstractThymeleafComponentDialectTest { + + private static final String FILE = "once_test.html"; + + @Test + public void itShouldHaveMultipleComponentsButOneScript() { + String html = processThymeleafFile(FILE, new Context()); + + assertNotNull(html); + assertTrue(countMatches( + "\\ + + +
+ + + \ No newline at end of file diff --git a/src/test/resources/templates/once_test.html b/src/test/resources/templates/once_test.html new file mode 100644 index 0000000..fd58b83 --- /dev/null +++ b/src/test/resources/templates/once_test.html @@ -0,0 +1,18 @@ + + + + Test + + + + + + + + + + + + \ No newline at end of file From 3a7178d256970cf85aa9d28e2fe0a48cc504d045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Amorim=20Brand=C3=A3o=20da=20Silva?= Date: Fri, 2 Mar 2018 18:14:31 +0000 Subject: [PATCH 24/39] Fixed issue with "NullPointerException" after building into .jar. This was caused by the resource lookup process, which would only work if the files were organized into directories. When packaged into a jar, the "new File(path).listFiles()" would throw the NullPointerException would occur. This addition has the disadvantage of requiring the "org.springframework.spring-core" dependency, in order to be able to use the PathMatchingResourcePatternResolver class. --- pom.xml | 5 + .../thymeleaf/helper/ResourcePathFinder.java | 99 ++++++++++--------- 2 files changed, 55 insertions(+), 49 deletions(-) diff --git a/pom.xml b/pom.xml index 9d6e614..28b0d37 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,11 @@ 4.12 test + + org.springframework + spring-core + 4.3.9.RELEASE + diff --git a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java index 303ed33..c8a5bcc 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java @@ -1,12 +1,12 @@ -/* +/* * Copyright 2017, Danny Rottstegge - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,59 +16,60 @@ package de.morphbit.thymeleaf.helper; -import java.io.File; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +import java.io.*; import java.net.URL; import java.util.ArrayList; import java.util.List; public class ResourcePathFinder { - private final String directory; - private final ClassLoader loader; + private final String directory; + private final ClassLoader loader; + + /** + * Constructor + * + * @param directory + * Base directory to search resource files (e.g. + * templates/components) + */ + public ResourcePathFinder(String directory) { + this.directory = directory; + this.loader = Thread.currentThread().getContextClassLoader(); + } + + /** + * Searches for resource files + * + * @param recursively + * Search files recursively + * @return List of files as strings + */ + public List findResourceFiles(boolean recursively) { + return getResourceFiles(directory, recursively); + } - /** - * Constructor - * - * @param directory - * Base directory to search resource files (e.g. - * templates/components) - */ - public ResourcePathFinder(String directory) { - this.directory = directory; - this.loader = Thread.currentThread().getContextClassLoader(); - } + private List getResourceFiles(String dir, boolean recursively) + { + List files = new ArrayList<>(); + try{ + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader); + Resource[] resources = resolver.getResources("classpath*:/"+ dir + "/**/*.*"); + String basePath = loader.getResource(dir).getPath(); + for (Resource resource: resources){ - /** - * Searches for resource files - * - * @param recursively - * Search files recursively - * @return List of files as strings - */ - public List findResourceFiles(boolean recursively) { - return getResourceFiles(directory, new ArrayList<>(), recursively); - } + String pathRelativeToDir = dir + "/" + resource.getURL().getPath().replace(basePath + "/", ""); + files.add(pathRelativeToDir); + } - private List getResourceFiles(String dir, List files, - boolean recursively) { - URL url = loader.getResource(dir); - String path = url.getPath(); - for (File file : new File(path).listFiles()) { - if (recursively && file.isDirectory()) { - return getResourceFiles(concatPath(dir, file.getName()), files, - recursively); - } else { - files.add(concatPath(dir, file.getName())); - } - } - return files; - } + }catch (IOException ex){ + System.err.println("Could not process resource pattern."); + } - private String concatPath(String path1, String path2) { - if (path1 == null) { - return path2; - } - return path1.replaceAll("[/|\\\\]*$", "") + "/" - + path2.replaceAll("^[/|\\\\]*", ""); - } + return files; + } } From 4f925202d8dc4e9a31fe57c6390a86e5a7015c7d Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 9 Mar 2018 16:34:02 +0100 Subject: [PATCH 25/39] Add quality gate badge to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fe14135..a94a617 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Thymeleaf Component Dialect [![Build Status](https://travis-ci.org/Serbroda/thymeleaf-component-dialect.svg?branch=develop)](https://travis-ci.org/Serbroda/thymeleaf-component-dialect) [![jitpack](https://jitpack.io/v/Serbroda/thymeleaf-component-dialect.svg)](https://jitpack.io/#Serbroda/thymeleaf-component-dialect) [![license](https://img.shields.io/github/license/Serbroda/thymeleaf-component-dialect.svg)](https://github.com/Serbroda/thymeleaf-component-dialect/blob/master/LICENSE.txt) +[![quality gate](https://sonarcloud.io/api/badges/gate?key=de.morphbit%3Athymeleaf-component-dialect%3Adevelop)](https://sonarcloud.io/dashboard?id=de.morphbit%3Athymeleaf-component-dialect%3Adevelop) + A dialect for creating reusable thymeleaf components. From 3d9ce8956845d839efded5981b80fc33b70f999c Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 9 Mar 2018 16:34:54 +0100 Subject: [PATCH 26/39] Sonar: Remove unused import java.net.URL --- .../thymeleaf/helper/ResourcePathFinder.java | 89 ++++++++++--------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java index c8a5bcc..5b58a54 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java @@ -16,60 +16,61 @@ package de.morphbit.thymeleaf.helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; -import java.io.*; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - public class ResourcePathFinder { - private final String directory; - private final ClassLoader loader; + private final String directory; + private final ClassLoader loader; - /** - * Constructor - * - * @param directory - * Base directory to search resource files (e.g. - * templates/components) - */ - public ResourcePathFinder(String directory) { - this.directory = directory; - this.loader = Thread.currentThread().getContextClassLoader(); - } + /** + * Constructor + * + * @param directory + * Base directory to search resource files (e.g. + * templates/components) + */ + public ResourcePathFinder(String directory) { + this.directory = directory; + this.loader = Thread.currentThread().getContextClassLoader(); + } - /** - * Searches for resource files - * - * @param recursively - * Search files recursively - * @return List of files as strings - */ - public List findResourceFiles(boolean recursively) { - return getResourceFiles(directory, recursively); - } + /** + * Searches for resource files + * + * @param recursively + * Search files recursively + * @return List of files as strings + */ + public List findResourceFiles(boolean recursively) { + return getResourceFiles(directory, recursively); + } - private List getResourceFiles(String dir, boolean recursively) - { - List files = new ArrayList<>(); - try{ - ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader); - Resource[] resources = resolver.getResources("classpath*:/"+ dir + "/**/*.*"); - String basePath = loader.getResource(dir).getPath(); - for (Resource resource: resources){ + private List getResourceFiles(String dir, boolean recursively) { + List files = new ArrayList<>(); + try { + ResourcePatternResolver resolver = + new PathMatchingResourcePatternResolver(loader); + Resource[] resources = + resolver.getResources("classpath*:/" + dir + "/**/*.*"); + String basePath = loader.getResource(dir).getPath(); + for (Resource resource : resources) { - String pathRelativeToDir = dir + "/" + resource.getURL().getPath().replace(basePath + "/", ""); - files.add(pathRelativeToDir); - } + String pathRelativeToDir = dir + "/" + resource.getURL() + .getPath().replace(basePath + "/", ""); + files.add(pathRelativeToDir); + } - }catch (IOException ex){ - System.err.println("Could not process resource pattern."); - } + } catch (IOException ex) { + System.err.println("Could not process resource pattern."); + } - return files; - } + return files; + } } From 9c5c7c3abf48af50fc097e2ba3da9818da626204 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 9 Mar 2018 16:36:36 +0100 Subject: [PATCH 27/39] Sonar: Remove unused parameter 'recursively' --- .../morphbit/thymeleaf/helper/ResourcePathFinder.java | 10 +++++----- .../parser/StandardThymeleafComponentParser.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java index 5b58a54..3a880e4 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java @@ -44,15 +44,15 @@ public ResourcePathFinder(String directory) { /** * Searches for resource files * - * @param recursively - * Search files recursively + * Search files recursively + * * @return List of files as strings */ - public List findResourceFiles(boolean recursively) { - return getResourceFiles(directory, recursively); + public List findResourceFiles() { + return getResourceFiles(directory); } - private List getResourceFiles(String dir, boolean recursively) { + private List getResourceFiles(String dir) { List files = new ArrayList<>(); try { ResourcePatternResolver resolver = diff --git a/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java b/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java index e0826c3..81aba52 100644 --- a/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java +++ b/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java @@ -60,7 +60,7 @@ public Set parse() { Set components = new HashSet<>(); for (String file : new ResourcePathFinder(templatePrefix + directory) - .findResourceFiles(true)) { + .findResourceFiles()) { for (Element element : parseElements(file)) { if (isThymeleafComponent(element)) { components.add(createComponent(element, file)); From ec7ac5cbcaa49702821076563266421176dcd34b Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Mon, 12 Mar 2018 15:42:47 +0100 Subject: [PATCH 28/39] Add comment --- pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pom.xml b/pom.xml index 28b0d37..2526bbf 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ 1.8 1.8 1.8 + 2.0.0.RELEASE @@ -30,6 +31,8 @@ 4.12 test + + org.springframework spring-core From 578eae45a3b0d65e959b35634e4b1f25dd80413f Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Mon, 12 Mar 2018 16:06:25 +0100 Subject: [PATCH 29/39] Add slf4j-api dependency --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index 2526bbf..06a5b58 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,13 @@ spring-core 4.3.9.RELEASE + + + + org.slf4j + slf4j-api + 1.7.25 + From c37045310b7690215a011ab3999dfd5af0114d79 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Mon, 12 Mar 2018 16:07:19 +0100 Subject: [PATCH 30/39] Use slf4j logger instead of System.out.println to log error --- .../de/morphbit/thymeleaf/helper/ResourcePathFinder.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java index 3a880e4..2a9635f 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java @@ -20,12 +20,17 @@ import java.util.ArrayList; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; public class ResourcePathFinder { + private static final Logger LOG = + LoggerFactory.getLogger(ResourcePathFinder.class); + private final String directory; private final ClassLoader loader; @@ -68,7 +73,7 @@ private List getResourceFiles(String dir) { } } catch (IOException ex) { - System.err.println("Could not process resource pattern."); + LOG.error("Could not process resource pattern. {}", ex); } return files; From a1d213a3f9b8b8c543d2688d04b56d50c70b0aed Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Mon, 12 Mar 2018 16:13:19 +0100 Subject: [PATCH 31/39] Sonar: Make return statement conditional --- .../thymeleaf/processor/ComponentNamedElementProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java index 7c9f714..519b85d 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java @@ -260,7 +260,9 @@ private String getReplaceAttributePart(String attributeValue) { Pattern pattern = Pattern.compile(".*\\?\\[([\\w|\\d|.|\\-|_]*)\\].*"); Matcher matcher = pattern.matcher(attributeValue); while (matcher.find()) { - return matcher.group(1); + if (matcher.group(1) != null && !matcher.group(1).isEmpty()) { + return matcher.group(1); + } } return null; } From 701c261544063e6e15211ea56ba6034ed462cedd Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Thu, 11 Oct 2018 11:57:58 +0200 Subject: [PATCH 32/39] Add possibility to register variables globally via parameter --- .../de/morphbit/thymeleaf/helper/WithHelper.java | 13 ++++++++++--- .../processor/ComponentNamedElementProcessor.java | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java b/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java index bb80bca..32e3f3c 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java @@ -20,7 +20,7 @@ private WithHelper() { public static void processWith(ITemplateContext context, String attributeValue, - IElementModelStructureHandler structureHandler) { + IElementModelStructureHandler structureHandler, boolean registerGlobal) { final AssignationSequence assignations = AssignationUtils.parseAssignationSequence(context, attributeValue, false /* no parameters without value */); @@ -30,6 +30,7 @@ public static void processWith(ITemplateContext context, + attributeValue + "\""); } + // Normally we would just allow the structure handler to be in charge of // declaring the local variables // by using structureHandler.setLocalVariable(...) but in this case we @@ -68,7 +69,13 @@ public static void processWith(ITemplateContext context, + leftExpr + "\""); } - if (engineContext != null) { + if(registerGlobal && engineContext != null) { + engineContext.setVariable(newVariableName, rightValue); + } else { + structureHandler.setLocalVariable(newVariableName, rightValue); + } + + /*if (engineContext != null) { // The advantage of this vs. using the structure handler is that // we will be able to // use this newly created value in other expressions in the same @@ -78,7 +85,7 @@ public static void processWith(ITemplateContext context, // The problem is, these won't be available until we execute the // next processor structureHandler.setLocalVariable(newVariableName, rightValue); - } + }*/ } } diff --git a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java index 519b85d..7b4adfe 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java @@ -127,7 +127,7 @@ private void processVariables(Map attributes, attributeValue = "${true}"; } WithHelper.processWith(context, entry.getKey() + "=" + attributeValue, - structureHandler); + structureHandler, false); } } From 1adb83c002e2c5fdcc72889b59a55ca31f62cc2b Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 12 Oct 2018 10:21:15 +0200 Subject: [PATCH 33/39] Replace keyword 'params' with 'tc:constructor' --- .../thymeleaf/processor/ComponentNamedElementProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java index 7b4adfe..da77c9e 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java @@ -49,7 +49,7 @@ public class ComponentNamedElementProcessor private static final int PRECEDENCE = 350; - private final Set excludeAttributes = singleton("params"); + private final Set excludeAttributes = singleton("tc:constructor"); private final String fragmentName; /** @@ -75,7 +75,7 @@ protected void doProcess(ITemplateContext context, IModel model, IProcessableElementTag tag = processElementTag(context, model); Map attributes = processAttribute(tag); - String param = attributes.get("params"); + String param = attributes.get("tc:constructor"); IModel componentModel = model.cloneModel(); componentModel.remove(0); From 691f2f49113aa64fb06ac71c538fdedae3ee13cc Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 12 Oct 2018 10:22:00 +0200 Subject: [PATCH 34/39] Rename varibale --- .../thymeleaf/processor/ComponentNamedElementProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java index da77c9e..c3ab764 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java @@ -75,7 +75,7 @@ protected void doProcess(ITemplateContext context, IModel model, IProcessableElementTag tag = processElementTag(context, model); Map attributes = processAttribute(tag); - String param = attributes.get("tc:constructor"); + String constructorParams = attributes.get("tc:constructor"); IModel componentModel = model.cloneModel(); componentModel.remove(0); @@ -85,7 +85,7 @@ protected void doProcess(ITemplateContext context, IModel model, } IModel fragmentModel = FragmentHelper.getFragmentModel(context, - fragmentName + (param == null ? "" : "(" + param + ")"), + fragmentName + (constructorParams == null ? "" : "(" + constructorParams + ")"), structureHandler, StandardDialect.PREFIX, FRAGMENT_ATTRIBUTE); model.reset(); From 601432a7f1b36ba78534825b510c7afd63389dd1 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 12 Oct 2018 10:37:39 +0200 Subject: [PATCH 35/39] Fix tests --- src/test/resources/templates/link_with_content.html | 2 +- .../resources/templates/link_with_content_and_variable.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/resources/templates/link_with_content.html b/src/test/resources/templates/link_with_content.html index eac41ba..ca500ef 100644 --- a/src/test/resources/templates/link_with_content.html +++ b/src/test/resources/templates/link_with_content.html @@ -7,7 +7,7 @@ - + Test diff --git a/src/test/resources/templates/link_with_content_and_variable.html b/src/test/resources/templates/link_with_content_and_variable.html index 7c47ef8..9491016 100644 --- a/src/test/resources/templates/link_with_content_and_variable.html +++ b/src/test/resources/templates/link_with_content_and_variable.html @@ -7,7 +7,7 @@ - + Test From c8c9429f99ee6341627583027d758ad64c445618 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 12 Oct 2018 10:57:24 +0200 Subject: [PATCH 36/39] Fix sonarcloud badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a94a617..70c6798 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Thymeleaf Component Dialect [![Build Status](https://travis-ci.org/Serbroda/thymeleaf-component-dialect.svg?branch=develop)](https://travis-ci.org/Serbroda/thymeleaf-component-dialect) [![jitpack](https://jitpack.io/v/Serbroda/thymeleaf-component-dialect.svg)](https://jitpack.io/#Serbroda/thymeleaf-component-dialect) [![license](https://img.shields.io/github/license/Serbroda/thymeleaf-component-dialect.svg)](https://github.com/Serbroda/thymeleaf-component-dialect/blob/master/LICENSE.txt) -[![quality gate](https://sonarcloud.io/api/badges/gate?key=de.morphbit%3Athymeleaf-component-dialect%3Adevelop)](https://sonarcloud.io/dashboard?id=de.morphbit%3Athymeleaf-component-dialect%3Adevelop) +[![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=de.morphbit:thymeleaf-component-dialect:develop&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.morphbit:thymeleaf-component-dialect:develop) From 058cdf2bc7b4bf0850b4fe92f48d75d738e13ac7 Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 20 Mar 2026 21:13:14 +0100 Subject: [PATCH 37/39] Refactor tests to use JUnit 5 and update Maven dependencies --- .github/workflows/ci.yml | 31 +++++++ .mvn/wrapper/maven-wrapper.properties | 2 +- .travis.yml | 22 ----- README.md | 17 ++-- pom.xml | 42 +++++---- .../thymeleaf/helper/FragmentHelper.java | 4 +- .../thymeleaf/helper/ResourcePathFinder.java | 57 ++++++++---- ...AbstractThymeleafComponentDialectTest.java | 4 +- .../dialect/AttributeReplaceTest.java | 92 +++++++++---------- .../dialect/ComponentDialectTest.java | 77 ++++++++++++++++ .../thymeleaf/dialect/ContentReplaceTest.java | 13 +-- .../dialect/MultipleComponentsTest.java | 69 ++++++++++++++ .../thymeleaf/dialect/NamedSelectorTest.java | 25 +++++ .../dialect/NestedComponentTest.java | 29 ++++++ .../thymeleaf/dialect/OnceAttributeTest.java | 77 ++++++++-------- .../dialect/SelfClosingComponentTest.java | 25 +++++ .../helper/ResourcePathFinderTest.java | 55 +++++++++++ .../model/ThymeleafComponentTest.java | 43 +++++++++ .../StandardThymeleafComponentParserTest.java | 26 ++---- .../templates/components/alert_component.html | 13 +++ .../templates/components/card_component.html | 17 ++++ .../templates/multiple_components.html | 23 +++++ .../resources/templates/named_selector.html | 15 +++ .../templates/nested_components.html | 17 ++++ .../templates/self_closing_component.html | 13 +++ 25 files changed, 631 insertions(+), 177 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/ComponentDialectTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/dialect/SelfClosingComponentTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/helper/ResourcePathFinderTest.java create mode 100644 src/test/java/de/morphbit/thymeleaf/model/ThymeleafComponentTest.java create mode 100644 src/test/resources/templates/components/alert_component.html create mode 100644 src/test/resources/templates/components/card_component.html create mode 100644 src/test/resources/templates/multiple_components.html create mode 100644 src/test/resources/templates/named_selector.html create mode 100644 src/test/resources/templates/nested_components.html create mode 100644 src/test/resources/templates/self_closing_component.html diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..848f3db --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: + push: + branches: [ develop ] + pull_request: + branches: [ develop ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + + - name: Build and test + run: ./mvnw clean verify + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results + path: target/surefire-reports/ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index c315043..11213b0 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1 +1 @@ -distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7c4268d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: java -jdk: oraclejdk8 - -branches: - except: - - master - -cache: - directories: - - $HOME/.m2/repository - -install: mvn install - -addons: - sonarcloud: - organization: "serbroda-github" - token: - secure: e0624c074cc2912e0a56aad2df374638bbc29bed - branches: - - develop -script: - - mvn clean org.jacoco:jacoco-maven-plugin:prepare-agent install sonar:sonar \ No newline at end of file diff --git a/README.md b/README.md index 70c6798..6d55f1a 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,24 @@ Thymeleaf Component Dialect =========================== -[![Build Status](https://travis-ci.org/Serbroda/thymeleaf-component-dialect.svg?branch=develop)](https://travis-ci.org/Serbroda/thymeleaf-component-dialect) +[![CI](https://github.com/Serbroda/thymeleaf-component-dialect/actions/workflows/ci.yml/badge.svg)](https://github.com/Serbroda/thymeleaf-component-dialect/actions/workflows/ci.yml) [![jitpack](https://jitpack.io/v/Serbroda/thymeleaf-component-dialect.svg)](https://jitpack.io/#Serbroda/thymeleaf-component-dialect) -[![license](https://img.shields.io/github/license/Serbroda/thymeleaf-component-dialect.svg)](https://github.com/Serbroda/thymeleaf-component-dialect/blob/master/LICENSE.txt) -[![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=de.morphbit:thymeleaf-component-dialect:develop&metric=alert_status)](https://sonarcloud.io/dashboard?id=de.morphbit:thymeleaf-component-dialect:develop) +[![license](https://img.shields.io/github/license/Serbroda/thymeleaf-component-dialect.svg)](https://github.com/Serbroda/thymeleaf-component-dialect/blob/develop/LICENSE.txt) +A dialect for creating reusable Thymeleaf components, similar to React or Vue components. +Requirements +------ -A dialect for creating reusable thymeleaf components. +- Java 17+ +- Thymeleaf 3.1+ Installation ------ Add the jitpack repository. -```html +```xml jitpack.io @@ -26,7 +29,7 @@ Add the jitpack repository. Add the dependency (for all available versions see [https://jitpack.io/#Serbroda/thymeleaf-component-dialect](https://jitpack.io/#Serbroda/thymeleaf-component-dialect)). -```html +```xml com.github.Serbroda thymeleaf-component-dialect @@ -49,8 +52,6 @@ public ComponentDialect componentDialect() { Usage ----- -For detailed configurations have a look at the [demo project](https://github.com/Serbroda/thymeleaf-component-dialect-demo). - ### Create a thymeleaf component Thymeleaf components uses the standard `th:fragment` attribute to register components. Just create a fragment with a `` tag which will be replaced with specific contents. diff --git a/pom.xml b/pom.xml index 06a5b58..47b562a 100644 --- a/pom.xml +++ b/pom.xml @@ -13,47 +13,53 @@ UTF-8 UTF-8 - 1.8 - 1.8 - 1.8 - 2.0.0.RELEASE + 17 + 17 + 17 org.thymeleaf thymeleaf - 3.0.7.RELEASE + 3.1.3.RELEASE - junit - junit - 4.12 + org.junit.jupiter + junit-jupiter + 5.11.4 test - - - - org.springframework - spring-core - 4.3.9.RELEASE - - + org.slf4j slf4j-api - 1.7.25 + 2.0.16 + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.2 + true org.apache.maven.plugins maven-source-plugin - 3.0.1 + 3.3.1 attach-sources diff --git a/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java b/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java index 9ab08a0..a766e08 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java @@ -18,7 +18,6 @@ import org.thymeleaf.standard.expression.FragmentSignatureUtils; import org.thymeleaf.standard.expression.IStandardExpressionParser; import org.thymeleaf.standard.expression.NoOpToken; -import org.thymeleaf.standard.expression.StandardExpressionExecutionContext; import org.thymeleaf.standard.expression.StandardExpressions; import org.thymeleaf.util.EscapedAttributeUtils; import org.thymeleaf.util.StringUtils; @@ -160,8 +159,7 @@ private static Object computeFragment(final ITemplateContext context, final FragmentExpression.ExecutedFragmentExpression executedFragmentExpression = FragmentExpression.createExecutedFragmentExpression(context, - fragmentExpression, - StandardExpressionExecutionContext.NORMAL); + fragmentExpression); if (executedFragmentExpression .getFragmentSelectorExpressionResult() == null diff --git a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java index 2a9635f..007fb4e 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java @@ -17,14 +17,23 @@ package de.morphbit.thymeleaf.helper; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.FileSystem; +import java.nio.file.FileSystemAlreadyExistsException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; import java.util.List; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; public class ResourcePathFinder { @@ -50,7 +59,7 @@ public ResourcePathFinder(String directory) { * Searches for resource files * * Search files recursively - * + * * @return List of files as strings */ public List findResourceFiles() { @@ -60,20 +69,36 @@ public List findResourceFiles() { private List getResourceFiles(String dir) { List files = new ArrayList<>(); try { - ResourcePatternResolver resolver = - new PathMatchingResourcePatternResolver(loader); - Resource[] resources = - resolver.getResources("classpath*:/" + dir + "/**/*.*"); - String basePath = loader.getResource(dir).getPath(); - for (Resource resource : resources) { + Enumeration resources = loader.getResources(dir); + while (resources.hasMoreElements()) { + URL resourceUrl = resources.nextElement(); + URI uri = resourceUrl.toURI(); - String pathRelativeToDir = dir + "/" + resource.getURL() - .getPath().replace(basePath + "/", ""); - files.add(pathRelativeToDir); - } + Path path; + if ("jar".equals(uri.getScheme())) { + FileSystem fileSystem; + try { + fileSystem = FileSystems.newFileSystem(uri, + Collections.emptyMap()); + } catch (FileSystemAlreadyExistsException e) { + fileSystem = FileSystems.getFileSystem(uri); + } + path = fileSystem.getPath(dir); + } else { + path = Paths.get(uri); + } - } catch (IOException ex) { - LOG.error("Could not process resource pattern. {}", ex); + try (Stream walk = Files.walk(path)) { + walk.filter(Files::isRegularFile).forEach(p -> { + String relativePath = + dir + "/" + path.relativize(p).toString(); + files.add(relativePath); + }); + } + } + } catch (IOException | URISyntaxException ex) { + LOG.error("Could not process resource pattern. {}", ex.getMessage(), + ex); } return files; diff --git a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java index 7118213..d896224 100644 --- a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java +++ b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java @@ -1,6 +1,6 @@ package de.morphbit.thymeleaf.base; -import org.junit.BeforeClass; +import org.junit.jupiter.api.BeforeAll; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import org.thymeleaf.templatemode.TemplateMode; @@ -15,7 +15,7 @@ public abstract class AbstractThymeleafComponentDialectTest { private static TemplateEngine templateEngine; - @BeforeClass + @BeforeAll public static void beforeClass() { setupThymeleaf(); } diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java index 68e0376..eaa4af3 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java @@ -1,46 +1,46 @@ -package de.morphbit.thymeleaf.dialect; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Collections; -import java.util.Locale; - -import org.junit.Test; -import org.thymeleaf.context.Context; - -import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; - -public class AttributeReplaceTest - extends AbstractThymeleafComponentDialectTest { - - private static final String FILE = "repl_test.html"; - - public static class User { - - private String name; - - public User(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - } - - @Test - public void itShouldReplaceAllReplAttributes() { - String html = processThymeleafFile(FILE, new Context(Locale.ENGLISH, - Collections.singletonMap("user", new User("John")))); - - assertNotNull(html); - assertTrue(!html.matches(".*\\?\\[([\\w|\\d|.|\\-|_]*)\\].*")); - } - -} +package de.morphbit.thymeleaf.dialect; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.Collections; +import java.util.Locale; + +import org.junit.jupiter.api.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class AttributeReplaceTest + extends AbstractThymeleafComponentDialectTest { + + private static final String FILE = "repl_test.html"; + + public static class User { + + private String name; + + public User(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } + + @Test + public void itShouldReplaceAllReplAttributes() { + String html = processThymeleafFile(FILE, new Context(Locale.ENGLISH, + Collections.singletonMap("user", new User("John")))); + + assertNotNull(html); + assertFalse(html.matches(".*\\?\\[([\\w|\\d|.|\\-|_]*)\\].*")); + } + +} diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentDialectTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentDialectTest.java new file mode 100644 index 0000000..5b0d239 --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentDialectTest.java @@ -0,0 +1,77 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Test; +import org.thymeleaf.context.Context; +import org.thymeleaf.processor.IProcessor; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; + +import de.morphbit.thymeleaf.model.ThymeleafComponent; + +public class ComponentDialectTest { + + @Test + public void itShouldHaveCorrectPrefixAndName() { + ComponentDialect dialect = new ComponentDialect(); + assertEquals("tc", dialect.getPrefix()); + assertEquals("Component Dialect", dialect.getName()); + } + + @Test + public void itShouldRegisterManualComponents() { + Set components = new HashSet<>(); + components.add( + new ThymeleafComponent("my-comp", "templates/test :: fragment")); + + ComponentDialect dialect = new ComponentDialect(components); + Set processors = dialect.getProcessors("tc"); + + // OnceAttributeTagProcessor + 1 manual component + assertTrue(processors.size() >= 2); + } + + @Test + public void itShouldWorkWithManuallyRegisteredComponent() { + ClassLoaderTemplateResolver templateResolver = + new ClassLoaderTemplateResolver(); + templateResolver.setCacheable(false); + templateResolver.setCharacterEncoding("UTF-8"); + templateResolver.setTemplateMode(TemplateMode.HTML); + templateResolver.setSuffix(".html"); + + TemplateEngine engine = new TemplateEngine(); + engine.setTemplateResolver(templateResolver); + + Set components = new HashSet<>(); + components.add(new ThymeleafComponent("link", + "templates/components/link_component :: link")); + + ComponentDialect dialect = new ComponentDialect(components); + engine.addDialect(dialect.getPrefix(), dialect); + + String html = engine.process("templates/link_with_content", + new Context()); + + assertNotNull(html); + assertFalse(html.contains("tc:link")); + assertTrue(html.contains("")); + } + + @Test + public void itShouldReturnOnceProcessorWithEmptyDialect() { + ComponentDialect dialect = new ComponentDialect(); + Set processors = dialect.getProcessors("tc"); + + assertFalse(processors.isEmpty()); + assertEquals(1, processors.size()); + } +} diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java index c38d830..0aab729 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java @@ -1,9 +1,10 @@ package de.morphbit.thymeleaf.dialect; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.thymeleaf.context.Context; import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; @@ -21,11 +22,11 @@ public void itShouldNotRenderNamespaceTagsAndReplaceContent() { processThymeleafFile(FILE_LINK_WITH_CONTENT, new Context()); assertNotNull(html); - assertTrue(!html.contains("tc:link")); - assertTrue(!html.contains("tc:content")); + assertFalse(html.contains("tc:link")); + assertFalse(html.contains("tc:content")); assertTrue(html.contains("")); assertTrue(html.contains("Test")); - assertTrue(!html.contains(">> ")); + assertFalse(html.contains(">> ")); } @Test diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java new file mode 100644 index 0000000..4351555 --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java @@ -0,0 +1,69 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.jupiter.api.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class MultipleComponentsTest + extends AbstractThymeleafComponentDialectTest { + + @Test + public void itShouldRenderMultipleComponentsOnSamePage() { + String html = processThymeleafFile("multiple_components.html", + new Context()); + + assertNotNull(html); + assertFalse(html.contains("tc:alert")); + assertFalse(html.contains("tc:card")); + assertFalse(html.contains("tc:content")); + + // Two alert components + assertTrue(html.contains("First")); + assertTrue(html.contains("Second")); + assertTrue(html.contains("Content 1")); + assertTrue(html.contains("Content 2")); + + // One card component + assertTrue(html.contains("My Card")); + assertTrue(html.contains("

Card content

")); + } + + @Test + public void itShouldRenderCorrectAlertTypes() { + String html = processThymeleafFile("multiple_components.html", + new Context()); + + assertNotNull(html); + assertTrue(html.contains("alert-success")); + assertTrue(html.contains("alert-danger")); + } + + @Test + public void itShouldRenderCorrectNumberOfAlerts() { + String html = processThymeleafFile("multiple_components.html", + new Context()); + + assertNotNull(html); + int alertCount = countMatches("class=\"alert", html); + assertTrue(alertCount == 2, + "Expected 2 alerts but found " + alertCount); + } + + private int countMatches(String text, String search) { + int count = 0; + Pattern pattern = Pattern.compile(Pattern.quote(text)); + Matcher matcher = pattern.matcher(search); + while (matcher.find()) { + count++; + } + return count; + } +} diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java new file mode 100644 index 0000000..4eb40e9 --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java @@ -0,0 +1,25 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class NamedSelectorTest extends AbstractThymeleafComponentDialectTest { + + @Test + public void itShouldResolveComponentByNamedSelector() { + String html = + processThymeleafFile("named_selector.html", new Context()); + + assertNotNull(html); + assertFalse(html.contains("tc:link-named")); + assertFalse(html.contains("tc:content")); + assertTrue(html.contains("
")); + assertTrue(html.contains("Named Link")); + } +} diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java new file mode 100644 index 0000000..6b79f64 --- /dev/null +++ b/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java @@ -0,0 +1,29 @@ +package de.morphbit.thymeleaf.dialect; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.thymeleaf.context.Context; + +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; + +public class NestedComponentTest extends AbstractThymeleafComponentDialectTest { + + @Test + public void itShouldRenderNestedComponents() { + String html = processThymeleafFile("nested_components.html", + new Context()); + + assertNotNull(html); + assertFalse(html.contains("tc:card")); + assertFalse(html.contains("tc:alert")); + assertFalse(html.contains("tc:content")); + assertTrue(html.contains("class=\"card\"")); + assertTrue(html.contains("Outer Card")); + assertTrue(html.contains("class=\"alert")); + assertTrue(html.contains("Nested Alert")); + assertTrue(html.contains("Nested content")); + } +} diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java index 0aaf83a..f73cb8c 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java @@ -1,38 +1,39 @@ -package de.morphbit.thymeleaf.dialect; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.junit.Test; -import org.thymeleaf.context.Context; - -import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; - -public class OnceAttributeTest extends AbstractThymeleafComponentDialectTest { - - private static final String FILE = "once_test.html"; - - @Test - public void itShouldHaveMultipleComponentsButOneScript() { - String html = processThymeleafFile(FILE, new Context()); - - assertNotNull(html); - assertTrue(countMatches( - "\\