diff --git a/cms-templates/src/main/java/com/condation/cms/templates/TemplateEngineFactory.java b/cms-templates/src/main/java/com/condation/cms/templates/TemplateEngineFactory.java index 7c0eabae4..bd08db4f0 100644 --- a/cms-templates/src/main/java/com/condation/cms/templates/TemplateEngineFactory.java +++ b/cms-templates/src/main/java/com/condation/cms/templates/TemplateEngineFactory.java @@ -3,6 +3,7 @@ import com.condation.cms.api.cache.ICache; import com.condation.cms.templates.filter.impl.DateFilter; import com.condation.cms.templates.filter.impl.DefaultFilter; +import com.condation.cms.templates.filter.impl.MarkdownFilter; import com.condation.cms.templates.filter.impl.RawFilter; import com.condation.cms.templates.filter.impl.UpperFilter; @@ -97,7 +98,8 @@ public TemplateEngineFactory defaultFilters() { .registerFilter(DateFilter.NAME, new DateFilter()) .registerFilter(UpperFilter.NAME, new UpperFilter()) .registerFilter(RawFilter.NAME, new RawFilter()) - .registerFilter(DefaultFilter.NAME, new DefaultFilter()); + .registerFilter(DefaultFilter.NAME, new DefaultFilter()) + .registerFilter(MarkdownFilter.NAME, new MarkdownFilter()); return this; } diff --git a/cms-templates/src/main/java/com/condation/cms/templates/filter/impl/MarkdownFilter.java b/cms-templates/src/main/java/com/condation/cms/templates/filter/impl/MarkdownFilter.java new file mode 100644 index 000000000..6e59f2eb7 --- /dev/null +++ b/cms-templates/src/main/java/com/condation/cms/templates/filter/impl/MarkdownFilter.java @@ -0,0 +1,51 @@ +package com.condation.cms.templates.filter.impl; + +/*- + * #%L + * cms-templates + * %% + * Copyright (C) 2023 - 2026 CondationCMS + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program. If not, see + * . + * #L% + */ + +import com.condation.cms.api.feature.features.MarkdownRendererFeature; +import com.condation.cms.api.request.RequestContextScope; +import com.condation.cms.templates.filter.Filter; + +/** + * + * @author thmar + */ +public class MarkdownFilter implements Filter { + + public static final String NAME = "markdown"; + + @Override + public Object apply(Object input, Object... params) { + if (input == null || !(input instanceof String)) { + return input; + } + + var requestContext = RequestContextScope.REQUEST_CONTEXT.get(); + + if (requestContext.has(MarkdownRendererFeature.class)) { + return requestContext.get(MarkdownRendererFeature.class).markdownRenderer().render((String)input); + } + + return input; + } +} diff --git a/cms-templates/src/test/java/com/condation/cms/templates/filter/FilterTest.java b/cms-templates/src/test/java/com/condation/cms/templates/filter/FilterTest.java index e2f6474a0..e518c3e0e 100644 --- a/cms-templates/src/test/java/com/condation/cms/templates/filter/FilterTest.java +++ b/cms-templates/src/test/java/com/condation/cms/templates/filter/FilterTest.java @@ -21,8 +21,12 @@ * . * #L% */ - +import com.condation.cms.api.feature.features.MarkdownRendererFeature; +import com.condation.cms.api.markdown.MarkdownRenderer; +import com.condation.cms.api.request.RequestContext; +import com.condation.cms.api.request.RequestContextScope; import com.condation.cms.templates.filter.impl.DateFilter; +import com.condation.cms.templates.filter.impl.MarkdownFilter; import com.condation.cms.templates.filter.impl.RawFilter; import java.text.SimpleDateFormat; import java.util.Date; @@ -30,79 +34,77 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class FilterTest { - FilterRegistry registry = new FilterRegistry(); - FilterPipeline pipeline = new FilterPipeline(registry); - - @BeforeEach - public void setup() { - // Register filters - registry.register("raw", (input, params) -> input); // Raw does nothing - registry.register("truncate", (input, params) -> { - if (input instanceof String stringValue) { - int length = params.length > 0 ? (Integer)params[0] : stringValue.length(); - return stringValue.length() > length ? stringValue.substring(0, length) + "..." : input; - } - return input; - }); - - pipeline.addStep("raw"); - pipeline.addStep("truncate", 20); - } - - @Test - void test() { - Object result = pipeline.execute("Dies ist ein langer Text, der abgeschnitten werden sollte."); - Assertions.assertThat(result).isEqualTo("Dies ist ein langer ..."); - } - + FilterRegistry registry = new FilterRegistry(); + FilterPipeline pipeline = new FilterPipeline(registry); + + @BeforeEach + public void setup() { + // Register filters + registry.register("raw", (input, params) -> input); // Raw does nothing + registry.register("truncate", (input, params) -> { + if (input instanceof String stringValue) { + int length = params.length > 0 ? (Integer) params[0] : stringValue.length(); + return stringValue.length() > length ? stringValue.substring(0, length) + "..." : input; + } + return input; + }); + + pipeline.addStep("raw"); + pipeline.addStep("truncate", 20); + } + + @Test + void test() { + Object result = pipeline.execute("Dies ist ein langer Text, der abgeschnitten werden sollte."); + Assertions.assertThat(result).isEqualTo("Dies ist ein langer ..."); + } + @Test - void date() { - + void date() { + FilterRegistry registry = new FilterRegistry(); FilterPipeline pipeline = new FilterPipeline(registry); registry.register(DateFilter.NAME, new DateFilter()); - + pipeline.addStep("date"); - - + var date = new Date(); SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy"); var formatted = format.format(date); - - Object result = pipeline.execute(date); - Assertions.assertThat(result).isEqualTo(formatted); - } - + + Object result = pipeline.execute(date); + Assertions.assertThat(result).isEqualTo(formatted); + } + @Test - void date_custom_format() { - + void date_custom_format() { + FilterRegistry registry = new FilterRegistry(); FilterPipeline pipeline = new FilterPipeline(registry); registry.register(DateFilter.NAME, new DateFilter()); - + pipeline.addStep("date", "MM/yyyy"); - - + var date = new Date(); SimpleDateFormat format = new SimpleDateFormat("MM/yyyy"); var formatted = format.format(date); - - Object result = pipeline.execute(date); - Assertions.assertThat(result).isEqualTo(formatted); - } - + + Object result = pipeline.execute(date); + Assertions.assertThat(result).isEqualTo(formatted); + } + @Test - void raw() { - + void raw() { FilterRegistry registry = new FilterRegistry(); FilterPipeline pipeline = new FilterPipeline(registry); registry.register(RawFilter.NAME, new RawFilter()); - + pipeline.addStep("raw"); - + String input = """

"We believe that great content is the foundation for successful communication and lasting connections. With Condation, we aim to create the base where ideas can grow and thrive. Our goal is to provide a solid, reliable platform that enables everyone to easily create, manage, and share their content—helping to change the world, one idea at a time."

"""; @@ -110,5 +112,25 @@ void raw() { String escaped = StringEscapeUtils.ESCAPE_HTML4.translate(input); Object result = pipeline.execute(escaped); Assertions.assertThat(result).isEqualTo(input); - } + } + + @Test + void markdown() { + FilterRegistry registry = new FilterRegistry(); + FilterPipeline pipeline = new FilterPipeline(registry); + registry.register(MarkdownFilter.NAME, new MarkdownFilter()); + pipeline.addStep("markdown"); + + var markdownRenderer = Mockito.mock(MarkdownRenderer.class); + Mockito.when(markdownRenderer.render(Mockito.any())).thenReturn(""); + + RequestContext context = new RequestContext(); + context.add(MarkdownRendererFeature.class, new MarkdownRendererFeature(markdownRenderer)); + ScopedValue.where(RequestContextScope.REQUEST_CONTEXT, context).run(() -> { + String input = "input string"; + pipeline.execute(input); + + Mockito.verify(markdownRenderer, Mockito.times(1)).render(input); + }); + } }