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

@ -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
*/
public static String normalize(String src) {
var sb = new StringBuilder(src.length());
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
@ -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.
*
@ -221,7 +254,7 @@ public final class RenderUtils {
var shorten = url;
try {
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();
connection.setRequestProperty(
"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();
}
}

View file

@ -45,6 +45,14 @@ class TestFormat {
+ 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
void testShortenUrl() {
var t = TemplateFactory.HTML.get("shortenUrl");

View file

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