Added QrCode renderer

This commit is contained in:
Erik C. Thauvin 2023-03-19 03:06:19 -07:00
parent b97abc7091
commit b218313ed3
5 changed files with 106 additions and 5 deletions

View file

@ -37,8 +37,9 @@ This project provides a collection of useful template renderers.
| Renderer | Description | | Renderer | Description |
|:--------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------| |:--------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------|
| [rife.render.formatCreditcard](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.FormatCreditCard) | Formats a template credit card number value to the last 4 digits | | [rife.render.formatCreditcard](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.FormatCreditCard) | Formats a template credit card number value to the last 4 digits |
| [rife.render.Normalize](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Normalize) | Normalizes a template value for inclusion in a URL path | | [rife.render.Normalize](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Normalize) | Normalizes a template value for inclusion in a URL path |
| [rife.render.ShortenUrl](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.ShortenUrl) | Shortens a template value using [is./gd](https://is.gd/) | | [rife.render.QrCode](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.QrCode) | Generate a SVG QR Code from a template value |
| [rife.render.ShortenUrl](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.ShortenUrl) | Shortens a template value |
| [rife.render.Uptime](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Uptime) | Renders the server uptime in various customizable formats | | [rife.render.Uptime](https://github.com/rife2/rife2-template-renderers/wiki/rife.render.Uptime) | Renders the server uptime in various customizable formats |

View file

@ -0,0 +1,59 @@
/*
* 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 java.io.IOException;
import java.io.StringReader;
import java.util.Properties;
/**
* <p>Generates an SVG QR Code for a template value using <a href="https://goqr.me/">goQR.me</a>.</p>
*
* <p>Usage:</p>
*
* <pre>
* &lt;!--v render:rife.render.QrCode:valueId/--&gt;
* {{v render:rife.render.QrCode:valueId/}}
* </pre>
*
* @author <a href="https://erik.thauvin.net/">Erik C. Thauvin</a>
* @see <a href="https://github.com/rife2/rife2-template-renderers/wiki/rife.render.QrCode">rife.render.QrCode</a>
* @since 1.0
*/
public class QrCode implements ValueRenderer {
/**
* {@inheritDoc}
*/
@Override
public String render(Template template, String valueId, String differentiator) {
var size = "150x150";
if (template.hasDefaultValue(valueId)) {
var properties = new Properties();
try {
properties.load(new StringReader(template.getDefaultValue(valueId)));
size = properties.getProperty("size", size);
} catch (IOException ignore) {
// do nothing
}
}
return RenderUtils.qrCode(template.getValueOrAttribute(differentiator), size);
}
}

View file

@ -129,8 +129,8 @@ public final class RenderUtils {
* @return The normalized String * @return The normalized String
*/ */
public static String normalize(String src) { public static String normalize(String src) {
var sb = new StringBuilder(src.length());
var normalized = Normalizer.normalize(src.trim(), Normalizer.Form.NFD); var normalized = Normalizer.normalize(src.trim(), Normalizer.Form.NFD);
var sb = new StringBuilder(normalized.length());
boolean space = false; boolean space = false;
for (var c : normalized.toCharArray()) { for (var c : normalized.toCharArray()) {
if (c <= '\u007F') { // ascii only if (c <= '\u007F') { // ascii only
@ -166,6 +166,39 @@ public final class RenderUtils {
} }
} }
/**
* Generates an SVG QR Code from the given String using <a href="https://goqr.me/">goQR.me</a>.
*
* @param src the data String
* @param size the QR Code size. (e.g. {@code 150x150})
* @return the QR code
*/
public static String qrCode(String src, String size) {
if (src == null || src.isBlank()) {
return src;
}
var svg = src;
try {
var connection = (HttpURLConnection) new URL(
String.format("https://api.qrserver.com/v1/create-qr-code/?format=svg&size=%s&data=%s", size,
StringUtils.encodeUrl(src.trim())))
.openConnection();
connection.setRequestProperty(
"User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0"
);
var responseCode = connection.getResponseCode();
if (responseCode >= 200 && responseCode <= 399) {
try (var inputStream = connection.getInputStream()) {
svg = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
}
}
} catch (IOException ignore) {
// do nothing
}
return svg;
}
/** /**
* Translates a String to/from ROT13. * Translates a String to/from ROT13.
* *
@ -221,7 +254,7 @@ public final class RenderUtils {
var shorten = url; var shorten = url;
try { try {
var connection = (HttpURLConnection) new URL( var connection = (HttpURLConnection) new URL(
String.format("https://is.gd/create.php?format=simple&url=%s", StringUtils.decodeUrl(url.trim()))) String.format("https://is.gd/create.php?format=simple&url=%s", StringUtils.encodeUrl(url.trim())))
.openConnection(); .openConnection();
connection.setRequestProperty( connection.setRequestProperty(
"User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0" "User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0"
@ -385,5 +418,4 @@ public final class RenderUtils {
return sb.toString(); return sb.toString();
} }
} }

View file

@ -45,6 +45,14 @@ class TestFormat {
+ foo + "</a>"); + foo + "</a>");
} }
@Test
void testQrCode() {
var t = TemplateFactory.SVG.get("qrCode");
var foo = "https://example.com/";
t.setAttribute(TestCase.FOO, foo);
assertThat(t.getContent()).startsWith("<?xml").contains("<desc>" + foo + "</desc").contains("width=\"200\"");
}
@Test @Test
void testShortenUrl() { void testShortenUrl() {
var t = TemplateFactory.HTML.get("shortenUrl"); var t = TemplateFactory.HTML.get("shortenUrl");

View file

@ -0,0 +1 @@
{{v render:rife.render.QrCode:foo}}size=200x200{{/v}}