From 54f40eb41e2b67de2b3f78c4b29a69c3ee71b319 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Thu, 16 Mar 2023 01:03:32 -0700 Subject: [PATCH] Added EncodeJS --- README.md | 56 +++++++------- lib/src/main/java/rife/render/EncodeJS.java | 74 +++++++++++++++++++ .../test/java/rife/render/TestDateTime.java | 2 +- lib/src/test/java/rife/render/TestEncode.java | 12 ++- lib/src/test/resources/templates/encodeJS.txt | 1 + 5 files changed, 113 insertions(+), 32 deletions(-) create mode 100644 lib/src/main/java/rife/render/EncodeJS.java create mode 100644 lib/src/test/resources/templates/encodeJS.txt diff --git a/README.md b/README.md index 0d8def5..493b67a 100644 --- a/README.md +++ b/README.md @@ -9,40 +9,40 @@ This project provides a collection of template renderers. ## Date/Time Renderers -| Renderer | Description | -|:---------------------------------|:-----------------------------------------------------------------| -| `rife.render.BeatTime` | Renders the current time in Swatch Internet (.beat) Time format. | -| `rife.render.DateIso` | Renders the current date in ISO 8061 format. | -| `rife.render.DateTimeIso` | Renders the current date and time in ISO 8061 format. | -| `rife.render.DateTimeRfc2822` | Renders the current date and time in RFC 2822 format. | -| `rife.render.DateTimeUtc` | Renders the current UTC date and time in ISO 8061 format. | -| `rife.render.TimeIso` | Renders the current time in ISO 8061 format. | -| `rife.render.Year` | Renders the current year. | +| Renderer | Description | +|:---------------------------------|:----------------------------------------------------------------| +| `rife.render.BeatTime` | Renders the current time in Swatch Internet (.beat) Time format | +| `rife.render.DateIso` | Renders the current date in ISO 8061 format | +| `rife.render.DateTimeIso` | Renders the current date and time in ISO 8061 format | +| `rife.render.DateTimeRfc2822` | Renders the current date and time in RFC 2822 format | +| `rife.render.DateTimeUtc` | Renders the current UTC date and time in ISO 8061 format | +| `rife.render.TimeIso` | Renders the current time in ISO 8061 format | +| `rife.render.Year` | Renders the current year | ## Encoding Renderers -| Renderer | Description | -|:-----------------------------------|:--------------------------------------------------------| -| `rife.render.EncodeBase64` | Encodes a template value to Base64. | -| `rife.render.EncodeHtml` | Encodes a template value to HTML. | -| `rife.render.EncodeHtmlEntities` | Encodes a template value to HTML decimal entities. | -| `rife.render.EncodeJson` | Encodes a template value to JSON. | -| `rife.render.EncodeQp` | Converts a template value to a quoted-printable string. | -| `rife.render.EncodeUnicode` | Encodes a template value to Unicode escape codes. | -| `rife.render.EncodeUrl` | URL-encodes a template value. | -| `rife.render.EncodeXml` | Encodes a template value to XML. | +| Renderer | Description | +|:---------------------------------|:-------------------------------------------------------| +| `rife.render.EncodeBase64` | Encodes a template value to Base64 | +| `rife.render.EncodeHtml` | Encodes a template value to HTML | +| `rife.render.EncodeHtmlEntities` | Encodes a template value to HTML decimal entities | +| `rife.render.EncodeJS` | Encodes a template value to JavaScript/ECMAScript | +| `rife.render.EncodeQp` | Converts a template value to a quoted-printable string | +| `rife.render.EncodeUnicode` | Encodes a template value to Unicode escape codes | +| `rife.render.EncodeUrl` | URL-encodes a template value | +| `rife.render.EncodeXml` | Encodes a template value to XML | ## Text Renderers -| Renderer | Description | -|:----------------------------|:---------------------------------------------------------------| -| `rife.render.Capitalize` | Capitalizes a template value. | -| `rife.render.Lowercase` | Converts a template value to lowercase. | -| `rife.render.Rot13` | Translates a template value to/from ROT13. | -| `rife.render.SwapCase` | Swap case of a template value. | -| `rife.render.Trim` | Removes leading and trailing whitespace from a template value. | -| `rife.render.Uncapitalize` | Un-capitalizes a template value. | -| `rife.render.Uppercase` | Converts a template value to uppercase. | +| Renderer | Description | +|:----------------------------|:--------------------------------------------------------------| +| `rife.render.Capitalize` | Capitalizes a template value | +| `rife.render.Lowercase` | Converts a template value to lowercase | +| `rife.render.Rot13` | Translates a template value to/from ROT13 | +| `rife.render.SwapCase` | Swap case of a template value | +| `rife.render.Trim` | Removes leading and trailing whitespace from a template value | +| `rife.render.Uncapitalize` | Un-capitalizes a template value | +| `rife.render.Uppercase` | Converts a template value to uppercase | ## Usage in Templates diff --git a/lib/src/main/java/rife/render/EncodeJS.java b/lib/src/main/java/rife/render/EncodeJS.java new file mode 100644 index 0000000..e1b4cae --- /dev/null +++ b/lib/src/main/java/rife/render/EncodeJS.java @@ -0,0 +1,74 @@ +/* + * Copyright 2023 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; +import rife.tools.StringUtils; + +/** + *

Encodes a template value to JavaScript/ECMAScript.

+ * + *

Usage:

+ * + *
+ *   <!--v render:rife.render.EncodeJS:valueId/-->
+ *   {{v render:rife.render.EncodeJS:valueId/}}
+ * 
+ * + * @author Erik C. Thauvin + * @see StringUtils#encodeJson(String) + * @since 1.0 + */ +public class EncodeJS implements ValueRenderer { + /** + * Encodes a string to JavaScript/ECMAScript. + * + * @param src the source string. + * @return the enocded string + */ + public static String encodeJS(String src) { + if (src == null || src.isBlank()) { + return src; + } + + var sb = new StringBuilder(); + var len = src.length(); + + char c; + for (var i = 0; i < len; i++) { + c = src.charAt(i); + switch (c) { + case '\'' -> sb.append("\\'"); + case '"' -> sb.append("\\\""); + case '\\' -> sb.append("\\\\"); + case '/' -> sb.append("\\/"); + default -> sb.append(c); + } + } + return sb.toString(); + } + + /** + * {@inheritDoc} + */ + @Override + public String render(Template template, String valueId, String differentiator) { + return encodeJS(RenderUtils.fetchValue(template, differentiator)); + } +} diff --git a/lib/src/test/java/rife/render/TestDateTime.java b/lib/src/test/java/rife/render/TestDateTime.java index bc3d7e1..91cb9d5 100644 --- a/lib/src/test/java/rife/render/TestDateTime.java +++ b/lib/src/test/java/rife/render/TestDateTime.java @@ -49,7 +49,7 @@ class TestDateTime { } @Test - void testDateTimeUtc2() { + void testDateTimeUtc() { var t = TemplateFactory.HTML.get("dateTimeUtc"); assertThatCode(() -> DateTimeIso.iso8601Formatter.parse(t.getContent())).doesNotThrowAnyException(); } diff --git a/lib/src/test/java/rife/render/TestEncode.java b/lib/src/test/java/rife/render/TestEncode.java index 8d35e09..b1edced 100644 --- a/lib/src/test/java/rife/render/TestEncode.java +++ b/lib/src/test/java/rife/render/TestEncode.java @@ -44,6 +44,13 @@ class TestEncode { assertThat(t.getContent()).isEqualTo("Email"); } + @Test + void testEncodeJS() { + var t = TemplateFactory.TXT.get("encodeJS"); + t.setAttribute(TestCase.FOO, "'\"\\/"); + assertThat(t.getContent()).isEqualTo("\\'\\\"\\\\\\/"); + } + @Test void testEncodeJson() { var t = TemplateFactory.JSON.get("encodeJson"); @@ -61,17 +68,16 @@ class TestEncode { @Test void testEncodeRot13() { var t = TemplateFactory.TXT.get("rot13"); - var value = TestCase.SAMPLE_TEXT; var rot13 = "Guvf vf n grfg."; // Encode - var bean = new ValueBean(value); + var bean = new ValueBean(TestCase.SAMPLE_TEXT); t.setBean(bean); assertThat(t.getContent()).isEqualTo(bean.getValue() + ": " + rot13); // Decode t.setValue("value", rot13); - assertThat(t.getContent()).isEqualTo(rot13 + ": " + value); + assertThat(t.getContent()).isEqualTo(rot13 + ": " + TestCase.SAMPLE_TEXT); } @Test diff --git a/lib/src/test/resources/templates/encodeJS.txt b/lib/src/test/resources/templates/encodeJS.txt new file mode 100644 index 0000000..e707a53 --- /dev/null +++ b/lib/src/test/resources/templates/encodeJS.txt @@ -0,0 +1 @@ +{{v render:rife.render.EncodeJS:foo/}} \ No newline at end of file