diff --git a/.github/workflows/bld.yml b/.github/workflows/bld.yml index 129b60f..21791c9 100644 --- a/.github/workflows/bld.yml +++ b/.github/workflows/bld.yml @@ -1,6 +1,6 @@ name: bld-ci -on: [ push, pull_request, workflow_dispatch ] +on: [push, pull_request, workflow_dispatch] jobs: build-bld-project: @@ -8,28 +8,25 @@ jobs: strategy: matrix: - java-version: [ 17, 19, 20 ] + java-version: [17, 21, 23] steps: - name: Checkout source repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK ${{ matrix.java-version }} - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - distribution: 'zulu' + distribution: "zulu" java-version: ${{ matrix.java-version }} - - name: Grant execute permission for bld - run: chmod +x bld - - - name: Download the dependencies + - name: Download dependencies run: ./bld download - - name: Run tests with bld + - name: Run tests run: >- ./bld compile test -DtestsBadgeUrl=https://rife2.com/tests-badge/update/com.uwyn.rife2/rife2-renderers - -DtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} \ No newline at end of file + -DtestsBadgeApiKey=${{ secrets.TESTS_BADGE_API_KEY }} diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 0236ccd..508f6a5 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -3,7 +3,7 @@ name: javadocs-pages on: # Runs on pushes targeting the default branch push: - branches: [ "master" ] + branches: ["master"] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -30,14 +30,14 @@ jobs: steps: - name: Checkout source repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK 17 - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - distribution: 'zulu' + distribution: "zulu" java-version: 17 - name: Build Javadocs @@ -47,11 +47,11 @@ jobs: uses: actions/configure-pages@v3 - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: # Upload generated Javadocs repository - path: 'build/javadoc/' + path: "build/javadoc/" - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 \ No newline at end of file + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index bcbe7bf..1a64ef3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,9 +1,9 @@ -name: Publish to the Maven Central +name: Publish to the Maven Central/Rife2 on: workflow_dispatch: release: - types: [ released ] + types: [released] jobs: build-bld-project: @@ -11,23 +11,23 @@ jobs: steps: - name: Checkout source repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up JDK - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - distribution: 'temurin' + distribution: "temurin" java-version: 17 - - name: Grant execute permission for bld - run: chmod +x bld - - - name: Download the dependencies + - name: Download dependencies run: ./bld download - - name: Publish with bld + - name: Import key + run: echo "${{ secrets.SIGN_SECRET_KEY }}" | gpg --batch --import + + - name: Publish run: >- ./bld compile test publish -DtestsBadgeUrl=https://rife2.com/tests-badge/update/com.uwyn.rife2/rife2-renderers @@ -38,3 +38,6 @@ jobs: -DsonatypePassword=${{ secrets.SONATYPE_PASSWORD }} -DsignKey=${{ secrets.SIGN_KEY }} -DsignPassphrase=${{ secrets.SIGN_PASSPHRASE }} + + - name: Delete GnuPG data + run: rm -rfv $HOME/.gnupg diff --git a/.idea/bld.xml b/.idea/bld.xml new file mode 100644 index 0000000..6600cee --- /dev/null +++ b/.idea/bld.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..d91f848 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/Apache_License.xml b/.idea/copyright/Apache_License.xml index 606a6ad..a780185 100644 --- a/.idea/copyright/Apache_License.xml +++ b/.idea/copyright/Apache_License.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/icon.svg b/.idea/icon.svg new file mode 100644 index 0000000..4d21850 --- /dev/null +++ b/.idea/icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/.idea/intellij-javadocs-4.0.1.xml b/.idea/intellij-javadocs-4.0.1.xml new file mode 100644 index 0000000..0e6ccfe --- /dev/null +++ b/.idea/intellij-javadocs-4.0.1.xml @@ -0,0 +1,204 @@ + + + + + UPDATE + false + true + + TYPE + FIELD + METHOD + + + DEFAULT + PROTECTED + PUBLIC + + + + + + ^.*(public|protected|private)*.+interface\s+\w+.* + /**\n + * The interface ${name}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> + */ + + + ^.*(public|protected|private)*.+enum\s+\w+.* + /**\n + * The enum ${name}.\n + */ + + + ^.*(public|protected|private)*.+class\s+\w+.* + /**\n + * The type ${name}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> + */ + + + .+ + /**\n + * The type ${name}.\n + */ + + + + + .+ + /**\n + * Instantiates a new ${name}.\n +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + + + ^.*(public|protected|private)*\s*.*(\w(\s*<.+>)*)+\s+get\w+\s*\(.*\).+ + /**\n + * Gets ${partName}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${partName}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + ^.*(public|protected|private)*\s*.*(void|\w(\s*<.+>)*)+\s+set\w+\s*\(.*\).+ + /**\n + * Sets ${partName}.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${partName}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + ^.*((public\s+static)|(static\s+public))\s+void\s+main\s*\(\s*String\s*(\[\s*\]|\.\.\.)\s+\w+\s*\).+ + /**\n + * The entry point of application.\n + + <#if element.parameterList.parameters?has_content> + *\n +</#if> + * @param ${element.parameterList.parameters[0].name} the input arguments\n +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + .+ + /**\n + * ${name}<#if isNotVoid> ${return}</#if>.\n +<#if element.typeParameters?has_content> * \n +</#if> +<#list element.typeParameters as typeParameter> + * @param <${typeParameter.name}> the type parameter\n +</#list> +<#if element.parameterList.parameters?has_content> + *\n +</#if> +<#list element.parameterList.parameters as parameter> + * @param ${parameter.name} the ${paramNames[parameter.name]}\n +</#list> +<#if isNotVoid> + *\n + * @return the ${return}\n +</#if> +<#if element.throwsList.referenceElements?has_content> + *\n +</#if> +<#list element.throwsList.referenceElements as exception> + * @throws ${exception.referenceName} the ${exceptionNames[exception.referenceName]}\n +</#list> + */ + + + + + ^.*(public|protected|private)*.+static.*(\w\s\w)+.+ + /**\n + * The constant ${element.getName()}.\n + */ + + + ^.*(public|protected|private)*.*(\w\s\w)+.+ + /**\n + <#if element.parent.isInterface()> + * The constant ${element.getName()}.\n +<#else> + * The ${name}.\n +</#if> */ + + + .+ + /**\n + <#if element.parent.isEnum()> + *${name} ${typeName}.\n +<#else> + * The ${name}.\n +</#if>*/ + + + + + \ No newline at end of file diff --git a/.idea/libraries/bld.xml b/.idea/libraries/bld.xml index 1bc7dda..153a060 100644 --- a/.idea/libraries/bld.xml +++ b/.idea/libraries/bld.xml @@ -2,11 +2,12 @@ - + - + + @@ -14,4 +15,4 @@ - \ No newline at end of file + diff --git a/.idea/libraries/compile.xml b/.idea/libraries/compile.xml index 9bd86aa..99cc0c0 100644 --- a/.idea/libraries/compile.xml +++ b/.idea/libraries/compile.xml @@ -7,7 +7,7 @@ - - + + \ No newline at end of file diff --git a/.idea/libraries/runtime.xml b/.idea/libraries/runtime.xml index 81feb0b..56ddbf1 100644 --- a/.idea/libraries/runtime.xml +++ b/.idea/libraries/runtime.xml @@ -7,7 +7,7 @@ - - + + \ No newline at end of file diff --git a/.idea/libraries/test.xml b/.idea/libraries/test.xml index 13b6513..f72f7a3 100644 --- a/.idea/libraries/test.xml +++ b/.idea/libraries/test.xml @@ -7,7 +7,7 @@ - - + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 542659b..2fa2388 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,22 @@ + + + + + + diff --git a/.vscode/settings.json b/.vscode/settings.json index e04f1cd..ba429d0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,13 +3,13 @@ "src/main/java", "src/main/resources", "src/test/java", - "src/bld/java" + "src/test/resources", + "src/bld/java", + "src/bld/resources" ], "java.configuration.updateBuildConfiguration": "automatic", "java.project.referencedLibraries": [ - "${HOME}/.rife2/dist/rife2-1.5.18.jar", - "lib/compile/*.jar", - "lib/runtime/*.jar", - "lib/test/*.jar" + "${HOME}/.bld/dist/bld-2.2.1.jar", + "lib/**/*.jar" ] } diff --git a/README.md b/README.md index ea261b7..0e85de6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ [![License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Java](https://img.shields.io/badge/java-17%2B-blue)](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html) +[![bld](https://img.shields.io/badge/2.2.1-FA9052?label=bld&labelColor=2392FF)](https://rife2.com/bld) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/rife2/rife2-template-renderers)](https://github.com/rife2/rife2-template-renderers/releases/latest) -[![Maven Central](https://img.shields.io/maven-central/v/com.uwyn.rife2/rife2-renderers)](https://central.sonatype.com/artifact/com.uwyn.rife2/rife2-renderers/1.1.0) +[![Release](https://flat.badgen.net/maven/v/metadata-url/repo.rife2.com/releases/com/uwyn/rife2/rife2-renderers/maven-metadata.xml?color=blue)](https://repo.rife2.com/#/releases/com/uwyn/rife2/rife2-renderers) +[![Maven Central](https://img.shields.io/maven-central/v/com.uwyn.rife2/rife2-renderers)](https://central.sonatype.com/artifact/com.uwyn.rife2/rife2-renderers/) [![Nexus Snapshot](https://img.shields.io/nexus/s/com.uwyn.rife2/rife2-renderers?server=https%3A%2F%2Fs01.oss.sonatype.org%2F)](https://s01.oss.sonatype.org/content/repositories/snapshots/com/uwyn/rife2/rife2-renderers/) [![GitHub CI](https://github.com/rife2/rife2-template-renderers/actions/workflows/bld.yml/badge.svg)](https://github.com/rife2/rife2-template-renderers/actions/workflows/bld.yml) [![Tests](https://rife2.com/tests-badge/badge/com.uwyn.rife2/rife2-renderers)](https://github.com/rife2/rife2-template-renderers/actions/workflows/gradle.yml) @@ -49,16 +51,17 @@ This project provides a collection of useful template renderers. ## Text Renderers -| Renderer | Description | -|:------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------| -| [rife.render.Capitalize](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Capitalize) | Capitalizes a template value | -| [rife.render.Lowercase](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Lowercase) | Converts a template value to lowercase | -| [rife.render.Rot13](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Rot13) | Translates a template value to/from ROT13 | -| [rife.render.SwapCase](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.SwapCase) | Swap case of a template value | -| [rife.render.Trim](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Trim) | Removes leading and trailing whitespace from a template value | -| [rife.render.Uncapitalize](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Uncapitalize) | Uncapitalizes a template value | -| [rife.render.Uppercase](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Uppercase) | Converts a template value to uppercase | +| Renderer | Description | +|:------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------| +| [rife.render.Capitalize](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Capitalize) | Capitalizes a template value | +| [rife.render.CapitalizeWords](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.CapitalizeWords) | Capitalizes words of a template value | +| [rife.render.Lowercase](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Lowercase) | Converts a template value to lowercase | +| [rife.render.Rot13](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Rot13) | Translates a template value to/from ROT13 | +| [rife.render.SwapCase](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.SwapCase) | Swaps case of a template value | +| [rife.render.Trim](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Trim) | Removes leading and trailing whitespace from a template value | +| [rife.render.Uncapitalize](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Uncapitalize) | Uncapitalizes a template value | +| [rife.render.Uppercase](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Uppercase) | Converts a template value to uppercase | ## Documentation -Read more in the [documenation](https://github.com/rife2/rife2-template-renderers/wiki). +Read more in the [documentation](https://github.com/rife2/rife2-template-renderers/wiki). diff --git a/config/pmd.xml b/config/pmd.xml index 8811583..2641880 100644 --- a/config/pmd.xml +++ b/config/pmd.xml @@ -7,8 +7,9 @@ - - + + + @@ -25,7 +26,6 @@ - @@ -35,8 +35,15 @@ - + + + + + + + + @@ -46,8 +53,6 @@ - - @@ -74,7 +79,6 @@ - @@ -90,13 +94,6 @@ - - - - ^ignore$ - - - diff --git a/lib/bld/bld-wrapper.jar b/lib/bld/bld-wrapper.jar index a2bd323..1c1580c 100644 Binary files a/lib/bld/bld-wrapper.jar and b/lib/bld/bld-wrapper.jar differ diff --git a/lib/bld/bld-wrapper.properties b/lib/bld/bld-wrapper.properties index 04bc59a..c1d316f 100644 --- a/lib/bld/bld-wrapper.properties +++ b/lib/bld/bld-wrapper.properties @@ -1,6 +1,8 @@ bld.downloadExtensionJavadoc=false bld.downloadExtensionSources=true -bld.extension-tests=com.uwyn.rife2:bld-tests-badge:1.1.0 -bld.repositories=MAVEN_CENTRAL,RIFE2_RELEASES -rife2.downloadLocation= -rife2.version=1.5.18 \ No newline at end of file +bld.downloadLocation= +bld.extension-jacoco=com.uwyn.rife2:bld-jacoco-report:0.9.9 +bld.extension-pmd=com.uwyn.rife2:bld-pmd:1.2.0 +bld.extension-tests=com.uwyn.rife2:bld-tests-badge:1.4.6 +bld.repositories=MAVEN_CENTRAL,MAVEN_LOCAL,RIFE2_SNAPSHOTS,RIFE2_RELEASES +bld.version=2.2.1 diff --git a/src/bld/java/rife/render/TemplateRenderersBuild.java b/src/bld/java/rife/render/TemplateRenderersBuild.java index 0ccafe1..4f4fc5e 100644 --- a/src/bld/java/rife/render/TemplateRenderersBuild.java +++ b/src/bld/java/rife/render/TemplateRenderersBuild.java @@ -1,6 +1,26 @@ +/* + * Copyright 2023-2024 the original author or authors. + * + * 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 + * + * https://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. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + package rife.render; +import rife.bld.BuildCommand; import rife.bld.Project; +import rife.bld.extension.JacocoReportOperation; +import rife.bld.extension.PmdOperation; import rife.bld.extension.TestsBadgeOperation; import rife.bld.publish.PublishDeveloper; import rife.bld.publish.PublishInfo; @@ -10,7 +30,8 @@ import rife.bld.publish.PublishScm; import java.util.List; import static rife.bld.dependencies.Repository.*; -import static rife.bld.dependencies.Scope.*; +import static rife.bld.dependencies.Scope.compile; +import static rife.bld.dependencies.Scope.test; import static rife.bld.operations.JavadocOptions.DocLinkOption.NO_MISSING; public class TemplateRenderersBuild extends Project { @@ -19,64 +40,86 @@ public class TemplateRenderersBuild extends Project { public TemplateRenderersBuild() { pkg = "rife.render"; name = "rife2-template-renderers"; - version = version(1, 1, 1); + version = version(1, 2, 1, "SNAPSHOT"); + + javaRelease = 17; + downloadSources = true; + autoDownloadPurge = true; + repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES); + + scope(compile) + .include(dependency("com.uwyn.rife2", "rife2", version(1, 9, 1))); + scope(test) + .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 12, 0))) + .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 12, 0))) + .include(dependency("org.assertj", "assertj-core", version(3, 27, 3))); javadocOperation().javadocOptions() .docTitle("RIFE2 Template Renderers") + .author() .docLint(NO_MISSING) .link("https://rife2.github.io/rife2/"); publishOperation() - .repository(version.isSnapshot() ? repository(RIFE2_SNAPSHOTS.location()) - .withCredentials(property("rife2Username"), property("rife2Password")) - : repository(RIFE2_RELEASES.location()) - .withCredentials(property("rife2Username"), property("rife2Password"))) - .repository(repository(SONATYPE_RELEASES.location()) + .repository(version.isSnapshot() ? SONATYPE_SNAPSHOTS + .withCredentials(property("sonatypeUser"), property("sonatypePassword")) + : SONATYPE_RELEASES .withCredentials(property("sonatypeUser"), property("sonatypePassword"))) + .repository(version.isSnapshot() ? RIFE2_SNAPSHOTS + .withCredentials(property("rife2Username"), property("rife2Password")) + : RIFE2_RELEASES + .withCredentials(property("rife2Username"), property("rife2Password"))) .info(new PublishInfo() .groupId("com.uwyn.rife2") .artifactId("rife2-renderers") .name("RIFE2 Template Renderers") .description("Template Renderers for the RIFE2 web framework") .url("https://github.com/rife2/rife2-template-renderers") - .developer(new PublishDeveloper().id("ethauvin").name("Erik C. Thauvin").email("erik@thauvin.net") + .developer(new PublishDeveloper() + .id("ethauvin") + .name("Erik C. Thauvin") + .email("erik@thauvin.net") .url("https://erik.thauvin.net/")) - .developer(new PublishDeveloper().id("gbevin").name("Geert Bevin").email("gbevin@uwyn.com") + .developer(new PublishDeveloper() + .id("gbevin") + .name("Geert Bevin") + .email("gbevin@uwyn.com") .url("https://github.com/gbevin")) - .license(new PublishLicense().name("The Apache License, Version 2.0") - .url("http://www.apache.org/licenses/LICENSE-2.0.txt")) - .scm(new PublishScm().connection("scm:git:https://github.com/rife2/rife2-template-renderers.git") + .license(new PublishLicense() + .name("The Apache License, Version 2.0") + .url("https://www.apache.org/licenses/LICENSE-2.0.txt")) + .scm(new PublishScm() + .connection("scm:git:https://github.com/rife2/rife2-template-renderers.git") .developerConnection("scm:git:git@github.com:rife2/rife2-template-renderers.git") .url("https://github.com/rife2/rife2-template-renderers")) .signKey(property("signKey")) .signPassphrase(property("signPassphrase"))); - - javaRelease = 17; - downloadSources = true; - autoDownloadPurge = true; - repositories = List.of(MAVEN_CENTRAL, RIFE2_RELEASES, RIFE2_SNAPSHOTS); - - scope(compile) - .include(dependency("com.uwyn.rife2", "rife2", version(1, 5, 18))); - scope(test) - .include(dependency("org.junit.jupiter", "junit-jupiter", version(5, 9, 2))) - .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1, 9, 2))) - .include(dependency("org.assertj:assertj-core:3.24.2")); } public static void main(String[] args) { new TemplateRenderersBuild().start(args); } + @BuildCommand(summary = "Generates JaCoCo Reports") + public void jacoco() throws Exception { + new JacocoReportOperation() + .fromProject(this) + .execute(); + } + + @BuildCommand(summary = "Runs PMD analysis") + public void pmd() throws Exception { + new PmdOperation() + .fromProject(this) + .failOnViolation(true) + .ruleSets("config/pmd.xml") + .execute(); + } + public void test() throws Exception { testsBadgeOperation.executeOnce(() -> testsBadgeOperation .url(property("testsBadgeUrl")) .apiKey(property("testsBadgeApiKey")) .fromProject(this)); } - - @Override - public void precompile() throws Exception { - // TODO remove when fixed in bld - } -} \ No newline at end of file +} diff --git a/src/main/java/rife/render/Abbreviate.java b/src/main/java/rife/render/Abbreviate.java index 89f6991..dfacacb 100644 --- a/src/main/java/rife/render/Abbreviate.java +++ b/src/main/java/rife/render/Abbreviate.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import rife.template.Template; import rife.template.ValueRenderer; /** - *

Abbreviate a template value with ellipses.

+ *

Abbreviates a template value with ellipses.

* *

Usage:

* @@ -36,7 +36,18 @@ import rife.template.ValueRenderer; */ public class Abbreviate implements ValueRenderer { /** - * {@inheritDoc} + *

Returns the template value abbreviated with ellipses.

+ * + *

Two parameters can be specified:

+ *
    + *
  • mark: the string that will be used to abbreviate the value. Default is ...
  • + *
  • max: the maximum number of characters to render. Default is -1 (no abbreviation).
  • + *
+ * + * @param template the template that contains the value + * @param valueId the id of the value to render + * @param differentiator a generic string that can be used to differentiate the rendering + * @return the abbreviated value, or the original value if no abbreviation is necessary */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/BeatTime.java b/src/main/java/rife/render/BeatTime.java index dd4cfad..f11f97f 100644 --- a/src/main/java/rife/render/BeatTime.java +++ b/src/main/java/rife/render/BeatTime.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import java.time.ZonedDateTime; */ public class BeatTime implements ValueRenderer { /** - * {@inheritDoc} + * Returns the current time in Swatch Internet (.beat) Time format. + * + * @param template the template instance + * @param valueId the value id + * @param differentiator the differentiator + * @return the rendered value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Capitalize.java b/src/main/java/rife/render/Capitalize.java index dc4c126..e0d769f 100644 --- a/src/main/java/rife/render/Capitalize.java +++ b/src/main/java/rife/render/Capitalize.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,12 @@ import rife.tools.StringUtils; */ public class Capitalize implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value by capitalizing it. + * + * @param template the template containing the value to be rendered + * @param valueId the identifier of the value to render + * @param differentiator a string used to differentiate the rendering + * @return the capitalized and encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/CapitalizeWords.java b/src/main/java/rife/render/CapitalizeWords.java new file mode 100644 index 0000000..e95e6f8 --- /dev/null +++ b/src/main/java/rife/render/CapitalizeWords.java @@ -0,0 +1,50 @@ +/* + * Copyright 2023-2024 the original author or authors. + * + * 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 + * + * https://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. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package rife.render; + +import rife.template.Template; +import rife.template.ValueRenderer; + +/** + *

Capitalizes words of a template value.

+ * + *

Usage:

+ * + *
+ *   <!--v render:rife.render.CapitalizeWords:valueId/-->
+ *   {{v render:rife.render.CapitalizeWords:valueId/}}
+ * 
+ * + * @author Erik C. Thauvin + * @see rife.render.CapitalizeWords + * @since 1.2 + */ +public class CapitalizeWords implements ValueRenderer { + /** + * Returns the template value by capitalizing it. + * + * @param template the template containing the value to be rendered + * @param valueId the identifier of the value to render + * @param differentiator a string used to differentiate the rendering + * @return the capitalized and encoded value + */ + @Override + public String render(Template template, String valueId, String differentiator) { + return template.getEncoder().encode(RenderUtils.capitalizeWords(template.getValueOrAttribute(differentiator))); + } +} diff --git a/src/main/java/rife/render/DateIso.java b/src/main/java/rife/render/DateIso.java index 3fe35c6..0da04e6 100644 --- a/src/main/java/rife/render/DateIso.java +++ b/src/main/java/rife/render/DateIso.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import rife.template.ValueRenderer; import java.time.ZonedDateTime; /** - *

Return the current date in ISO 8601 format.

+ *

Renders the current date in ISO 8601 format.

* *

Usage:

* @@ -38,7 +38,12 @@ import java.time.ZonedDateTime; */ public class DateIso implements ValueRenderer { /** - * {@inheritDoc} + * Returns the current date in ISO 8601 format, encoded according to the template's encoding rules. + * + * @param template the template that is currently being rendered + * @param valueId the value id that triggers the rendering of this value renderer + * @param differentiator a differentiator that may be used to differentiate the rendering of this value renderer + * @return the current date in ISO 8601 format, encoded according to the template's encoding rules */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/DateTimeIso.java b/src/main/java/rife/render/DateTimeIso.java index 9a8bb63..e8513bb 100644 --- a/src/main/java/rife/render/DateTimeIso.java +++ b/src/main/java/rife/render/DateTimeIso.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; /** - *

Return the current date and time in ISO 8601 format.

+ *

Renders the current date and time in ISO 8601 format.

* *

Usage:

* @@ -39,7 +39,15 @@ import java.time.ZonedDateTime; */ public class DateTimeIso implements ValueRenderer { /** - * {@inheritDoc} + * Renders the current date and time in ISO 8601 format. + * + *

Additionally, it allows specifying a time zone through the template's default value properties with the key + * {@code tz}. If no time zone is specified, the system default time zone is used.

+ * + * @param template the template that is currently being rendered + * @param valueId the id of the value to be rendered + * @param differentiator a differentiator that may be used to differentiate the rendering of this value renderer + * @return the current date and time in ISO 8601 format */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/DateTimeRfc2822.java b/src/main/java/rife/render/DateTimeRfc2822.java index a420201..2bdbd54 100644 --- a/src/main/java/rife/render/DateTimeRfc2822.java +++ b/src/main/java/rife/render/DateTimeRfc2822.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import rife.template.ValueRenderer; import java.time.ZonedDateTime; /** - *

Return the current date and time in RFC 2822 format.

+ *

Renders the current date and time in RFC 2822 format.

* *

Usage:

* @@ -38,7 +38,12 @@ import java.time.ZonedDateTime; */ public class DateTimeRfc2822 implements ValueRenderer { /** - * {@inheritDoc} + * Returns the current date and time in RFC 2822 format. + * + * @param template the template instance + * @param valueId the value id + * @param differentiator the differentiator + * @return the current date and time in RFC 2822 format */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeBase64.java b/src/main/java/rife/render/EncodeBase64.java index fd2e62a..e00b24c 100644 --- a/src/main/java/rife/render/EncodeBase64.java +++ b/src/main/java/rife/render/EncodeBase64.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,12 @@ import java.nio.charset.StandardCharsets; */ public class EncodeBase64 implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to Base64. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the Base64-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeHtml.java b/src/main/java/rife/render/EncodeHtml.java index 858b6dd..b67959d 100644 --- a/src/main/java/rife/render/EncodeHtml.java +++ b/src/main/java/rife/render/EncodeHtml.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.tools.StringUtils; */ public class EncodeHtml implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to HTML. + * + * @param template the template containing the value to be rendered + * @param valueId the identifier of the value to render + * @param differentiator a string used to differentiate the rendering + * @return the HTML-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeHtmlEntities.java b/src/main/java/rife/render/EncodeHtmlEntities.java index 4f84839..cee3e8b 100644 --- a/src/main/java/rife/render/EncodeHtmlEntities.java +++ b/src/main/java/rife/render/EncodeHtmlEntities.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,12 @@ import rife.template.ValueRenderer; */ public class EncodeHtmlEntities implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to HTML decimal entities. + * + * @param template the template instance + * @param valueId the value id + * @param differentiator the differentiator + * @return the encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeJs.java b/src/main/java/rife/render/EncodeJs.java index 1122356..27de902 100644 --- a/src/main/java/rife/render/EncodeJs.java +++ b/src/main/java/rife/render/EncodeJs.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.tools.StringUtils; */ public class EncodeJs implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to JavaScript/ECMAScript. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the JavaScript/ECMAScript-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeJson.java b/src/main/java/rife/render/EncodeJson.java index 7356650..8e17b29 100644 --- a/src/main/java/rife/render/EncodeJson.java +++ b/src/main/java/rife/render/EncodeJson.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.tools.StringUtils; */ public class EncodeJson implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to JSON. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the JSON-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeUnicode.java b/src/main/java/rife/render/EncodeUnicode.java index 60166a1..afd2a48 100644 --- a/src/main/java/rife/render/EncodeUnicode.java +++ b/src/main/java/rife/render/EncodeUnicode.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.tools.StringUtils; */ public class EncodeUnicode implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to Unicode escape codes. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the Unicode escape codes-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeUrl.java b/src/main/java/rife/render/EncodeUrl.java index 6692636..b977353 100644 --- a/src/main/java/rife/render/EncodeUrl.java +++ b/src/main/java/rife/render/EncodeUrl.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.tools.StringUtils; */ public class EncodeUrl implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to URL. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the URL-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/EncodeXml.java b/src/main/java/rife/render/EncodeXml.java index 743e084..00b0faa 100644 --- a/src/main/java/rife/render/EncodeXml.java +++ b/src/main/java/rife/render/EncodeXml.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.tools.StringUtils; */ public class EncodeXml implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded to XML. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the XML-encoded value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/FormatCreditCard.java b/src/main/java/rife/render/FormatCreditCard.java index f2025eb..fec124d 100644 --- a/src/main/java/rife/render/FormatCreditCard.java +++ b/src/main/java/rife/render/FormatCreditCard.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,12 @@ import rife.template.ValueRenderer; */ public class FormatCreditCard implements ValueRenderer { /** - * {@inheritDoc} + * Returns the last 4 digits of the template credit number value. + * + * @param template the {@link Template} + * @param valueId the value id + * @param differentiator the differentiator + * @return the formatted value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Lowercase.java b/src/main/java/rife/render/Lowercase.java index aa7858c..6f9f2ec 100644 --- a/src/main/java/rife/render/Lowercase.java +++ b/src/main/java/rife/render/Lowercase.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,12 @@ import rife.tools.Localization; */ public class Lowercase implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value converted to lowercase. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the lowercase value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Mask.java b/src/main/java/rife/render/Mask.java index 97647eb..fe0a709 100644 --- a/src/main/java/rife/render/Mask.java +++ b/src/main/java/rife/render/Mask.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,30 @@ import rife.template.ValueRenderer; * @since 1.0 */ public class Mask implements ValueRenderer { + /** - * {@inheritDoc} + *

Renders a template value with characters of the value masked using the specified mask.

+ * + *

The mask is specified as a template default value with the following syntax:

+ * + *
+     *   mask=<mask>[,unmasked=<unmasked>][,fromStart=<fromStart>]
+     * 
+ * + *

Where:

+ * + *
    + *
  • mask is the character to use for masking, defaulting to *
  • + *
  • unmasked is the number of characters at the beginning of the value that should be left unmasked, + * defaulting to 0
  • + *
  • fromStart is a boolean indicating whether the unmasked value should be counted from + * the start of the value, defaulting to false
  • + *
+ * + * @param template the template to render the value in + * @param valueId the ID of the value to render + * @param differentiator the differentiator of the value to render + * @return the rendered value */ @Override public String render(Template template, String valueId, String differentiator) { @@ -49,7 +71,7 @@ public class Mask implements ValueRenderer { mask = properties.getProperty("mask", mask); try { unmasked = Integer.parseInt(properties.getProperty("unmasked", "0")); - } catch (NumberFormatException ignore) { + } catch (NumberFormatException ignored) { // do nothing } fromStart = "true".equalsIgnoreCase(properties.getProperty("fromStart", "false")); diff --git a/src/main/java/rife/render/Normalize.java b/src/main/java/rife/render/Normalize.java index c3e66a2..b6cb9d1 100644 --- a/src/main/java/rife/render/Normalize.java +++ b/src/main/java/rife/render/Normalize.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,12 @@ import rife.template.ValueRenderer; */ public class Normalize implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value normalized for inclusion in a URL path. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the normalized value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/QrCode.java b/src/main/java/rife/render/QrCode.java index 2875e99..47f74c0 100644 --- a/src/main/java/rife/render/QrCode.java +++ b/src/main/java/rife/render/QrCode.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,12 @@ import rife.template.ValueRenderer; */ public class QrCode implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value encoded as an SVG QR Code. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the SVG QR Code */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/RenderUtils.java b/src/main/java/rife/render/RenderUtils.java index 220c991..c05f5b9 100644 --- a/src/main/java/rife/render/RenderUtils.java +++ b/src/main/java/rife/render/RenderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import java.text.Normalizer; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoField; import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -84,7 +83,7 @@ public final class RenderUtils { DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss zzz").withLocale(Localization.getLocale()); private static final String DEFAULT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0"; - private final static Logger LOGGER = Logger.getLogger(RenderUtils.class.getName()); + private static final Logger LOGGER = Logger.getLogger(RenderUtils.class.getName()); private RenderUtils() { // no-op @@ -120,11 +119,43 @@ public final class RenderUtils { */ public static String beatTime(ZonedDateTime zonedDateTime) { var zdt = zonedDateTime.withZoneSameInstant(ZoneId.of("UTC+01:00")); - var beats = (int) ((zdt.get(ChronoField.SECOND_OF_MINUTE) + (zdt.get(ChronoField.MINUTE_OF_HOUR) * 60) + - (zdt.get(ChronoField.HOUR_OF_DAY) * 3600)) / 86.4); + var beats = (int) ((zdt.getSecond() + (zdt.getMinute() * 60) + + (zdt.getHour() * 3600)) / 86.4); return String.format("@%03d", beats); } + /** + * Returns a {@code String} with the first letter of each word capitalized. + * + * @param src the source {@code String} + * @return the capitalized {@code String} + */ + public static String capitalizeWords(String src) { + if (src == null || src.isBlank()) { + return src; + } + + var result = new StringBuilder(); + var capitalizeNext = true; + + for (var i = 0; i < src.length(); i++) { + var c = src.charAt(i); + if (Character.isWhitespace(c)) { + capitalizeNext = true; + result.append(c); + } else { + if (capitalizeNext) { + result.append(Character.toUpperCase(c)); + } else { + result.append(Character.toLowerCase(c)); + } + capitalizeNext = false; + } + } + + return result.toString(); + } + /** *

Encodes the source {@code String} to the specified encoding.

* @@ -154,7 +185,7 @@ public final class RenderUtils { return StringUtils.encodeHtml(src); } case "js" -> { - return RenderUtils.encodeJs(src); + return encodeJs(src); } case "json" -> { return StringUtils.encodeJson(src); @@ -196,6 +227,11 @@ public final class RenderUtils { case '"' -> sb.append("\\\""); case '\\' -> sb.append("\\\\"); case '/' -> sb.append("\\/"); + case '\b' -> sb.append("\\b"); + case '\n' -> sb.append(("\\n")); + case '\t' -> sb.append("\\t"); + case '\f' -> sb.append("\\f"); + case '\r' -> sb.append("\\r"); default -> sb.append(c); } } @@ -212,8 +248,9 @@ public final class RenderUtils { public static String fetchUrl(String url, String defaultContent) { try { var fetchUrl = new URL(url); + HttpURLConnection connection = null; try { - var connection = (HttpURLConnection) fetchUrl.openConnection(); + connection = (HttpURLConnection) fetchUrl.openConnection(); connection.setRequestProperty("User-Agent", DEFAULT_USER_AGENT); var code = connection.getResponseCode(); if (code >= 200 && code <= 399) { @@ -229,10 +266,15 @@ public final class RenderUtils { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.log(Level.WARNING, "An IO error occurred while connecting to " + fetchUrl.getHost(), ioe); } + } finally { + if (connection != null) { + connection.disconnect(); + } } - } catch (MalformedURLException ignore) { + } catch (MalformedURLException ignored) { // do nothing } + return defaultContent; } @@ -330,21 +372,20 @@ public final class RenderUtils { return src; } - var normalized = Normalizer.normalize(src.trim(), Normalizer.Form.NFD); - var sb = new StringBuilder(normalized.length()); - boolean space = false; - for (var c : normalized.toCharArray()) { - if (c <= '\u007F') { // ascii only - if (!space && c == ' ') { - space = true; - sb.append('-'); - } else { - space = false; - if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) { - sb.append(c); - } else if (c >= 'A' && c <= 'Z') { - sb.append((char) (c + 32)); // lowercase + var normalized = Normalizer.normalize(src.trim(), Normalizer.Form.NFD).toCharArray(); + + var sb = new StringBuilder(normalized.length); + for (var i = 0; i < normalized.length; i++) { + var c = normalized[i]; + if (c <= '\u007F') { // ASCII only + if (" &()-_=[{]}\\|;:,<.>/".indexOf(c) != -1) { // common separators + if (!sb.isEmpty() && i != normalized.length - 1 && sb.charAt(sb.length() - 1) != '-') { + sb.append('-'); } + } else if (c >= '0' && c <= '9' || c >= 'a' && c <= 'z') { // letters & digits + sb.append(c); + } else if (c >= 'A' && c <= 'Z') { // uppercase letters + sb.append((char) (c + 32)); // make lowercase } } } @@ -362,7 +403,7 @@ public final class RenderUtils { if (src != null && !src.isBlank()) { try { properties.load(new StringReader(src)); - } catch (IOException ignore) { + } catch (IOException ignored) { // ignore } } @@ -419,7 +460,7 @@ public final class RenderUtils { for (var i = 0; i < len; i++) { var inChar = src.charAt(i); - if ((inChar >= 'A') && (inChar <= 'Z')) { + if (inChar >= 'A' && inChar <= 'Z') { inChar += (char) 13; if (inChar > 'Z') { @@ -427,7 +468,7 @@ public final class RenderUtils { } } - if ((inChar >= 'a') && (inChar <= 'z')) { + if (inChar >= 'a' && inChar <= 'z') { inChar += (char) 13; if (inChar > 'z') { @@ -593,7 +634,7 @@ public final class RenderUtils { return true; } } - } catch (NumberFormatException ignore) { + } catch (NumberFormatException ignored) { // do nothing } return false; diff --git a/src/main/java/rife/render/Rot13.java b/src/main/java/rife/render/Rot13.java index d3a33c4..75e3dd7 100644 --- a/src/main/java/rife/render/Rot13.java +++ b/src/main/java/rife/render/Rot13.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,12 @@ import rife.template.ValueRenderer; */ public class Rot13 implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value translated to/from ROT13. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the ROT13 value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/ShortenUrl.java b/src/main/java/rife/render/ShortenUrl.java index 3ddd62e..204d7c6 100644 --- a/src/main/java/rife/render/ShortenUrl.java +++ b/src/main/java/rife/render/ShortenUrl.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import rife.template.ValueRenderer; */ public class ShortenUrl implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value shortened using is.gid. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the template shortened value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/SwapCase.java b/src/main/java/rife/render/SwapCase.java index c059a6a..1fd996a 100644 --- a/src/main/java/rife/render/SwapCase.java +++ b/src/main/java/rife/render/SwapCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import rife.template.Template; import rife.template.ValueRenderer; /** - *

Swap case of a template value.

+ *

Swaps case of a template value.

* *

Usage:

* @@ -35,9 +35,13 @@ import rife.template.ValueRenderer; * @since 1.0 */ public class SwapCase implements ValueRenderer { - /** - * {@inheritDoc} + * Returns the template value with swapped case. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the swapped case value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/TimeIso.java b/src/main/java/rife/render/TimeIso.java index 9f99269..01bf5b2 100644 --- a/src/main/java/rife/render/TimeIso.java +++ b/src/main/java/rife/render/TimeIso.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import rife.template.ValueRenderer; import java.time.ZonedDateTime; /** - *

Return the current time in ISO 8601 format.

+ *

Renders the current time in ISO 8601 format.

* *

Usage:

* @@ -38,7 +38,12 @@ import java.time.ZonedDateTime; */ public class TimeIso implements ValueRenderer { /** - * {@inheritDoc} + * Returns the current time in ISO 8601 format. + * + * @param template the template that is currently being rendered + * @param valueId the id of the value to be rendered + * @param differentiator a differentiator that may be used to differentiate the rendering of this value renderer + * @return the current time in ISO 8601 format */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Trim.java b/src/main/java/rife/render/Trim.java index fb97e31..a0951b4 100644 --- a/src/main/java/rife/render/Trim.java +++ b/src/main/java/rife/render/Trim.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,12 @@ import rife.template.ValueRenderer; */ public class Trim implements ValueRenderer { /** - * {@inheritDoc} + * Renders the template value by removing leading and trailing whitespace. + * + * @param template the template instance + * @param valueId the id of the value to render + * @param differentiator an optional differentiator to use for cache invalidation + * @return the trimmed value, or the original value if it is {@code null} or empty */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Uncapitalize.java b/src/main/java/rife/render/Uncapitalize.java index bef0dfe..20b0aad 100644 --- a/src/main/java/rife/render/Uncapitalize.java +++ b/src/main/java/rife/render/Uncapitalize.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,12 @@ import rife.tools.StringUtils; */ public class Uncapitalize implements ValueRenderer { /** - * {@inheritDoc} + * Returns the un-capitalized template value. + * + * @param template the template to render + * @param valueId the id of the value to render + * @param differentiator the differentiator to use for the value lookup + * @return the un-capitalized value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Uppercase.java b/src/main/java/rife/render/Uppercase.java index 47a7eb5..92e57a5 100644 --- a/src/main/java/rife/render/Uppercase.java +++ b/src/main/java/rife/render/Uppercase.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import rife.template.ValueRenderer; import rife.tools.Localization; /** - *

Convert a template value to uppercase.

+ *

Converts a template value to uppercase.

* *

Usage:

* @@ -37,7 +37,12 @@ import rife.tools.Localization; */ public class Uppercase implements ValueRenderer { /** - * {@inheritDoc} + * Returns the template value converted to uppercase. + * + * @param template the template that contains the value + * @param valueId the id of the value + * @param differentiator the differentiator to use + * @return the uppercased value */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Uptime.java b/src/main/java/rife/render/Uptime.java index 09ffc3e..14bb2de 100644 --- a/src/main/java/rife/render/Uptime.java +++ b/src/main/java/rife/render/Uptime.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,12 @@ import java.lang.management.ManagementFactory; */ public class Uptime implements ValueRenderer { /** - * {@inheritDoc} + * Renders the server uptime. + * + * @param template the template that is currently being rendered + * @param valueId the id of the value to render + * @param differentiator a differentiator that may be used to differentiate the rendering of this value renderer + * @return the server uptime */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/main/java/rife/render/Year.java b/src/main/java/rife/render/Year.java index c7fe2e3..cb8c8f5 100644 --- a/src/main/java/rife/render/Year.java +++ b/src/main/java/rife/render/Year.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,9 +37,13 @@ import java.time.ZonedDateTime; * @since 1.0 */ public class Year implements ValueRenderer { - /** - * {@inheritDoc} + * Renders the current year. + * + * @param template the template that is currently being rendered + * @param valueId the id of the value to render + * @param differentiator a differentiator that may be used to differentiate the rendering of this value renderer + * @return the current year */ @Override public String render(Template template, String valueId, String differentiator) { diff --git a/src/test/java/rife/render/DisableOnCiCondition.java b/src/test/java/rife/render/DisableOnCiCondition.java index cd59296..27081c2 100644 --- a/src/test/java/rife/render/DisableOnCiCondition.java +++ b/src/test/java/rife/render/DisableOnCiCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/rife/render/DisabledOnCi.java b/src/test/java/rife/render/DisabledOnCi.java index b243ee7..8c369d6 100644 --- a/src/test/java/rife/render/DisabledOnCi.java +++ b/src/test/java/rife/render/DisabledOnCi.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import java.lang.annotation.Target; * @author Erik C. Thauvin * @since 1.0 */ -@Target({ ElementType.TYPE, ElementType.METHOD }) +@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @ExtendWith(DisableOnCiCondition.class) public @interface DisabledOnCi { diff --git a/src/test/java/rife/render/TestCase.java b/src/test/java/rife/render/TestCase.java index cebd066..2759ff6 100644 --- a/src/test/java/rife/render/TestCase.java +++ b/src/test/java/rife/render/TestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,9 @@ class TestCase { var bean = new ValueBean("this IS a TEST."); t.setBean(bean); assertThat(t.getContent()).isEqualTo(bean.getValue() + ": this is a test."); + bean = new ValueBean(""); + t.setBean(bean); + assertThat(t.getContent()).isEqualTo(bean.getValue() + ": "); } @Test @@ -54,6 +57,8 @@ class TestCase { var t = TemplateFactory.TXT.get("trim"); t.setAttribute(FOO, "\t" + SAMPLE_TEXT + " \n"); assertThat(t.getContent()).isEqualTo(SAMPLE_TEXT); + t.setAttribute(FOO, ""); + assertThat(t.getContent()).isEmpty(); } @Test @@ -68,5 +73,7 @@ class TestCase { var t = TemplateFactory.TXT.get("uppercase"); t.setAttribute("bar", SAMPLE_TEXT); assertThat(t.getContent()).isEqualTo(SAMPLE_TEXT.toUpperCase(Localization.getLocale())); + t.setAttribute("bar", ""); + assertThat(t.getContent()).isEmpty(); } } \ No newline at end of file diff --git a/src/test/java/rife/render/TestDateTime.java b/src/test/java/rife/render/TestDateTime.java index 55bb519..bfb8cc7 100644 --- a/src/test/java/rife/render/TestDateTime.java +++ b/src/test/java/rife/render/TestDateTime.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/test/java/rife/render/TestEncode.java b/src/test/java/rife/render/TestEncode.java index 251b046..bc390d4 100644 --- a/src/test/java/rife/render/TestEncode.java +++ b/src/test/java/rife/render/TestEncode.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,6 +55,10 @@ class TestEncode { t.setAttribute(TestCase.FOO, "'\"\\/"); assertThat(t.getContent()).isEqualTo("\\'\\\"\\\\\\/"); + t = TemplateFactory.TXT.get("encodeJs"); + t.setAttribute(TestCase.FOO, "This is\f\b a\r\n\ttest"); + assertThat(t.getContent()).isEqualTo("This is\\f\\b a\\r\\n\\ttest"); + t = TemplateFactory.HTML.get("encodeJs"); t.setAttribute(TestCase.FOO, '"' + TestCase.SAMPLE_TEXT + '"'); assertThat(t.getContent()).as("with unicode") diff --git a/src/test/java/rife/render/TestFormat.java b/src/test/java/rife/render/TestFormat.java index 706c648..eb1840b 100644 --- a/src/test/java/rife/render/TestFormat.java +++ b/src/test/java/rife/render/TestFormat.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package rife.render; -import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import rife.template.TemplateFactory; @@ -45,7 +44,9 @@ class TestFormat { t.setAttribute(TestCase.FOO, "374380141731053"); assertThat(t.getContent()).as("UK AMEX").isEqualTo("1053"); t.setAttribute(TestCase.FOO, "000000000000001"); - assertThat(t.getContent()).isEmpty(); + assertThat(t.getContent()).as("000000000000001").isEmpty(); + t.setAttribute(TestCase.FOO, ""); + assertThat(t.getContent()).as("").isEmpty(); } @Test diff --git a/src/test/java/rife/render/TestRenderUtils.java b/src/test/java/rife/render/TestRenderUtils.java index 6854bf5..f1f8c46 100644 --- a/src/test/java/rife/render/TestRenderUtils.java +++ b/src/test/java/rife/render/TestRenderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package rife.render; +import org.assertj.core.api.AutoCloseableSoftAssertions; import org.junit.jupiter.api.Test; import java.util.Properties; @@ -35,11 +36,28 @@ class TestRenderUtils { assertThat(RenderUtils.abbreviate(TestCase.SAMPLE_TEXT, -1, "")).as("max=-1") .isEqualTo(TestCase.SAMPLE_TEXT); + + assertThat(RenderUtils.abbreviate("", 10, "")).as("").isEmpty(); + } + + @Test + void testCapitalizeWords() { + assertThat(RenderUtils.capitalizeWords("hello world")).isEqualTo("Hello World"); + assertThat(RenderUtils.capitalizeWords("java programming")).isEqualTo("Java Programming"); + assertThat(RenderUtils.capitalizeWords("TEST")).isEqualTo("Test"); + assertThat(RenderUtils.capitalizeWords("multiple spaces")).isEqualTo("Multiple Spaces"); + assertThat(RenderUtils.capitalizeWords("white\t\fspaces")).isEqualTo("White\t\fSpaces"); + assertThat(RenderUtils.capitalizeWords("")).isEmpty(); + assertThat(RenderUtils.capitalizeWords(null)).isNull(); } @Test void testEncode() { var p = new Properties(); + p.put(RenderUtils.ENCODING_PROPERTY, "blah"); + assertThat(RenderUtils.encode(TestCase.SAMPLE_TEXT, p)).as("invalid encoding").isEqualTo(TestCase.SAMPLE_TEXT); + p.put(RenderUtils.ENCODING_PROPERTY, "json"); + assertThat(RenderUtils.encode("This is a \"•test\"", p)).as("json").isEqualTo("This is a \\\"\\u2022test\\\""); p.put(RenderUtils.ENCODING_PROPERTY, "html"); assertThat(RenderUtils.encode("", p)).as("html").isEqualTo("<a test &>"); p.put(RenderUtils.ENCODING_PROPERTY, "js"); @@ -52,8 +70,22 @@ class TestRenderUtils { assertThat(RenderUtils.encode("Joe's Café & Bar", p)).as("xml").isEqualTo("Joe's Café & Bar"); } + @Test + void testEncodeJs() { + assertThat(RenderUtils.encodeJs("")).isEmpty(); + } + + @Test + void testFetchUrl() { + var s = "default"; + assertThat(RenderUtils.fetchUrl("blah", s)).isEqualTo(s); + assertThat(RenderUtils.fetchUrl("https://www.google.com/404", s)).isEqualTo(s); + assertThat(RenderUtils.fetchUrl("https://www.notreallythere.com/", s)).isEqualTo(s); + } + @Test void testHtmlEntities() { + assertThat(RenderUtils.htmlEntities("")).isEmpty(); assertThat(RenderUtils.htmlEntities(SAMPLE_GERMAN)) .isEqualTo("Möchten Sie ein paar Äpfel?"); } @@ -62,6 +94,8 @@ class TestRenderUtils { void testMask() { var foo = "4342256562440179"; + assertThat(RenderUtils.mask("", " ", 2, false)).isEmpty(); + assertThat(RenderUtils.mask(foo, "?", 4, false)).as("mask=?") .isEqualTo("????????????0179"); @@ -74,27 +108,43 @@ class TestRenderUtils { @Test void testNormalize() { - assertThat(RenderUtils.normalize(SAMPLE_GERMAN)).isEqualTo("mochten-sie-ein-paar-apfel"); + assertThat(RenderUtils.normalize("")).as("empty").isEmpty(); + assertThat(RenderUtils.normalize(" &()-_=[{]}\\|;:,<.>/")).as("blank").isEmpty(); + assertThat(RenderUtils.normalize(SAMPLE_GERMAN)).as("greman").isEqualTo("mochten-sie-ein-paar-apfel"); + assertThat(RenderUtils.normalize("foo bar, ,foo:bar,foo;(bar), {foo} & bar=foo.bar[foo|bar]")) + .as("foo-bar") + .isEqualTo("foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar"); + assertThat(RenderUtils.normalize("News for January 6, 2023 (Paris)")).as("docs example") + .isEqualTo("news-for-january-6-2023-paris"); + } + + @Test + void testQrCode() { + assertThat(RenderUtils.qrCode("", "12")).isEmpty(); } @Test void testRot13() { var encoded = "Zöpugra Fvr rva cnne Äcsry?"; + assertThat(RenderUtils.rot13("")).isEmpty(); assertThat(RenderUtils.rot13(SAMPLE_GERMAN)).as("encode").isEqualTo(encoded); assertThat(RenderUtils.rot13(encoded)).as("decode").isEqualTo(SAMPLE_GERMAN); } @Test void testSwapCase() { + assertThat(RenderUtils.swapCase("")).isEmpty(); assertThat(RenderUtils.swapCase(SAMPLE_GERMAN)).isEqualTo("mÖCHTEN sIE EIN PAAR äPFEL?"); } @Test void testValidateCreditCard() { - assertThat(RenderUtils.validateCreditCard("4505 4672 3366 6430")).as("visa").isTrue(); - assertThat(RenderUtils.validateCreditCard("5189-5923-3915-0425")).as("mastercard").isTrue(); - assertThat(RenderUtils.validateCreditCard("3433634926643302")).as("amex").isTrue(); - assertThat(RenderUtils.validateCreditCard("6011 1076-8252 0629")).as("discover").isTrue(); - assertThat(RenderUtils.validateCreditCard("0123456789012345")).as("invalid").isFalse(); + try (var softly = new AutoCloseableSoftAssertions()) { + softly.assertThat(RenderUtils.validateCreditCard("4505 4672 3366 6430")).as("visa").isTrue(); + softly.assertThat(RenderUtils.validateCreditCard("5189-5923-3915-0425")).as("mastercard").isTrue(); + softly.assertThat(RenderUtils.validateCreditCard("3433634926643302")).as("amex").isTrue(); + softly.assertThat(RenderUtils.validateCreditCard("6011 1076-8252 0629")).as("discover").isTrue(); + softly.assertThat(RenderUtils.validateCreditCard("0123456789012345")).as("invalid").isFalse(); + } } } diff --git a/src/test/java/rife/render/ValueBean.java b/src/test/java/rife/render/ValueBean.java index 6bf98fc..ed0911f 100644 --- a/src/test/java/rife/render/ValueBean.java +++ b/src/test/java/rife/render/ValueBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.