From c77dd86301b251af53dac40d61d9d5cf770a680e Mon Sep 17 00:00:00 2001 From: Serbroda Date: Tue, 17 Oct 2017 21:30:29 +0200 Subject: [PATCH 01/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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/44] 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( - "\\
-

Hello world

This is my first thymeleaf component

-
+``` + +### The `tc:once` Attribute + +Use `tc:once` to ensure an element (e.g. a script tag) is only rendered once, even if the component is used multiple times on the same page: + +```html +
+ + +
``` \ No newline at end of file diff --git a/pom.xml b/pom.xml index 47b562a..ce332bb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,11 @@ de.morphbit thymeleaf-component-dialect - 0.0.4-alpha-SNAPSHOT + 0.1.0-SNAPSHOT jar thymeleaf-component-dialect - Thymeleaf Layout Dialect + A Thymeleaf dialect for creating reusable components UTF-8 diff --git a/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java b/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java index 32e3f3c..bb1e62c 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java @@ -69,24 +69,12 @@ public static void processWith(ITemplateContext context, + leftExpr + "\""); } - if(registerGlobal && 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 - // 'th:with' - engineContext.setVariable(newVariableName, rightValue); - } else { - // The problem is, these won't be available until we execute the - // next processor - structureHandler.setLocalVariable(newVariableName, rightValue); - }*/ - } } } diff --git a/src/test/resources/templates/components/alert_component.html b/src/test/resources/templates/components/alert_component.html index 541b2be..cb58288 100644 --- a/src/test/resources/templates/components/alert_component.html +++ b/src/test/resources/templates/components/alert_component.html @@ -1,5 +1,5 @@ - + diff --git a/src/test/resources/templates/components/card_component.html b/src/test/resources/templates/components/card_component.html index 27b3476..eddcf9e 100644 --- a/src/test/resources/templates/components/card_component.html +++ b/src/test/resources/templates/components/card_component.html @@ -1,5 +1,5 @@ - + diff --git a/src/test/resources/templates/components/link_component.html b/src/test/resources/templates/components/link_component.html index 22f6651..96e8d80 100644 --- a/src/test/resources/templates/components/link_component.html +++ b/src/test/resources/templates/components/link_component.html @@ -1,5 +1,5 @@ - + diff --git a/src/test/resources/templates/components/no_component.html b/src/test/resources/templates/components/no_component.html index c1fdac8..81e3c06 100644 --- a/src/test/resources/templates/components/no_component.html +++ b/src/test/resources/templates/components/no_component.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> diff --git a/src/test/resources/templates/components/once_component.html b/src/test/resources/templates/components/once_component.html index bc54174..79faae5 100644 --- a/src/test/resources/templates/components/once_component.html +++ b/src/test/resources/templates/components/once_component.html @@ -1,5 +1,5 @@ - + diff --git a/src/test/resources/templates/components/valid_input.html b/src/test/resources/templates/components/valid_input.html index 9fc1069..987279c 100644 --- a/src/test/resources/templates/components/valid_input.html +++ b/src/test/resources/templates/components/valid_input.html @@ -1,5 +1,5 @@ - + diff --git a/src/test/resources/templates/link_with_content.html b/src/test/resources/templates/link_with_content.html index ca500ef..c2e90dc 100644 --- a/src/test/resources/templates/link_with_content.html +++ b/src/test/resources/templates/link_with_content.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> 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 9491016..e2f15bc 100644 --- a/src/test/resources/templates/link_with_content_and_variable.html +++ b/src/test/resources/templates/link_with_content_and_variable.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test diff --git a/src/test/resources/templates/multiple_components.html b/src/test/resources/templates/multiple_components.html index 7fd6e34..6a9aed9 100644 --- a/src/test/resources/templates/multiple_components.html +++ b/src/test/resources/templates/multiple_components.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test diff --git a/src/test/resources/templates/named_selector.html b/src/test/resources/templates/named_selector.html index 4b61ad5..a3628ad 100644 --- a/src/test/resources/templates/named_selector.html +++ b/src/test/resources/templates/named_selector.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test diff --git a/src/test/resources/templates/nested_components.html b/src/test/resources/templates/nested_components.html index 7d22511..2fb23d2 100644 --- a/src/test/resources/templates/nested_components.html +++ b/src/test/resources/templates/nested_components.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test diff --git a/src/test/resources/templates/once_test.html b/src/test/resources/templates/once_test.html index fd58b83..d09b94e 100644 --- a/src/test/resources/templates/once_test.html +++ b/src/test/resources/templates/once_test.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test diff --git a/src/test/resources/templates/repl_test.html b/src/test/resources/templates/repl_test.html index 5d28802..eee0b51 100644 --- a/src/test/resources/templates/repl_test.html +++ b/src/test/resources/templates/repl_test.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test diff --git a/src/test/resources/templates/self_closing_component.html b/src/test/resources/templates/self_closing_component.html index 429c584..34ee458 100644 --- a/src/test/resources/templates/self_closing_component.html +++ b/src/test/resources/templates/self_closing_component.html @@ -1,7 +1,7 @@ + xmlns:tc="https://github.com/Serbroda/thymeleaf-component-dialect"> Test From e9f31bc9df052dec673d09b4c5c4717f33e4c84c Mon Sep 17 00:00:00 2001 From: Danny Rottstegge Date: Fri, 20 Mar 2026 21:34:21 +0100 Subject: [PATCH 39/44] add spotless and format code --- pom.xml | 23 ++++ .../thymeleaf/dialect/ComponentDialect.java | 18 ++- .../thymeleaf/helper/FragmentHelper.java | 109 +++++++----------- .../thymeleaf/helper/ResourcePathFinder.java | 13 +-- .../morphbit/thymeleaf/helper/WithHelper.java | 24 ++-- .../thymeleaf/model/ThymeleafComponent.java | 3 +- .../parser/AbstractElementParser.java | 32 ++--- .../parser/IThymeleafComponentParser.java | 3 +- .../StandardThymeleafComponentParser.java | 47 +++----- .../ComponentNamedElementProcessor.java | 94 ++++++--------- .../processor/OnceAttributeTagProcessor.java | 8 +- ...AbstractThymeleafComponentDialectTest.java | 13 +-- .../dialect/AttributeReplaceTest.java | 11 +- .../dialect/ComponentDialectTest.java | 18 +-- .../thymeleaf/dialect/ContentReplaceTest.java | 15 +-- .../dialect/MultipleComponentsTest.java | 19 +-- .../thymeleaf/dialect/NamedSelectorTest.java | 6 +- .../dialect/NestedComponentTest.java | 6 +- .../thymeleaf/dialect/OnceAttributeTest.java | 8 +- .../dialect/SelfClosingComponentTest.java | 9 +- .../helper/ResourcePathFinderTest.java | 25 ++-- .../model/ThymeleafComponentTest.java | 12 +- .../StandardThymeleafComponentParserTest.java | 15 +-- 23 files changed, 207 insertions(+), 324 deletions(-) diff --git a/pom.xml b/pom.xml index ce332bb..a584871 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,29 @@ maven-surefire-plugin 3.5.2 + + com.diffplug.spotless + spotless-maven-plugin + 2.44.3 + + + + 4.33 + + + + + + + + spotless-check + verify + + check + + + + true org.apache.maven.plugins diff --git a/src/main/java/de/morphbit/thymeleaf/dialect/ComponentDialect.java b/src/main/java/de/morphbit/thymeleaf/dialect/ComponentDialect.java index 0b20098..2348231 100644 --- a/src/main/java/de/morphbit/thymeleaf/dialect/ComponentDialect.java +++ b/src/main/java/de/morphbit/thymeleaf/dialect/ComponentDialect.java @@ -16,19 +16,17 @@ package de.morphbit.thymeleaf.dialect; +import de.morphbit.thymeleaf.model.ThymeleafComponent; +import de.morphbit.thymeleaf.parser.IThymeleafComponentParser; +import de.morphbit.thymeleaf.processor.ComponentNamedElementProcessor; +import de.morphbit.thymeleaf.processor.OnceAttributeTagProcessor; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; - import org.thymeleaf.dialect.AbstractProcessorDialect; import org.thymeleaf.processor.IProcessor; -import de.morphbit.thymeleaf.model.ThymeleafComponent; -import de.morphbit.thymeleaf.parser.IThymeleafComponentParser; -import de.morphbit.thymeleaf.processor.ComponentNamedElementProcessor; -import de.morphbit.thymeleaf.processor.OnceAttributeTagProcessor; - /** * A dialect for creating reusable composite components with thymeleaf * @@ -73,14 +71,14 @@ public Set getProcessors(String dialectPrefix) { if (this.components != null) { for (ThymeleafComponent comp : this.components) { - processors.add(new ComponentNamedElementProcessor(dialectPrefix, - comp.getName(), comp.getFragmentTemplate())); + processors.add( + new ComponentNamedElementProcessor(dialectPrefix, comp.getName(), comp.getFragmentTemplate())); } } for (ThymeleafComponent comp : parseComponents()) { - processors.add(new ComponentNamedElementProcessor(dialectPrefix, - comp.getName(), comp.getFragmentTemplate())); + processors + .add(new ComponentNamedElementProcessor(dialectPrefix, comp.getName(), comp.getFragmentTemplate())); } return processors; diff --git a/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java b/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java index a766e08..f5ebfa5 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/FragmentHelper.java @@ -1,7 +1,6 @@ package de.morphbit.thymeleaf.helper; import java.util.Map; - import org.thymeleaf.IEngineConfiguration; import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.engine.TemplateData; @@ -28,10 +27,9 @@ private FragmentHelper() { } - public static IModel getFragmentModel(final ITemplateContext context, - final String attributeValue, - final IElementModelStructureHandler structureHandler, - final String dialectPrefix, final String FRAGMENT_ATTR_NAME) { + public static IModel getFragmentModel(final ITemplateContext context, final String attributeValue, + final IElementModelStructureHandler structureHandler, final String dialectPrefix, + final String FRAGMENT_ATTR_NAME) { IEngineConfiguration configuration = context.getConfiguration(); @@ -42,9 +40,8 @@ public static IModel getFragmentModel(final ITemplateContext context, // result is not the same as the result being the empty fragment // (~{}) - throw new TemplateInputException( - "Error resolving fragment: \"" + attributeValue + "\": " - + "template or fragment could not be resolved"); + throw new TemplateInputException("Error resolving fragment: \"" + attributeValue + "\": " + + "template or fragment could not be resolved"); } @@ -54,14 +51,13 @@ public static IModel getFragmentModel(final ITemplateContext context, Map fragmentParameters = fragment.getParameters(); /* - * ONCE WE HAVE THE FRAGMENT MODEL (its events, in fact), CHECK THE - * FRAGMENT SIGNATURE Fragment signature is important because it might - * affect the way we apply the parameters to the fragment. + * ONCE WE HAVE THE FRAGMENT MODEL (its events, in fact), CHECK THE FRAGMENT + * SIGNATURE Fragment signature is important because it might affect the way we + * apply the parameters to the fragment. * - * Note this works whatever the template mode of the inserted fragment, - * given we are looking for an element containing a - * "th:fragment/data-th-fragment" in a generic, non-template-dependent - * way. + * Note this works whatever the template mode of the inserted fragment, given we + * are looking for an element containing a "th:fragment/data-th-fragment" in a + * generic, non-template-dependent way. */ // We will check types first instead of events in order to (many times) @@ -69,36 +65,28 @@ public static IModel getFragmentModel(final ITemplateContext context, // event object when calling "model.get(pos)" boolean signatureApplied = false; - final ITemplateEvent firstEvent = - fragmentModel.size() > 2 ? fragmentModel.get(1) : null; - if (firstEvent != null && IProcessableElementTag.class - .isAssignableFrom(firstEvent.getClass())) { + final ITemplateEvent firstEvent = fragmentModel.size() > 2 ? fragmentModel.get(1) : null; + if (firstEvent != null && IProcessableElementTag.class.isAssignableFrom(firstEvent.getClass())) { - final IProcessableElementTag fragmentHolderEvent = - (IProcessableElementTag) firstEvent; + final IProcessableElementTag fragmentHolderEvent = (IProcessableElementTag) firstEvent; - if (fragmentHolderEvent.hasAttribute(dialectPrefix, - FRAGMENT_ATTR_NAME)) { + if (fragmentHolderEvent.hasAttribute(dialectPrefix, FRAGMENT_ATTR_NAME)) { // The selected fragment actually has a "th:fragment" attribute, // so we should process its signature - final String fragmentSignatureSpec = EscapedAttributeUtils - .unescapeAttribute(fragmentModel.getTemplateMode(), - fragmentHolderEvent.getAttributeValue(dialectPrefix, - FRAGMENT_ATTR_NAME)); + final String fragmentSignatureSpec = EscapedAttributeUtils.unescapeAttribute( + fragmentModel.getTemplateMode(), + fragmentHolderEvent.getAttributeValue(dialectPrefix, FRAGMENT_ATTR_NAME)); if (!StringUtils.isEmptyOrWhitespace(fragmentSignatureSpec)) { - final FragmentSignature fragmentSignature = - FragmentSignatureUtils.parseFragmentSignature( - configuration, fragmentSignatureSpec); + final FragmentSignature fragmentSignature = FragmentSignatureUtils + .parseFragmentSignature(configuration, fragmentSignatureSpec); if (fragmentSignature != null) { // Reshape the fragment parameters into the ones that we // will actually use, according to the signature - fragmentParameters = - FragmentSignatureUtils.processParameters( - fragmentSignature, fragmentParameters, - fragment.hasSyntheticParameters()); + fragmentParameters = FragmentSignatureUtils.processParameters(fragmentSignature, + fragmentParameters, fragment.hasSyntheticParameters()); signatureApplied = true; } @@ -117,59 +105,49 @@ public static IModel getFragmentModel(final ITemplateContext context, // assignation involved. if (!signatureApplied && fragment.hasSyntheticParameters()) { throw new TemplateProcessingException("Fragment '" + attributeValue - + "' specifies synthetic (unnamed) parameters, but the resolved fragment " - + "does not match a fragment signature (th:fragment,data-th-fragment) which could apply names to " - + "the specified parameters."); + + "' specifies synthetic (unnamed) parameters, but the resolved fragment " + + "does not match a fragment signature (th:fragment,data-th-fragment) which could apply names to " + + "the specified parameters."); } /* - * APPLY THE FRAGMENT'S TEMPLATE RESOLUTION so that all code inside the - * fragment is executed with its own template resolution info (working - * as if it were a local variable) + * APPLY THE FRAGMENT'S TEMPLATE RESOLUTION so that all code inside the fragment + * is executed with its own template resolution info (working as if it were a + * local variable) */ - final TemplateData fragmentTemplateData = - fragmentModel.getTemplateData(); + final TemplateData fragmentTemplateData = fragmentModel.getTemplateData(); structureHandler.setTemplateData(fragmentTemplateData); /* - * APPLY THE FRAGMENT PARAMETERS AS LOCAL VARIABLES, perhaps after - * reshaping it according to the fragment signature + * APPLY THE FRAGMENT PARAMETERS AS LOCAL VARIABLES, perhaps after reshaping it + * according to the fragment signature */ if (fragmentParameters != null && fragmentParameters.size() > 0) { - for (final Map.Entry fragmentParameterEntry : fragmentParameters - .entrySet()) { - structureHandler.setLocalVariable( - fragmentParameterEntry.getKey(), - fragmentParameterEntry.getValue()); + for (final Map.Entry fragmentParameterEntry : fragmentParameters.entrySet()) { + structureHandler.setLocalVariable(fragmentParameterEntry.getKey(), fragmentParameterEntry.getValue()); } } return fragmentModel; } - private static Object computeFragment(final ITemplateContext context, - final String input) { + private static Object computeFragment(final ITemplateContext context, final String input) { final IStandardExpressionParser expressionParser = StandardExpressions - .getExpressionParser(context.getConfiguration()); + .getExpressionParser(context.getConfiguration()); - final FragmentExpression fragmentExpression = - (FragmentExpression) expressionParser.parseExpression(context, - "~{" + input.trim() + "}"); + final FragmentExpression fragmentExpression = (FragmentExpression) expressionParser.parseExpression(context, + "~{" + input.trim() + "}"); - final FragmentExpression.ExecutedFragmentExpression executedFragmentExpression = - FragmentExpression.createExecutedFragmentExpression(context, - fragmentExpression); + final FragmentExpression.ExecutedFragmentExpression executedFragmentExpression = FragmentExpression + .createExecutedFragmentExpression(context, fragmentExpression); - if (executedFragmentExpression - .getFragmentSelectorExpressionResult() == null - && executedFragmentExpression.getFragmentParameters() == null) { + if (executedFragmentExpression.getFragmentSelectorExpressionResult() == null + && executedFragmentExpression.getFragmentParameters() == null) { // We might be in the scenario that what we thought was a template // name in fact was instead an expression // returning a Fragment itself, so we should simply return it - final Object templateNameExpressionResult = - executedFragmentExpression - .getTemplateNameExpressionResult(); + final Object templateNameExpressionResult = executedFragmentExpression.getTemplateNameExpressionResult(); if (templateNameExpressionResult != null) { if (templateNameExpressionResult instanceof Fragment) { return templateNameExpressionResult; @@ -188,7 +166,6 @@ private static Object computeFragment(final ITemplateContext context, // underlying resolution system would // have to execute a (potentially costly) resource.exists() call on the // resolved resource. - return FragmentExpression.resolveExecutedFragmentExpression(context, - executedFragmentExpression, true); + return FragmentExpression.resolveExecutedFragmentExpression(context, executedFragmentExpression, true); } } diff --git a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java index 007fb4e..4720c63 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/ResourcePathFinder.java @@ -31,14 +31,12 @@ import java.util.Enumeration; import java.util.List; import java.util.stream.Stream; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ResourcePathFinder { - private static final Logger LOG = - LoggerFactory.getLogger(ResourcePathFinder.class); + private static final Logger LOG = LoggerFactory.getLogger(ResourcePathFinder.class); private final String directory; private final ClassLoader loader; @@ -78,8 +76,7 @@ private List getResourceFiles(String dir) { if ("jar".equals(uri.getScheme())) { FileSystem fileSystem; try { - fileSystem = FileSystems.newFileSystem(uri, - Collections.emptyMap()); + fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap()); } catch (FileSystemAlreadyExistsException e) { fileSystem = FileSystems.getFileSystem(uri); } @@ -90,15 +87,13 @@ private List getResourceFiles(String dir) { try (Stream walk = Files.walk(path)) { walk.filter(Files::isRegularFile).forEach(p -> { - String relativePath = - dir + "/" + path.relativize(p).toString(); + String relativePath = dir + "/" + path.relativize(p).toString(); files.add(relativePath); }); } } } catch (IOException | URISyntaxException ex) { - LOG.error("Could not process resource pattern. {}", ex.getMessage(), - ex); + LOG.error("Could not process resource pattern. {}", ex.getMessage(), ex); } return files; diff --git a/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java b/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java index bb1e62c..751a196 100644 --- a/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java +++ b/src/main/java/de/morphbit/thymeleaf/helper/WithHelper.java @@ -1,7 +1,6 @@ package de.morphbit.thymeleaf.helper; import java.util.List; - import org.thymeleaf.context.IEngineContext; import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.exceptions.TemplateProcessingException; @@ -18,19 +17,15 @@ private WithHelper() { } - public static void processWith(ITemplateContext context, - String attributeValue, - IElementModelStructureHandler structureHandler, boolean registerGlobal) { - final AssignationSequence assignations = - AssignationUtils.parseAssignationSequence(context, - attributeValue, false /* no parameters without value */); + public static void processWith(ITemplateContext context, String attributeValue, + IElementModelStructureHandler structureHandler, boolean registerGlobal) { + final AssignationSequence assignations = AssignationUtils.parseAssignationSequence(context, attributeValue, + false /* no parameters without value */); if (assignations == null) { throw new TemplateProcessingException( - "Could not parse value as attribute assignations: \"" - + attributeValue + "\""); + "Could not parse value as attribute assignations: \"" + 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 @@ -47,8 +42,7 @@ public static void processWith(ITemplateContext context, engineContext = (IEngineContext) context; } - final List assignationValues = - assignations.getAssignations(); + final List assignationValues = assignations.getAssignations(); final int assignationValuesLen = assignationValues.size(); for (int i = 0; i < assignationValuesLen; i++) { @@ -61,12 +55,10 @@ public static void processWith(ITemplateContext context, final IStandardExpression rightExpr = assignation.getRight(); final Object rightValue = rightExpr.execute(context); - final String newVariableName = - leftValue == null ? null : leftValue.toString(); + final String newVariableName = leftValue == null ? null : leftValue.toString(); if (StringUtils.isEmptyOrWhitespace(newVariableName)) { throw new TemplateProcessingException( - "Variable name expression evaluated as null or empty: \"" - + leftExpr + "\""); + "Variable name expression evaluated as null or empty: \"" + leftExpr + "\""); } if (registerGlobal && engineContext != null) { diff --git a/src/main/java/de/morphbit/thymeleaf/model/ThymeleafComponent.java b/src/main/java/de/morphbit/thymeleaf/model/ThymeleafComponent.java index def9aa2..5c9a8d6 100644 --- a/src/main/java/de/morphbit/thymeleaf/model/ThymeleafComponent.java +++ b/src/main/java/de/morphbit/thymeleaf/model/ThymeleafComponent.java @@ -69,8 +69,7 @@ public void setFragmentTemplate(String fragmentTemplate) { @Override public String toString() { - return "Component [name=" + name + ", fragmentTemplate=" - + fragmentTemplate + "]"; + return "Component [name=" + name + ", fragmentTemplate=" + fragmentTemplate + "]"; } } diff --git a/src/main/java/de/morphbit/thymeleaf/parser/AbstractElementParser.java b/src/main/java/de/morphbit/thymeleaf/parser/AbstractElementParser.java index 23d370c..3fda602 100644 --- a/src/main/java/de/morphbit/thymeleaf/parser/AbstractElementParser.java +++ b/src/main/java/de/morphbit/thymeleaf/parser/AbstractElementParser.java @@ -22,7 +22,6 @@ import java.io.Reader; import java.util.ArrayList; import java.util.List; - import org.attoparser.AbstractMarkupHandler; import org.attoparser.MarkupParser; import org.attoparser.ParseException; @@ -33,8 +32,7 @@ public abstract class AbstractElementParser extends AbstractMarkupHandler { - private static final Logger LOG = - LoggerFactory.getLogger(AbstractElementParser.class); + private static final Logger LOG = LoggerFactory.getLogger(AbstractElementParser.class); protected final String dialectPrefix; @@ -46,21 +44,17 @@ public AbstractElementParser(String dialectPrefix) { } protected List parseElements(String file) { - return parseElements(Thread.currentThread().getContextClassLoader() - .getResourceAsStream(file)); + return parseElements(Thread.currentThread().getContextClassLoader().getResourceAsStream(file)); } protected List parseElements(InputStream stream) { this.elements = new ArrayList<>(); try (Reader reader = new InputStreamReader(stream)) { - final ParseConfiguration config = - ParseConfiguration.htmlConfiguration(); + final ParseConfiguration config = ParseConfiguration.htmlConfiguration(); - final ParseConfiguration autoCloseConfig = - ParseConfiguration.htmlConfiguration(); - autoCloseConfig.setElementBalancing( - ParseConfiguration.ElementBalancing.AUTO_OPEN_CLOSE); + final ParseConfiguration autoCloseConfig = ParseConfiguration.htmlConfiguration(); + autoCloseConfig.setElementBalancing(ParseConfiguration.ElementBalancing.AUTO_OPEN_CLOSE); final MarkupParser htmlStandardParser = new MarkupParser(config); htmlStandardParser.parse(reader, this); @@ -81,22 +75,20 @@ protected List parseElements(InputStream stream) { } @Override - public void handleAttribute(char[] buffer, int nameOffset, int nameLen, - int nameLine, int nameCol, int operatorOffset, int operatorLen, - int operatorLine, int operatorCol, int valueContentOffset, - int valueContentLen, int valueOuterOffset, int valueOuterLen, - int valueLine, int valueCol) throws ParseException { + public void handleAttribute(char[] buffer, int nameOffset, int nameLen, int nameLine, int nameCol, + int operatorOffset, int operatorLen, int operatorLine, int operatorCol, int valueContentOffset, + int valueContentLen, int valueOuterOffset, int valueOuterLen, int valueLine, int valueCol) + throws ParseException { String attributeName = new String(buffer, nameOffset, nameLen); - String attributeValue = - new String(buffer, valueContentOffset, valueContentLen); + String attributeValue = new String(buffer, valueContentOffset, valueContentLen); if (currentElement != null) { currentElement.addAttribute(attributeName, attributeValue); } } @Override - public void handleOpenElementStart(char[] buffer, int nameOffset, - int nameLen, int line, int col) throws ParseException { + public void handleOpenElementStart(char[] buffer, int nameOffset, int nameLen, int line, int col) + throws ParseException { String attributeName = new String(buffer, nameOffset, nameLen); this.currentElement = new Element(attributeName); this.elements.add(currentElement); diff --git a/src/main/java/de/morphbit/thymeleaf/parser/IThymeleafComponentParser.java b/src/main/java/de/morphbit/thymeleaf/parser/IThymeleafComponentParser.java index b12afe0..5a400a5 100644 --- a/src/main/java/de/morphbit/thymeleaf/parser/IThymeleafComponentParser.java +++ b/src/main/java/de/morphbit/thymeleaf/parser/IThymeleafComponentParser.java @@ -16,9 +16,8 @@ package de.morphbit.thymeleaf.parser; -import java.util.Set; - import de.morphbit.thymeleaf.model.ThymeleafComponent; +import java.util.Set; public interface IThymeleafComponentParser { diff --git a/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java b/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java index 81aba52..758df62 100644 --- a/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java +++ b/src/main/java/de/morphbit/thymeleaf/parser/StandardThymeleafComponentParser.java @@ -16,18 +16,15 @@ package de.morphbit.thymeleaf.parser; +import de.morphbit.thymeleaf.dialect.ComponentDialect; +import de.morphbit.thymeleaf.helper.ResourcePathFinder; +import de.morphbit.thymeleaf.model.ThymeleafComponent; import java.util.HashSet; import java.util.Set; - import org.attoparser.dom.Element; import org.thymeleaf.standard.StandardDialect; -import de.morphbit.thymeleaf.dialect.ComponentDialect; -import de.morphbit.thymeleaf.helper.ResourcePathFinder; -import de.morphbit.thymeleaf.model.ThymeleafComponent; - -public class StandardThymeleafComponentParser extends AbstractElementParser - implements IThymeleafComponentParser { +public class StandardThymeleafComponentParser extends AbstractElementParser implements IThymeleafComponentParser { protected static final String NAME_ATTRIBUTE = "selector"; protected static final String FRAGMENT_ATTRIBUTE = "fragment"; @@ -44,11 +41,10 @@ public class StandardThymeleafComponentParser extends AbstractElementParser * @param templateSuffix * Template suffix (e.g. .html) * @param directory - * Subdirectory of param templatePrefix to find components in - * (e.g. components) + * Subdirectory of param templatePrefix to find components in (e.g. + * components) */ - public StandardThymeleafComponentParser(String templatePrefix, - String templateSuffix, String directory) { + public StandardThymeleafComponentParser(String templatePrefix, String templateSuffix, String directory) { super(ComponentDialect.PREFIX); this.directory = directory; this.templatePrefix = templatePrefix; @@ -59,8 +55,7 @@ public StandardThymeleafComponentParser(String templatePrefix, public Set parse() { Set components = new HashSet<>(); - for (String file : new ResourcePathFinder(templatePrefix + directory) - .findResourceFiles()) { + for (String file : new ResourcePathFinder(templatePrefix + directory).findResourceFiles()) { for (Element element : parseElements(file)) { if (isThymeleafComponent(element)) { components.add(createComponent(element, file)); @@ -71,19 +66,15 @@ public Set parse() { return components; } - private ThymeleafComponent createComponent(Element element, - String htmlFile) { + private ThymeleafComponent createComponent(Element element, String htmlFile) { String templateFile = htmlFile; templateFile = templateFile.replaceAll("^" + this.templatePrefix, ""); - templateFile = templateFile - .replaceAll(this.templateSuffix.replace(".", "\\."), ""); + templateFile = templateFile.replaceAll(this.templateSuffix.replace(".", "\\."), ""); - String frag = getDynamicAttributeValue(element, StandardDialect.PREFIX, - FRAGMENT_ATTRIBUTE); + String frag = getDynamicAttributeValue(element, StandardDialect.PREFIX, FRAGMENT_ATTRIBUTE); frag = frag.replaceAll("\\(.*\\)", ""); - String name = getDynamicAttributeValue(element, this.dialectPrefix, - NAME_ATTRIBUTE); + String name = getDynamicAttributeValue(element, this.dialectPrefix, NAME_ATTRIBUTE); if (name == null) { name = frag; } @@ -92,20 +83,16 @@ private ThymeleafComponent createComponent(Element element, } private boolean isThymeleafComponent(Element element) { - return hasDynamicAttribute(element, StandardDialect.PREFIX, - FRAGMENT_ATTRIBUTE); + return hasDynamicAttribute(element, StandardDialect.PREFIX, FRAGMENT_ATTRIBUTE); } - private boolean hasDynamicAttribute(Element element, String prefix, - String dynamicAttribute) { + private boolean hasDynamicAttribute(Element element, String prefix, String dynamicAttribute) { return element.hasAttribute("data-" + prefix + "-" + dynamicAttribute) - || element.hasAttribute(prefix + ":" + dynamicAttribute); + || element.hasAttribute(prefix + ":" + dynamicAttribute); } - private String getDynamicAttributeValue(Element element, String prefix, - String dynamicAttribute) { - String value = element - .getAttributeValue("data-" + prefix + "-" + dynamicAttribute); + private String getDynamicAttributeValue(Element element, String prefix, String dynamicAttribute) { + String value = element.getAttributeValue("data-" + prefix + "-" + dynamicAttribute); if (value != null) { return value; } diff --git a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java index c3ab764..f4681dc 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/ComponentNamedElementProcessor.java @@ -18,13 +18,14 @@ import static java.util.Collections.singleton; +import de.morphbit.thymeleaf.helper.FragmentHelper; +import de.morphbit.thymeleaf.helper.WithHelper; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.engine.AttributeNames; import org.thymeleaf.model.IAttribute; @@ -38,11 +39,7 @@ import org.thymeleaf.standard.StandardDialect; import org.thymeleaf.templatemode.TemplateMode; -import de.morphbit.thymeleaf.helper.FragmentHelper; -import de.morphbit.thymeleaf.helper.WithHelper; - -public class ComponentNamedElementProcessor - extends AbstractElementModelProcessor { +public class ComponentNamedElementProcessor extends AbstractElementModelProcessor { private static final String FRAGMENT_ATTRIBUTE = "fragment"; private static final String REPLACE_CONTENT_TAG = "tc:content"; @@ -62,16 +59,13 @@ public class ComponentNamedElementProcessor * @param fragmentName * Fragment to search for */ - public ComponentNamedElementProcessor(final String dialectPrefix, - final String tagName, final String fragmentName) { - super(TemplateMode.HTML, dialectPrefix, tagName, true, null, false, - PRECEDENCE); + public ComponentNamedElementProcessor(final String dialectPrefix, final String tagName, final String fragmentName) { + super(TemplateMode.HTML, dialectPrefix, tagName, true, null, false, PRECEDENCE); this.fragmentName = fragmentName; } @Override - protected void doProcess(ITemplateContext context, IModel model, - IElementModelStructureHandler structureHandler) { + protected void doProcess(ITemplateContext context, IModel model, IElementModelStructureHandler structureHandler) { IProcessableElementTag tag = processElementTag(context, model); Map attributes = processAttribute(tag); @@ -85,8 +79,8 @@ protected void doProcess(ITemplateContext context, IModel model, } IModel fragmentModel = FragmentHelper.getFragmentModel(context, - fragmentName + (constructorParams == null ? "" : "(" + constructorParams + ")"), - structureHandler, StandardDialect.PREFIX, FRAGMENT_ATTRIBUTE); + fragmentName + (constructorParams == null ? "" : "(" + constructorParams + ")"), structureHandler, + StandardDialect.PREFIX, FRAGMENT_ATTRIBUTE); model.reset(); @@ -96,8 +90,7 @@ protected void doProcess(ITemplateContext context, IModel model, processVariables(attributes, context, structureHandler, excludeAttributes); } - private IProcessableElementTag processElementTag(ITemplateContext context, - IModel model) { + private IProcessableElementTag processElementTag(ITemplateContext context, IModel model) { ITemplateEvent firstEvent = model.get(0); for (IProcessableElementTag tag : context.getElementStack()) { if (locationMatches(firstEvent, tag)) { @@ -108,26 +101,21 @@ private IProcessableElementTag processElementTag(ITemplateContext context, } private boolean locationMatches(ITemplateEvent a, ITemplateEvent b) { - return Objects.equals(a.getTemplateName(), b.getTemplateName()) - && Objects.equals(a.getLine(), b.getLine()) - && Objects.equals(a.getCol(), b.getCol()); + return Objects.equals(a.getTemplateName(), b.getTemplateName()) && Objects.equals(a.getLine(), b.getLine()) + && Objects.equals(a.getCol(), b.getCol()); } - private void processVariables(Map attributes, - ITemplateContext context, - IElementModelStructureHandler structureHandler, - Set excludeAttr) { + private void processVariables(Map attributes, ITemplateContext context, + IElementModelStructureHandler structureHandler, Set excludeAttr) { for (Map.Entry entry : attributes.entrySet()) { - if (excludeAttr.contains(entry.getKey()) || isDynamicAttribute( - entry.getKey(), this.getDialectPrefix())) { + if (excludeAttr.contains(entry.getKey()) || isDynamicAttribute(entry.getKey(), this.getDialectPrefix())) { continue; } String attributeValue = entry.getValue(); if (attributeValue == null) { attributeValue = "${true}"; } - WithHelper.processWith(context, entry.getKey() + "=" + attributeValue, - structureHandler, false); + WithHelper.processWith(context, entry.getKey() + "=" + attributeValue, structureHandler, false); } } @@ -146,8 +134,7 @@ private Map processAttribute(IProcessableElementTag tag) { } private boolean isDynamicAttribute(String attribute, String prefix) { - return attribute.startsWith(prefix + ":") - || attribute.startsWith("data-" + prefix + "-"); + return attribute.startsWith(prefix + ":") || attribute.startsWith("data-" + prefix + "-"); } private IModel mergeModels(IModel base, IModel insert, String replaceTag) { @@ -180,18 +167,16 @@ private int findTagIndex(IModel model, final String search, Class clazz) { ITemplateEvent event = null; for (int i = 0; i < size; i++) { event = model.get(i); - if ((clazz == null || clazz.isInstance(event)) - && event.toString().contains(search)) { + if ((clazz == null || clazz.isInstance(event)) && event.toString().contains(search)) { return i; } } return -1; } - private IModel replaceAllAttributeValues(Map attributes, - ITemplateContext context, IModel model) { - Map replaceAttributes = findAllAttributesStartsWith( - attributes, super.getDialectPrefix(), "repl-", true); + private IModel replaceAllAttributeValues(Map attributes, ITemplateContext context, IModel model) { + Map replaceAttributes = findAllAttributesStartsWith(attributes, super.getDialectPrefix(), + "repl-", true); if (replaceAttributes.isEmpty()) { return model; @@ -199,8 +184,7 @@ private IModel replaceAllAttributeValues(Map attributes, IModel clonedModel = model.cloneModel(); int size = model.size(); for (int i = 0; i < size; i++) { - ITemplateEvent replacedEvent = replaceAttributeValue(context, - clonedModel.get(i), replaceAttributes); + ITemplateEvent replacedEvent = replaceAttributeValue(context, clonedModel.get(i), replaceAttributes); if (replacedEvent != null) { clonedModel.replace(i, replacedEvent); } @@ -209,46 +193,38 @@ private IModel replaceAllAttributeValues(Map attributes, return clonedModel; } - private ITemplateEvent replaceAttributeValue(ITemplateContext context, - ITemplateEvent model, Map replaceValueMap) { + private ITemplateEvent replaceAttributeValue(ITemplateContext context, ITemplateEvent model, + Map replaceValueMap) { IProcessableElementTag firstEvent = null; - if (!replaceValueMap.isEmpty() - && model instanceof IProcessableElementTag) { + if (!replaceValueMap.isEmpty() && model instanceof IProcessableElementTag) { final IModelFactory modelFactory = context.getModelFactory(); firstEvent = (IProcessableElementTag) model; - for (Map.Entry entry : firstEvent.getAttributeMap() - .entrySet()) { + for (Map.Entry entry : firstEvent.getAttributeMap().entrySet()) { String oldAttrValue = entry.getValue(); String replacePart = getReplaceAttributePart(oldAttrValue); - if (replacePart != null - && replaceValueMap.containsKey(replacePart)) { - String newStringValue = - oldAttrValue.replace("?[" + replacePart + "]", - replaceValueMap.get(replacePart)); - firstEvent = modelFactory.replaceAttribute(firstEvent, - AttributeNames.forTextName(entry.getKey()), - entry.getKey(), newStringValue); + if (replacePart != null && replaceValueMap.containsKey(replacePart)) { + String newStringValue = oldAttrValue.replace("?[" + replacePart + "]", + replaceValueMap.get(replacePart)); + firstEvent = modelFactory.replaceAttribute(firstEvent, AttributeNames.forTextName(entry.getKey()), + entry.getKey(), newStringValue); } } } return firstEvent; } - private Map findAllAttributesStartsWith( - final Map attributes, final String prefix, - final String attributeName, boolean removeStart) { + private Map findAllAttributesStartsWith(final Map attributes, final String prefix, + final String attributeName, boolean removeStart) { Map matchingAttributes = new HashMap<>(); for (Map.Entry entry : attributes.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); if (key.startsWith(prefix + ":" + attributeName) - || key.startsWith("data-" + prefix + "-" + attributeName)) { + || key.startsWith("data-" + prefix + "-" + attributeName)) { if (removeStart) { - key = key.replaceAll("^" + prefix + ":" + attributeName, - ""); - key = key.replaceAll( - "^data-" + prefix + "-" + attributeName, ""); + key = key.replaceAll("^" + prefix + ":" + attributeName, ""); + key = key.replaceAll("^data-" + prefix + "-" + attributeName, ""); } matchingAttributes.put(key, value); } diff --git a/src/main/java/de/morphbit/thymeleaf/processor/OnceAttributeTagProcessor.java b/src/main/java/de/morphbit/thymeleaf/processor/OnceAttributeTagProcessor.java index 42a0996..1e79b71 100644 --- a/src/main/java/de/morphbit/thymeleaf/processor/OnceAttributeTagProcessor.java +++ b/src/main/java/de/morphbit/thymeleaf/processor/OnceAttributeTagProcessor.java @@ -23,8 +23,7 @@ import org.thymeleaf.standard.processor.AbstractStandardConditionalVisibilityTagProcessor; import org.thymeleaf.templatemode.TemplateMode; -public class OnceAttributeTagProcessor - extends AbstractStandardConditionalVisibilityTagProcessor { +public class OnceAttributeTagProcessor extends AbstractStandardConditionalVisibilityTagProcessor { public static final int PRECEDENCE = 300; public static final String ATTR_NAME = "once"; @@ -40,9 +39,8 @@ public OnceAttributeTagProcessor(String dialectPrefix) { } @Override - protected boolean isVisible(ITemplateContext context, - IProcessableElementTag tag, AttributeName attributeName, - String attributeValue) { + protected boolean isVisible(ITemplateContext context, IProcessableElementTag tag, AttributeName attributeName, + String attributeValue) { Ids ids = new Ids(context); String id = ids.seq(attributeValue); return (attributeValue + "1").equals(id); diff --git a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java index d896224..200fbb3 100644 --- a/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java +++ b/src/test/java/de/morphbit/thymeleaf/base/AbstractThymeleafComponentDialectTest.java @@ -1,14 +1,13 @@ package de.morphbit.thymeleaf.base; +import de.morphbit.thymeleaf.dialect.ComponentDialect; +import de.morphbit.thymeleaf.parser.StandardThymeleafComponentParser; import org.junit.jupiter.api.BeforeAll; 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 abstract class AbstractThymeleafComponentDialectTest { private static final String BASE_PATH = "templates"; @@ -25,8 +24,7 @@ protected String processThymeleafFile(String fileName, Context context) { } private static void setupThymeleaf() { - ClassLoaderTemplateResolver templateResolver = - new ClassLoaderTemplateResolver(); + ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setCacheable(false); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); @@ -35,9 +33,8 @@ private static void setupThymeleaf() { templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); final ComponentDialect dialect = new ComponentDialect(); - final StandardThymeleafComponentParser parser = - new StandardThymeleafComponentParser("", ".html", - "templates/components"); + final StandardThymeleafComponentParser parser = new StandardThymeleafComponentParser("", ".html", + "templates/components"); dialect.addParser(parser); templateEngine.addDialect(dialect.getPrefix(), dialect); } diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java index eaa4af3..5d069a9 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/AttributeReplaceTest.java @@ -3,16 +3,13 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; 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 { +public class AttributeReplaceTest extends AbstractThymeleafComponentDialectTest { private static final String FILE = "repl_test.html"; @@ -36,8 +33,8 @@ public void setName(String name) { @Test public void itShouldReplaceAllReplAttributes() { - String html = processThymeleafFile(FILE, new Context(Locale.ENGLISH, - Collections.singletonMap("user", new User("John")))); + 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 index 5b0d239..7e60a36 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ComponentDialectTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ComponentDialectTest.java @@ -5,18 +5,16 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import de.morphbit.thymeleaf.model.ThymeleafComponent; import java.util.HashSet; import java.util.Set; - import org.junit.jupiter.api.Test; +import org.thymeleaf.TemplateEngine; 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 @@ -29,8 +27,7 @@ public void itShouldHaveCorrectPrefixAndName() { @Test public void itShouldRegisterManualComponents() { Set components = new HashSet<>(); - components.add( - new ThymeleafComponent("my-comp", "templates/test :: fragment")); + components.add(new ThymeleafComponent("my-comp", "templates/test :: fragment")); ComponentDialect dialect = new ComponentDialect(components); Set processors = dialect.getProcessors("tc"); @@ -41,8 +38,7 @@ public void itShouldRegisterManualComponents() { @Test public void itShouldWorkWithManuallyRegisteredComponent() { - ClassLoaderTemplateResolver templateResolver = - new ClassLoaderTemplateResolver(); + ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setCacheable(false); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); @@ -52,14 +48,12 @@ public void itShouldWorkWithManuallyRegisteredComponent() { engine.setTemplateResolver(templateResolver); Set components = new HashSet<>(); - components.add(new ThymeleafComponent("link", - "templates/components/link_component :: link")); + 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()); + String html = engine.process("templates/link_with_content", new Context()); assertNotNull(html); assertFalse(html.contains("tc:link")); diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java index 0aab729..0ccdaf1 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/ContentReplaceTest.java @@ -4,22 +4,18 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; import org.junit.jupiter.api.Test; import org.thymeleaf.context.Context; -import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; - public class ContentReplaceTest extends AbstractThymeleafComponentDialectTest { - 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"; + 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_LINK_WITH_CONTENT, new Context()); + String html = processThymeleafFile(FILE_LINK_WITH_CONTENT, new Context()); assertNotNull(html); assertFalse(html.contains("tc:link")); @@ -31,8 +27,7 @@ public void itShouldNotRenderNamespaceTagsAndReplaceContent() { @Test public void itShouldReplaceContentAndConsiderVariable() { - String html = processThymeleafFile(FILE_LINK_WITH_CONTENT_AND_VARIABLE, - new Context()); + String html = processThymeleafFile(FILE_LINK_WITH_CONTENT_AND_VARIABLE, new Context()); assertNotNull(html); assertTrue(html.contains("
")); diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java index 4351555..4a0a3e4 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/MultipleComponentsTest.java @@ -4,21 +4,17 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; 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 { +public class MultipleComponentsTest extends AbstractThymeleafComponentDialectTest { @Test public void itShouldRenderMultipleComponentsOnSamePage() { - String html = processThymeleafFile("multiple_components.html", - new Context()); + String html = processThymeleafFile("multiple_components.html", new Context()); assertNotNull(html); assertFalse(html.contains("tc:alert")); @@ -38,8 +34,7 @@ public void itShouldRenderMultipleComponentsOnSamePage() { @Test public void itShouldRenderCorrectAlertTypes() { - String html = processThymeleafFile("multiple_components.html", - new Context()); + String html = processThymeleafFile("multiple_components.html", new Context()); assertNotNull(html); assertTrue(html.contains("alert-success")); @@ -48,13 +43,11 @@ public void itShouldRenderCorrectAlertTypes() { @Test public void itShouldRenderCorrectNumberOfAlerts() { - String html = processThymeleafFile("multiple_components.html", - new Context()); + 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); + assertTrue(alertCount == 2, "Expected 2 alerts but found " + alertCount); } private int countMatches(String text, String search) { diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java index 4eb40e9..7db07cb 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/NamedSelectorTest.java @@ -4,17 +4,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; 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()); + String html = processThymeleafFile("named_selector.html", new Context()); assertNotNull(html); assertFalse(html.contains("tc:link-named")); diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java index 6b79f64..afc8a43 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/NestedComponentTest.java @@ -4,17 +4,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; 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()); + String html = processThymeleafFile("nested_components.html", new Context()); assertNotNull(html); assertFalse(html.contains("tc:card")); diff --git a/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java b/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java index f73cb8c..7f32948 100644 --- a/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java +++ b/src/test/java/de/morphbit/thymeleaf/dialect/OnceAttributeTest.java @@ -4,14 +4,12 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import de.morphbit.thymeleaf.base.AbstractThymeleafComponentDialectTest; 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 OnceAttributeTest extends AbstractThymeleafComponentDialectTest { private static final String FILE = "once_test.html"; @@ -21,9 +19,7 @@ public void itShouldHaveMultipleComponentsButOneScript() { String html = processThymeleafFile(FILE, new Context()); assertNotNull(html); - assertTrue(countMatches( - "\\