From 41b21eb4e4275326a87399baa4a40fc662e407f7 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Fri, 27 Jun 2025 18:33:50 +0200
Subject: [PATCH 01/11] fix: java 1.8 version in maven files
---
minify-html-java/pom.xml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/minify-html-java/pom.xml b/minify-html-java/pom.xml
index 98cbec62..9ce5546d 100644
--- a/minify-html-java/pom.xml
+++ b/minify-html-java/pom.xml
@@ -45,7 +45,7 @@
- 1.7
+ 1.8
UTF-8
UTF-8
@@ -57,8 +57,8 @@
maven-compiler-plugin
3.8.1
- 1.7
- 1.7
+ ${java.version}
+ ${java.version}
From 1f9e2334953f761d26213ee1d0c4efb35daa3116 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Fri, 27 Jun 2025 18:41:27 +0200
Subject: [PATCH 02/11] feat: use lombok to generate java classes
Signed-off-by: jogerj <[email protected]>
---
minify-html-java/lombok.config | 2 +
minify-html-java/pom.xml | 17 ++
.../in/wilsonl/minifyhtml/Configuration.java | 176 +++---------------
.../minifyhtml/Configuration.java.gen.js | 53 ------
.../in/wilsonl/minifyhtml/MinifyHtml.java | 52 +++---
minify-html-java/src/main/rust/lib.rs | 30 +--
6 files changed, 88 insertions(+), 242 deletions(-)
create mode 100644 minify-html-java/lombok.config
delete mode 100644 minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java.gen.js
diff --git a/minify-html-java/lombok.config b/minify-html-java/lombok.config
new file mode 100644
index 00000000..48d40f82
--- /dev/null
+++ b/minify-html-java/lombok.config
@@ -0,0 +1,2 @@
+config.stopBubbling = true
+lombok.addLombokGeneratedAnnotation = false
diff --git a/minify-html-java/pom.xml b/minify-html-java/pom.xml
index 9ce5546d..9f93302e 100644
--- a/minify-html-java/pom.xml
+++ b/minify-html-java/pom.xml
@@ -46,10 +46,20 @@
1.8
+ 1.18.38
UTF-8
UTF-8
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
@@ -57,6 +67,13 @@
maven-compiler-plugin
3.8.1
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
${java.version}
${java.version}
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
index c06181da..512a384e 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
@@ -1,160 +1,32 @@
package in.wilsonl.minifyhtml;
-// WARNING: Do not manually edit, use Configuration.java.gen.js.
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
/**
* Class representing minification configuration.
+ * Use the {@link Builder} to create an instance of this class.
*/
+@Builder(
+ setterPrefix = "set",
+ builderClassName = "Builder"
+)
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Configuration {
- public final boolean allow_noncompliant_unquoted_attribute_values;
- public final boolean allow_optimal_entities;
- public final boolean allow_removing_spaces_between_attributes;
- public final boolean keep_closing_tags;
- public final boolean keep_comments;
- public final boolean keep_html_and_head_opening_tags;
- public final boolean keep_input_type_text_attr;
- public final boolean keep_ssi_comments;
- public final boolean minify_css;
- public final boolean minify_doctype;
- public final boolean minify_js;
- public final boolean preserve_brace_template_syntax;
- public final boolean preserve_chevron_percent_template_syntax;
- public final boolean remove_bangs;
- public final boolean remove_processing_instructions;
-
- private Configuration(
- boolean allow_noncompliant_unquoted_attribute_values,
- boolean allow_optimal_entities,
- boolean allow_removing_spaces_between_attributes,
- boolean keep_closing_tags,
- boolean keep_comments,
- boolean keep_html_and_head_opening_tags,
- boolean keep_input_type_text_attr,
- boolean keep_ssi_comments,
- boolean minify_css,
- boolean minify_doctype,
- boolean minify_js,
- boolean preserve_brace_template_syntax,
- boolean preserve_chevron_percent_template_syntax,
- boolean remove_bangs,
- boolean remove_processing_instructions
- ) {
- this.allow_noncompliant_unquoted_attribute_values = allow_noncompliant_unquoted_attribute_values;
- this.allow_optimal_entities = allow_optimal_entities;
- this.allow_removing_spaces_between_attributes = allow_removing_spaces_between_attributes;
- this.keep_closing_tags = keep_closing_tags;
- this.keep_comments = keep_comments;
- this.keep_html_and_head_opening_tags = keep_html_and_head_opening_tags;
- this.keep_input_type_text_attr = keep_input_type_text_attr;
- this.keep_ssi_comments = keep_ssi_comments;
- this.minify_css = minify_css;
- this.minify_doctype = minify_doctype;
- this.minify_js = minify_js;
- this.preserve_brace_template_syntax = preserve_brace_template_syntax;
- this.preserve_chevron_percent_template_syntax = preserve_chevron_percent_template_syntax;
- this.remove_bangs = remove_bangs;
- this.remove_processing_instructions = remove_processing_instructions;
- }
-
- /**
- * Builder to help create configuration.
- */
- public static class Builder {
- private boolean allow_noncompliant_unquoted_attribute_values = false;
- private boolean allow_optimal_entities = false;
- private boolean allow_removing_spaces_between_attributes = false;
- private boolean keep_closing_tags = false;
- private boolean keep_comments = false;
- private boolean keep_html_and_head_opening_tags = false;
- private boolean keep_input_type_text_attr = false;
- private boolean keep_ssi_comments = false;
- private boolean minify_css = false;
- private boolean minify_doctype = false;
- private boolean minify_js = false;
- private boolean preserve_brace_template_syntax = false;
- private boolean preserve_chevron_percent_template_syntax = false;
- private boolean remove_bangs = false;
- private boolean remove_processing_instructions = false;
-
- public Builder setAllowNoncompliantUnquotedAttributeValues(boolean v) {
- this.allow_noncompliant_unquoted_attribute_values = v;
- return this;
- }
- public Builder setAllowOptimalEntities(boolean v) {
- this.allow_optimal_entities = v;
- return this;
- }
- public Builder setAllowRemovingSpacesBetweenAttributes(boolean v) {
- this.allow_removing_spaces_between_attributes = v;
- return this;
- }
- public Builder setKeepClosingTags(boolean v) {
- this.keep_closing_tags = v;
- return this;
- }
- public Builder setKeepComments(boolean v) {
- this.keep_comments = v;
- return this;
- }
- public Builder setKeepHtmlAndHeadOpeningTags(boolean v) {
- this.keep_html_and_head_opening_tags = v;
- return this;
- }
- public Builder setKeepInputTypeTextAttr(boolean v) {
- this.keep_input_type_text_attr = v;
- return this;
- }
- public Builder setKeepSsiComments(boolean v) {
- this.keep_ssi_comments = v;
- return this;
- }
- public Builder setMinifyCss(boolean v) {
- this.minify_css = v;
- return this;
- }
- public Builder setMinifyDoctype(boolean v) {
- this.minify_doctype = v;
- return this;
- }
- public Builder setMinifyJs(boolean v) {
- this.minify_js = v;
- return this;
- }
- public Builder setPreserveBraceTemplateSyntax(boolean v) {
- this.preserve_brace_template_syntax = v;
- return this;
- }
- public Builder setPreserveChevronPercentTemplateSyntax(boolean v) {
- this.preserve_chevron_percent_template_syntax = v;
- return this;
- }
- public Builder setRemoveBangs(boolean v) {
- this.remove_bangs = v;
- return this;
- }
- public Builder setRemoveProcessingInstructions(boolean v) {
- this.remove_processing_instructions = v;
- return this;
- }
-
- public Configuration build() {
- return new Configuration(
- this.allow_noncompliant_unquoted_attribute_values,
- this.allow_optimal_entities,
- this.allow_removing_spaces_between_attributes,
- this.keep_closing_tags,
- this.keep_comments,
- this.keep_html_and_head_opening_tags,
- this.keep_input_type_text_attr,
- this.keep_ssi_comments,
- this.minify_css,
- this.minify_doctype,
- this.minify_js,
- this.preserve_brace_template_syntax,
- this.preserve_chevron_percent_template_syntax,
- this.remove_bangs,
- this.remove_processing_instructions
- );
- }
- }
+ public final boolean allowNoncompliantUnquotedAttributeValues;
+ public final boolean allowOptimalEntities;
+ public final boolean allowRemovingSpacesBetweenAttributes;
+ public final boolean keepClosingTags;
+ public final boolean keepComments;
+ public final boolean keepHtmlAndHeadOpeningTags;
+ public final boolean keepInputTypeTextAttr;
+ public final boolean keepSsiComments;
+ public final boolean minifyCss;
+ public final boolean minifyDoctype;
+ public final boolean minifyJs;
+ public final boolean preserveBraceTemplateSyntax;
+ public final boolean preserveChevronPercentTemplateSyntax;
+ public final boolean removeBangs;
+ public final boolean removeProcessingInstructions;
}
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java.gen.js b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java.gen.js
deleted file mode 100644
index c76e5d04..00000000
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java.gen.js
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env node
-
-/*
- Normally I'd avoid scripts to generate code as it makes it harder to reason and work/develop with. But in this case the Java class is too tedious and error-prone to do manually.
-*/
-
-const fs = require("fs");
-
-const cfgRs = fs.readFileSync(`${__dirname}/../../../../../../../minify-html/src/cfg/mod.rs`, "utf8");
-const opts = [];
-for (const [_, snake] of cfgRs.matchAll(/^\s*pub ([a-zA-Z0-9_]+): bool,?\s*$/gm)) {
- const pascal = snake.split("_").map((w) => `${w[0].toUpperCase()}${w.slice(1)}`).join("");
- opts.push({snake, pascal});
-}
-
-const java = `
-package in.wilsonl.minifyhtml;
-
-// WARNING: Do not manually edit, use Configuration.java.gen.js.
-
-/**
- * Class representing minification configuration.
- */
-public class Configuration {
- ${opts.map(o => `public final boolean ${o.snake};`).join("\n ")}
-
- private Configuration(
- ${opts.map(o => `boolean ${o.snake}`).join(",\n ")}
- ) {
- ${opts.map(o => `this.${o.snake} = ${o.snake};`).join("\n ")}
- }
-
- /**
- * Builder to help create configuration.
- */
- public static class Builder {
- ${opts.map(o => `private boolean ${o.snake} = false;`).join("\n ")}
-
- ${opts.map(o => `public Builder set${o.pascal}(boolean v) {
- this.${o.snake} = v;
- return this;
- }`).join("\n ")}
-
- public Configuration build() {
- return new Configuration(
- ${opts.map(o => `this.${o.snake}`).join(",\n ")}
- );
- }
- }
-}
-`.trim();
-
-fs.writeFileSync(`${__dirname}/Configuration.java`, java);
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
index 50bf0481..61b2c829 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
@@ -2,12 +2,9 @@
import java.io.File;
import java.io.InputStream;
-import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
-import static java.lang.String.format;
-
/**
* Class containing only static methods and exception classes. Cannot be instantiated.
* Methods call to native compiled Rust code using JNI.
@@ -15,31 +12,20 @@
*/
public class MinifyHtml {
static {
- String osName = System.getProperty("os.name").toLowerCase();
- String osArch = System.getProperty("os.arch").toLowerCase();
-
- String nativeLibNameOs = osName.startsWith("windows")
- ? "win"
- : osName.startsWith("linux")
- ? "linux"
- : osName.startsWith("mac")
- ? "mac"
- : null;
- String nativeLibNameArch =
- osArch.equals("amd64") || osArch.equals("x86_64")
- ? "x64"
- : osArch.equals("arm64") || osArch.equals("aarch64")
- ? "aarch64"
- : null;
+ final String osName = System.getProperty("os.name").toLowerCase();
+ final String osArch = System.getProperty("os.arch").toLowerCase();
+
+ final String nativeLibNameOs = getNativeLibNameOs(osName);
+ final String nativeLibNameArch = getNativeLibNameArch(osArch);
if (nativeLibNameOs == null || nativeLibNameArch == null) {
- throw new RuntimeException(format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
+ throw new RuntimeException(String.format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
}
- String nativeLibFile = format("/%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
+ final String nativeLibFile = String.format("/%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
try (InputStream is = MinifyHtml.class.getResourceAsStream(nativeLibFile)) {
- File temp = File.createTempFile("minify-html-java-nativelib", nativeLibFile.substring(1));
+ final File temp = File.createTempFile("minify-html-java-nativelib", nativeLibFile.substring(1));
temp.deleteOnExit();
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.load(temp.getAbsolutePath());
@@ -60,4 +46,26 @@ private MinifyHtml() {
* @return minified HTML code
*/
public static native String minify(String code, Configuration cfg);
+
+ private static String getNativeLibNameOs(String osName) {
+ if (osName.startsWith("windows")) {
+ return "win";
+ } else if (osName.startsWith("linux")) {
+ return "linux";
+ } else if (osName.startsWith("mac")) {
+ return "mac";
+ } else {
+ return null;
+ }
+ }
+
+ private static String getNativeLibNameArch(String osArch) {
+ if (osArch.equals("amd64") || osArch.equals("x86_64")) {
+ return "x64";
+ } else if (osArch.equals("arm64") || osArch.equals("aarch64")) {
+ return "aarch64";
+ } else {
+ return null;
+ }
+ }
}
diff --git a/minify-html-java/src/main/rust/lib.rs b/minify-html-java/src/main/rust/lib.rs
index ead6d2b0..698f6521 100644
--- a/minify-html-java/src/main/rust/lib.rs
+++ b/minify-html-java/src/main/rust/lib.rs
@@ -11,21 +11,21 @@ fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
#[rustfmt::skip]
// This is a statement because "attributes on expressions are experimental".
let cfg = Cfg {
- allow_noncompliant_unquoted_attribute_values: env.get_field(*obj, "allow_noncompliant_unquoted_attribute_values", "Z").unwrap().z().unwrap(),
- allow_optimal_entities: env.get_field(*obj, "allow_optimal_entities", "Z").unwrap().z().unwrap(),
- allow_removing_spaces_between_attributes: env.get_field(*obj, "allow_removing_spaces_between_attributes", "Z").unwrap().z().unwrap(),
- keep_closing_tags: env.get_field(*obj, "keep_closing_tags", "Z").unwrap().z().unwrap(),
- keep_comments: env.get_field(*obj, "keep_comments", "Z").unwrap().z().unwrap(),
- keep_html_and_head_opening_tags: env.get_field(*obj, "keep_html_and_head_opening_tags", "Z").unwrap().z().unwrap(),
- keep_input_type_text_attr: env.get_field(*obj, "keep_input_type_text_attr", "Z").unwrap().z().unwrap(),
- keep_ssi_comments: env.get_field(*obj, "keep_ssi_comments", "Z").unwrap().z().unwrap(),
- minify_css: env.get_field(*obj, "minify_css", "Z").unwrap().z().unwrap(),
- minify_doctype: env.get_field(*obj, "minify_doctype", "Z").unwrap().z().unwrap(),
- minify_js: env.get_field(*obj, "minify_js", "Z").unwrap().z().unwrap(),
- preserve_brace_template_syntax: env.get_field(*obj, "preserve_brace_template_syntax", "Z").unwrap().z().unwrap(),
- preserve_chevron_percent_template_syntax: env.get_field(*obj, "preserve_chevron_percent_template_syntax", "Z").unwrap().z().unwrap(),
- remove_bangs: env.get_field(*obj, "remove_bangs", "Z").unwrap().z().unwrap(),
- remove_processing_instructions: env.get_field(*obj, "remove_processing_instructions", "Z").unwrap().z().unwrap(),
+ allow_noncompliant_unquoted_attribute_values: env.get_field(*obj, "allowNoncompliantUnquotedAttributeValues", "Z").unwrap().z().unwrap(),
+ allow_optimal_entities: env.get_field(*obj, "allowOptimalEntities", "Z").unwrap().z().unwrap(),
+ allow_removing_spaces_between_attributes: env.get_field(*obj, "allowRemovingSpacesBetweenAttributes", "Z").unwrap().z().unwrap(),
+ keep_closing_tags: env.get_field(*obj, "keepClosingTags", "Z").unwrap().z().unwrap(),
+ keep_comments: env.get_field(*obj, "keepComments", "Z").unwrap().z().unwrap(),
+ keep_html_and_head_opening_tags: env.get_field(*obj, "keepHtmlAndHeadOpeningTags", "Z").unwrap().z().unwrap(),
+ keep_input_type_text_attr: env.get_field(*obj, "keepInputTypeTextAttr", "Z").unwrap().z().unwrap(),
+ keep_ssi_comments: env.get_field(*obj, "keepSsiComments", "Z").unwrap().z().unwrap(),
+ minify_css: env.get_field(*obj, "minifyCss", "Z").unwrap().z().unwrap(),
+ minify_doctype: env.get_field(*obj, "minifyDoctype", "Z").unwrap().z().unwrap(),
+ minify_js: env.get_field(*obj, "minifyJs", "Z").unwrap().z().unwrap(),
+ preserve_brace_template_syntax: env.get_field(*obj, "preserveBraceTemplateSyntax", "Z").unwrap().z().unwrap(),
+ preserve_chevron_percent_template_syntax: env.get_field(*obj, "preserveChevronPercentTemplateSyntax", "Z").unwrap().z().unwrap(),
+ remove_bangs: env.get_field(*obj, "removeBangs", "Z").unwrap().z().unwrap(),
+ remove_processing_instructions: env.get_field(*obj, "removeProcessingInstructions", "Z").unwrap().z().unwrap(),
};
cfg
}
From 137ba670713ef457bbb2210b277977a0a7443842 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 02:07:27 +0200
Subject: [PATCH 03/11] feat: use a value class for config
Signed-off-by: jogerj <[email protected]>
---
.../in/wilsonl/minifyhtml/Configuration.java | 38 ++++++++++---------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
index 512a384e..d46fec9f 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
@@ -3,30 +3,32 @@
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
+import lombok.Value;
/**
* Class representing minification configuration.
* Use the {@link Builder} to create an instance of this class.
*/
+@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder(
- setterPrefix = "set",
- builderClassName = "Builder"
+ setterPrefix = "set",
+ builderClassName = "Builder"
)
-@AllArgsConstructor(access = AccessLevel.PRIVATE)
+@Value
public class Configuration {
- public final boolean allowNoncompliantUnquotedAttributeValues;
- public final boolean allowOptimalEntities;
- public final boolean allowRemovingSpacesBetweenAttributes;
- public final boolean keepClosingTags;
- public final boolean keepComments;
- public final boolean keepHtmlAndHeadOpeningTags;
- public final boolean keepInputTypeTextAttr;
- public final boolean keepSsiComments;
- public final boolean minifyCss;
- public final boolean minifyDoctype;
- public final boolean minifyJs;
- public final boolean preserveBraceTemplateSyntax;
- public final boolean preserveChevronPercentTemplateSyntax;
- public final boolean removeBangs;
- public final boolean removeProcessingInstructions;
+ boolean allowNoncompliantUnquotedAttributeValues;
+ boolean allowOptimalEntities;
+ boolean allowRemovingSpacesBetweenAttributes;
+ boolean keepClosingTags;
+ boolean keepComments;
+ boolean keepHtmlAndHeadOpeningTags;
+ boolean keepInputTypeTextAttr;
+ boolean keepSsiComments;
+ boolean minifyCss;
+ boolean minifyDoctype;
+ boolean minifyJs;
+ boolean preserveBraceTemplateSyntax;
+ boolean preserveChevronPercentTemplateSyntax;
+ boolean removeBangs;
+ boolean removeProcessingInstructions;
}
From fc63072ddd8bdf8901fbc9548ce540e152a8c8c6 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 02:08:50 +0200
Subject: [PATCH 04/11] feat: call getter methods of java Configuration object
Signed-off-by: jogerj <[email protected]>
---
minify-html-java/src/main/rust/lib.rs | 30 +++++++++++++--------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/minify-html-java/src/main/rust/lib.rs b/minify-html-java/src/main/rust/lib.rs
index 698f6521..5285dac1 100644
--- a/minify-html-java/src/main/rust/lib.rs
+++ b/minify-html-java/src/main/rust/lib.rs
@@ -11,21 +11,21 @@ fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
#[rustfmt::skip]
// This is a statement because "attributes on expressions are experimental".
let cfg = Cfg {
- allow_noncompliant_unquoted_attribute_values: env.get_field(*obj, "allowNoncompliantUnquotedAttributeValues", "Z").unwrap().z().unwrap(),
- allow_optimal_entities: env.get_field(*obj, "allowOptimalEntities", "Z").unwrap().z().unwrap(),
- allow_removing_spaces_between_attributes: env.get_field(*obj, "allowRemovingSpacesBetweenAttributes", "Z").unwrap().z().unwrap(),
- keep_closing_tags: env.get_field(*obj, "keepClosingTags", "Z").unwrap().z().unwrap(),
- keep_comments: env.get_field(*obj, "keepComments", "Z").unwrap().z().unwrap(),
- keep_html_and_head_opening_tags: env.get_field(*obj, "keepHtmlAndHeadOpeningTags", "Z").unwrap().z().unwrap(),
- keep_input_type_text_attr: env.get_field(*obj, "keepInputTypeTextAttr", "Z").unwrap().z().unwrap(),
- keep_ssi_comments: env.get_field(*obj, "keepSsiComments", "Z").unwrap().z().unwrap(),
- minify_css: env.get_field(*obj, "minifyCss", "Z").unwrap().z().unwrap(),
- minify_doctype: env.get_field(*obj, "minifyDoctype", "Z").unwrap().z().unwrap(),
- minify_js: env.get_field(*obj, "minifyJs", "Z").unwrap().z().unwrap(),
- preserve_brace_template_syntax: env.get_field(*obj, "preserveBraceTemplateSyntax", "Z").unwrap().z().unwrap(),
- preserve_chevron_percent_template_syntax: env.get_field(*obj, "preserveChevronPercentTemplateSyntax", "Z").unwrap().z().unwrap(),
- remove_bangs: env.get_field(*obj, "removeBangs", "Z").unwrap().z().unwrap(),
- remove_processing_instructions: env.get_field(*obj, "removeProcessingInstructions", "Z").unwrap().z().unwrap(),
+ allow_noncompliant_unquoted_attribute_values: env.call_method(*obj, "getAllowNoncompliantUnquotedAttributeValues", "()Z", &[]).unwrap().z().unwrap(),
+ allow_optimal_entities: env.call_method(*obj, "getAllowOptimalEntities", "()Z", &[]).unwrap().z().unwrap(),
+ allow_removing_spaces_between_attributes: env.call_method(*obj, "getAllowRemovingSpacesBetweenAttributes", "()Z", &[]).unwrap().z().unwrap(),
+ keep_closing_tags: env.call_method(*obj, "getKeepClosingTags", "()Z", &[]).unwrap().z().unwrap(),
+ keep_comments: env.call_method(*obj, "getKeepComments", "()Z", &[]).unwrap().z().unwrap(),
+ keep_html_and_head_opening_tags: env.call_method(*obj, "getKeepHtmlAndHeadOpeningTags", "()Z", &[]).unwrap().z().unwrap(),
+ keep_input_type_text_attr: env.call_method(*obj, "getKeepInputTypeTextAttr", "()Z", &[]).unwrap().z().unwrap(),
+ keep_ssi_comments: env.call_method(*obj, "getKeepSsiComments", "()Z", &[]).unwrap().z().unwrap(),
+ minify_css: env.call_method(*obj, "getMinifyCss", "()Z", &[]).unwrap().z().unwrap(),
+ minify_doctype: env.call_method(*obj, "getMinifyDoctype", "()Z", &[]).unwrap().z().unwrap(),
+ minify_js: env.call_method(*obj, "getMinifyJs", "()Z", &[]).unwrap().z().unwrap(),
+ preserve_brace_template_syntax: env.call_method(*obj, "getPreserveBraceTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
+ preserve_chevron_percent_template_syntax: env.call_method(*obj, "getPreserveChevronPercentTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
+ remove_bangs: env.call_method(*obj, "getRemoveBangs", "()Z", &[]).unwrap().z().unwrap(),
+ remove_processing_instructions: env.call_method(*obj, "getRemoveProcessingInstructions", "()Z", &[]).unwrap().z().unwrap(),
};
cfg
}
From 56d17efb743b8ccff6156be1ba1dad07853d907e Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 02:10:26 +0200
Subject: [PATCH 05/11] feat: wrap native calls in null checks to prevent panic
Signed-off-by: jogerj <[email protected]>
---
.../in/wilsonl/minifyhtml/MinifyHtml.java | 23 ++++++++++++++-----
minify-html-java/src/main/rust/lib.rs | 2 +-
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
index 61b2c829..b855f661 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
@@ -22,10 +22,10 @@ public class MinifyHtml {
throw new RuntimeException(String.format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
}
- final String nativeLibFile = String.format("/%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
+ final String nativeLibFile = String.format("%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
- try (InputStream is = MinifyHtml.class.getResourceAsStream(nativeLibFile)) {
- final File temp = File.createTempFile("minify-html-java-nativelib", nativeLibFile.substring(1));
+ try (InputStream is = MinifyHtml.class.getResourceAsStream("/" + nativeLibFile)) {
+ final File temp = File.createTempFile("minify-html-java-nativelib", nativeLibFile);
temp.deleteOnExit();
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.load(temp.getAbsolutePath());
@@ -41,11 +41,22 @@ private MinifyHtml() {
* Minify HTML code represented as a {@link String}.
* The {@link String} will be copied to a UTF-8 byte array in native code, and then copied back into a Java {@link String}.
*
- * @param code HTML code to minify
- * @param cfg {@link Configuration} minification settings to use
+ * @param code HTML code to minify, cannot be null
+ * @param cfg {@link Configuration} minification settings to use, cannot be null
* @return minified HTML code
+ * @throws IllegalArgumentException if either {@code code} or {@code cfg} is null
*/
- public static native String minify(String code, Configuration cfg);
+ public static String minify(String code, Configuration cfg) {
+ if (code == null) {
+ throw new IllegalArgumentException("code cannot be null");
+ }
+ if (cfg == null) {
+ throw new IllegalArgumentException("configuration cannot be null");
+ }
+ return minifyRs(code, cfg);
+ }
+
+ private static native String minifyRs(String code, Configuration cfg);
private static String getNativeLibNameOs(String osName) {
if (osName.startsWith("windows")) {
diff --git a/minify-html-java/src/main/rust/lib.rs b/minify-html-java/src/main/rust/lib.rs
index 5285dac1..5e88ccaf 100644
--- a/minify-html-java/src/main/rust/lib.rs
+++ b/minify-html-java/src/main/rust/lib.rs
@@ -31,7 +31,7 @@ fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
}
#[no_mangle]
-pub extern "system" fn Java_in_wilsonl_minifyhtml_MinifyHtml_minify(
+pub extern "system" fn Java_in_wilsonl_minifyhtml_MinifyHtml_minifyRs(
env: JNIEnv,
_class: JClass,
input: JString,
From 57f74a4021ef890dd7edfb26ecd6e8aef4ab6af3 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 02:10:42 +0200
Subject: [PATCH 06/11] feat: add unit tests for sanity check
Signed-off-by: jogerj <[email protected]>
---
minify-html-java/pom.xml | 13 ++++++++++
.../in/wilsonl/minifyhtml/MinifyHtmlTest.java | 26 +++++++++++++++++++
2 files changed, 39 insertions(+)
create mode 100644 minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
diff --git a/minify-html-java/pom.xml b/minify-html-java/pom.xml
index 9f93302e..ef2f5ff8 100644
--- a/minify-html-java/pom.xml
+++ b/minify-html-java/pom.xml
@@ -46,6 +46,7 @@
1.8
+ 5.9.3
1.18.38
UTF-8
UTF-8
@@ -58,6 +59,12 @@
${lombok.version}
provided
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.version}
+ test
+
@@ -110,6 +117,12 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.2
+
+
org.apache.maven.plugins
maven-gpg-plugin
diff --git a/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java b/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
new file mode 100644
index 00000000..9f52f3ab
--- /dev/null
+++ b/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
@@ -0,0 +1,26 @@
+package in.wilsonl.minifyhtml;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class MinifyHtmlTest {
+
+ static final Configuration DEFAULT_CONFIG = new Configuration.Builder().build();
+
+ @Test
+ void testMinifyHtmlCallsNativeFunction() {
+ final String input = " Hello World! ";
+ final String expected = "Hello World!";
+ assertEquals(expected, MinifyHtml.minify(input, DEFAULT_CONFIG), "Basic HTML minification failed");
+ assertEquals("", MinifyHtml.minify("", DEFAULT_CONFIG));
+ }
+
+ @Test
+ void testNullParametersHandled() {
+ assertThrows(IllegalArgumentException.class, () -> MinifyHtml.minify(null, DEFAULT_CONFIG));
+ assertThrows(IllegalArgumentException.class, () -> MinifyHtml.minify("", null));
+ assertThrows(IllegalArgumentException.class, () -> MinifyHtml.minify(null, null));
+ }
+}
From 39031acaa65db9f2e528beace5fbb9aa658e3396 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 02:25:28 +0200
Subject: [PATCH 07/11] feat: bump maven plugins version
Signed-off-by: jogerj <[email protected]>
---
minify-html-java/pom.xml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/minify-html-java/pom.xml b/minify-html-java/pom.xml
index ef2f5ff8..3e8b8148 100644
--- a/minify-html-java/pom.xml
+++ b/minify-html-java/pom.xml
@@ -72,7 +72,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ 3.13.0
@@ -89,7 +89,7 @@
org.apache.maven.plugins
maven-source-plugin
- 2.2.1
+ 3.3.1
attach-sources
@@ -103,7 +103,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 2.9.1
+ 3.6.3
${java.version}
@@ -126,7 +126,7 @@
org.apache.maven.plugins
maven-gpg-plugin
- 1.5
+ 3.2.6
sign-artifacts
@@ -141,7 +141,7 @@
org.sonatype.plugins
nexus-staging-maven-plugin
- 1.6.8
+ 1.6.14
true
ossrh
From c46af908aec9bceac245cd201208a78833fbe7b4 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 03:01:59 +0200
Subject: [PATCH 08/11] feat: script to generate java configs
Signed-off-by: jogerj <[email protected]>
---
.../in/wilsonl/minifyhtml/Configuration.java | 2 +
minify-html-java/src/main/rust/lib.rs | 2 +
minify-html-java/update-java.sh | 99 +++++++++++++++++++
3 files changed, 103 insertions(+)
create mode 100755 minify-html-java/update-java.sh
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
index d46fec9f..3e8602dc 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
@@ -16,6 +16,7 @@
)
@Value
public class Configuration {
+ /* BEGIN FIELD NAMES */
boolean allowNoncompliantUnquotedAttributeValues;
boolean allowOptimalEntities;
boolean allowRemovingSpacesBetweenAttributes;
@@ -31,4 +32,5 @@ public class Configuration {
boolean preserveChevronPercentTemplateSyntax;
boolean removeBangs;
boolean removeProcessingInstructions;
+ /* END FIELD NAMES */
}
diff --git a/minify-html-java/src/main/rust/lib.rs b/minify-html-java/src/main/rust/lib.rs
index 5e88ccaf..c80ba3b8 100644
--- a/minify-html-java/src/main/rust/lib.rs
+++ b/minify-html-java/src/main/rust/lib.rs
@@ -11,6 +11,7 @@ fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
#[rustfmt::skip]
// This is a statement because "attributes on expressions are experimental".
let cfg = Cfg {
+ // BEGIN CONFIGURATION FIELDS
allow_noncompliant_unquoted_attribute_values: env.call_method(*obj, "getAllowNoncompliantUnquotedAttributeValues", "()Z", &[]).unwrap().z().unwrap(),
allow_optimal_entities: env.call_method(*obj, "getAllowOptimalEntities", "()Z", &[]).unwrap().z().unwrap(),
allow_removing_spaces_between_attributes: env.call_method(*obj, "getAllowRemovingSpacesBetweenAttributes", "()Z", &[]).unwrap().z().unwrap(),
@@ -26,6 +27,7 @@ fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
preserve_chevron_percent_template_syntax: env.call_method(*obj, "getPreserveChevronPercentTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
remove_bangs: env.call_method(*obj, "getRemoveBangs", "()Z", &[]).unwrap().z().unwrap(),
remove_processing_instructions: env.call_method(*obj, "getRemoveProcessingInstructions", "()Z", &[]).unwrap().z().unwrap(),
+ // END CONFIGURATION FIELDS
};
cfg
}
diff --git a/minify-html-java/update-java.sh b/minify-html-java/update-java.sh
new file mode 100755
index 00000000..9dd677d0
--- /dev/null
+++ b/minify-html-java/update-java.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+# Configuration paths
+RUST_CFG_FILE="../minify-html/src/cfg/mod.rs"
+JAVA_CONFIG_FILE="src/main/java/in/wilsonl/minifyhtml/Configuration.java"
+RUST_LIB_FILE="src/main/rust/lib.rs"
+
+# Function to convert snake_case to camelCase
+snake_to_camel() {
+ echo "$1" | sed -r 's/_([a-z])/\U\1/g'
+}
+
+# Function to capitalize first letter
+capitalize() {
+ echo "$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}"
+}
+
+echo "Extracting fields from Rust configuration..."
+
+# Extract field names using grep and sed
+rust_fields=$(grep -oP '^\s*pub \K[a-zA-Z0-9_]+(?=: bool,?\s*$)' "$RUST_CFG_FILE")
+
+if [ -z "$rust_fields" ]; then
+ echo "No boolean fields found in $RUST_CFG_FILE"
+ exit 1
+fi
+
+echo "Found fields:"
+while IFS= read -r field; do
+ echo " - $field"
+done <<< "$rust_fields"
+
+# Generate Java fields
+echo "Generating Java fields..."
+java_fields=""
+while IFS= read -r field; do
+ camel_field=$(snake_to_camel "$field")
+ java_fields="$java_fields boolean $camel_field;\n"
+done <<< "$rust_fields"
+
+# Update Java configuration file between markers
+echo "Updating Java configuration file..."
+temp_java=$(mktemp)
+awk -v fields="$java_fields" '
+ /\/\* BEGIN FIELD NAMES \*\// {
+ print $0
+ printf "%s", fields
+ skip=1
+ next
+ }
+ /\/\* END FIELD NAMES \*\// {
+ print $0
+ skip=0
+ next
+ }
+ !skip {
+ print
+ }
+' "$JAVA_CONFIG_FILE" > "$temp_java"
+mv "$temp_java" "$JAVA_CONFIG_FILE"
+
+# Generate Rust mappings
+echo "Generating Rust JNI mappings..."
+rust_mappings=""
+
+while IFS= read -r field; do
+ camel_field=$(snake_to_camel "$field")
+ getter_name="get$(capitalize "$camel_field")"
+
+ mapping=" $field: env.call_method(*obj, \"$getter_name\", \"()Z\", &[]).unwrap().z().unwrap(),"
+
+ rust_mappings="$rust_mappings$mapping\n"
+done <<< "$rust_fields"
+
+# Update Rust lib file between markers
+echo "Updating Rust library file..."
+temp_rust=$(mktemp)
+awk -v mappings="$rust_mappings" '
+ /\/\/ BEGIN CONFIGURATION FIELDS/ {
+ print $0
+ printf "%s", mappings
+ skip=1
+ next
+ }
+ /\/\/ END CONFIGURATION FIELDS/ {
+ print $0
+ skip=0
+ next
+ }
+ !skip {
+ print
+ }
+' "$RUST_LIB_FILE" > "$temp_rust"
+mv "$temp_rust" "$RUST_LIB_FILE"
+
+echo "Code generation completed!"
+echo "Updated files:"
+echo " - $JAVA_CONFIG_FILE"
+echo " - $RUST_LIB_FILE"
From a650c227bd45fff89f5f540477eb5bc211a719f3 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 12:32:07 +0200
Subject: [PATCH 09/11] fix: applied google java codestyle the original code
used 2-spaced indents and google java code seems to be most consistent to
this. - refactored some functions and finalized class
Signed-off-by: jogerj <[email protected]>
---
.../in/wilsonl/minifyhtml/Configuration.java | 46 +++++++++----------
.../in/wilsonl/minifyhtml/MinifyHtml.java | 46 ++++++++++---------
.../in/wilsonl/minifyhtml/MinifyHtmlTest.java | 2 +-
minify-html-java/update-java.sh | 2 +-
4 files changed, 50 insertions(+), 46 deletions(-)
mode change 100755 => 100644 minify-html-java/update-java.sh
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
index 3e8602dc..26ea77fd 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/Configuration.java
@@ -6,31 +6,31 @@
import lombok.Value;
/**
- * Class representing minification configuration.
- * Use the {@link Builder} to create an instance of this class.
+ * Class representing minification configuration. Use the {@link Builder} to create an instance of
+ * this class.
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
-@Builder(
- setterPrefix = "set",
- builderClassName = "Builder"
-)
+@Builder(setterPrefix = "set", builderClassName = "Builder")
@Value
public class Configuration {
- /* BEGIN FIELD NAMES */
- boolean allowNoncompliantUnquotedAttributeValues;
- boolean allowOptimalEntities;
- boolean allowRemovingSpacesBetweenAttributes;
- boolean keepClosingTags;
- boolean keepComments;
- boolean keepHtmlAndHeadOpeningTags;
- boolean keepInputTypeTextAttr;
- boolean keepSsiComments;
- boolean minifyCss;
- boolean minifyDoctype;
- boolean minifyJs;
- boolean preserveBraceTemplateSyntax;
- boolean preserveChevronPercentTemplateSyntax;
- boolean removeBangs;
- boolean removeProcessingInstructions;
- /* END FIELD NAMES */
+ // Do not change fields below or remove the markers.
+ // Use `update-java.sh` to generate config fields. Lombok takes care of the rest
+
+ /* BEGIN FIELD NAMES */
+ boolean allowNoncompliantUnquotedAttributeValues;
+ boolean allowOptimalEntities;
+ boolean allowRemovingSpacesBetweenAttributes;
+ boolean keepClosingTags;
+ boolean keepComments;
+ boolean keepHtmlAndHeadOpeningTags;
+ boolean keepInputTypeTextAttr;
+ boolean keepSsiComments;
+ boolean minifyCss;
+ boolean minifyDoctype;
+ boolean minifyJs;
+ boolean preserveBraceTemplateSyntax;
+ boolean preserveChevronPercentTemplateSyntax;
+ boolean removeBangs;
+ boolean removeProcessingInstructions;
+ /* END FIELD NAMES */
}
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
index b855f661..23bba536 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
@@ -6,11 +6,12 @@
import java.nio.file.StandardCopyOption;
/**
- * Class containing only static methods and exception classes. Cannot be instantiated.
- * Methods call to native compiled Rust code using JNI.
- * When this class is loaded, a static initialiser will attempt to load a prebuilt native library for the running operating system and architecture from the JAR. If it cannot, a {@link RuntimeException} will be thrown.
+ * Class containing only static methods and exception classes. Cannot be instantiated. Methods call
+ * to native compiled Rust code using JNI. When this class is loaded, a static initialiser will
+ * attempt to load a prebuilt native library for the running operating system and architecture from
+ * the JAR. If it cannot, a {@link RuntimeException} will be thrown.
*/
-public class MinifyHtml {
+public final class MinifyHtml {
static {
final String osName = System.getProperty("os.name").toLowerCase();
final String osArch = System.getProperty("os.arch").toLowerCase();
@@ -19,13 +20,16 @@ public class MinifyHtml {
final String nativeLibNameArch = getNativeLibNameArch(osArch);
if (nativeLibNameOs == null || nativeLibNameArch == null) {
- throw new RuntimeException(String.format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
+ throw new RuntimeException(
+ String.format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
}
- final String nativeLibFile = String.format("%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
+ final String nativeLibFile =
+ String.format("/%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
- try (InputStream is = MinifyHtml.class.getResourceAsStream("/" + nativeLibFile)) {
- final File temp = File.createTempFile("minify-html-java-nativelib", nativeLibFile);
+ try (InputStream is = MinifyHtml.class.getResourceAsStream(nativeLibFile)) {
+ final File temp =
+ File.createTempFile("minify-html-java-nativelib", nativeLibFile.substring(1));
temp.deleteOnExit();
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.load(temp.getAbsolutePath());
@@ -34,15 +38,14 @@ public class MinifyHtml {
}
}
- private MinifyHtml() {
- }
+ private MinifyHtml() {}
/**
- * Minify HTML code represented as a {@link String}.
- * The {@link String} will be copied to a UTF-8 byte array in native code, and then copied back into a Java {@link String}.
+ * Minify HTML code represented as a {@link String}. The {@link String} will be copied to a UTF-8
+ * byte array in native code, and then copied back into a Java {@link String}.
*
* @param code HTML code to minify, cannot be null
- * @param cfg {@link Configuration} minification settings to use, cannot be null
+ * @param cfg {@link Configuration} minification settings to use, cannot be null
* @return minified HTML code
* @throws IllegalArgumentException if either {@code code} or {@code cfg} is null
*/
@@ -59,24 +62,25 @@ public static String minify(String code, Configuration cfg) {
private static native String minifyRs(String code, Configuration cfg);
private static String getNativeLibNameOs(String osName) {
+ if (osName.startsWith("linux")) {
+ return "linux";
+ }
if (osName.startsWith("windows")) {
return "win";
- } else if (osName.startsWith("linux")) {
- return "linux";
- } else if (osName.startsWith("mac")) {
+ }
+ if (osName.startsWith("mac")) {
return "mac";
- } else {
- return null;
}
+ return null;
}
private static String getNativeLibNameArch(String osArch) {
if (osArch.equals("amd64") || osArch.equals("x86_64")) {
return "x64";
- } else if (osArch.equals("arm64") || osArch.equals("aarch64")) {
+ }
+ if (osArch.equals("arm64") || osArch.equals("aarch64")) {
return "aarch64";
- } else {
- return null;
}
+ return null;
}
}
diff --git a/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java b/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
index 9f52f3ab..f772bfc7 100644
--- a/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
+++ b/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
@@ -13,7 +13,7 @@ class MinifyHtmlTest {
void testMinifyHtmlCallsNativeFunction() {
final String input = " Hello World! ";
final String expected = "Hello World!";
- assertEquals(expected, MinifyHtml.minify(input, DEFAULT_CONFIG), "Basic HTML minification failed");
+ assertEquals(expected, MinifyHtml.minify(input, DEFAULT_CONFIG));
assertEquals("", MinifyHtml.minify("", DEFAULT_CONFIG));
}
diff --git a/minify-html-java/update-java.sh b/minify-html-java/update-java.sh
old mode 100755
new mode 100644
index 9dd677d0..ff3718de
--- a/minify-html-java/update-java.sh
+++ b/minify-html-java/update-java.sh
@@ -35,7 +35,7 @@ echo "Generating Java fields..."
java_fields=""
while IFS= read -r field; do
camel_field=$(snake_to_camel "$field")
- java_fields="$java_fields boolean $camel_field;\n"
+ java_fields="$java_fields boolean $camel_field;\n"
done <<< "$rust_fields"
# Update Java configuration file between markers
From db75854ac66e86834b3b973b4517ac16251e3546 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 12:48:31 +0200
Subject: [PATCH 10/11] feat: own exceptions to replace generic ones
Signed-off-by: jogerj <[email protected]>
---
.../in/wilsonl/minifyhtml/MinifyHtml.java | 37 ++++++++++---------
.../minifyhtml/MinifyHtmlException.java | 11 ++++++
2 files changed, 30 insertions(+), 18 deletions(-)
create mode 100644 minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtmlException.java
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
index 23bba536..4eee3127 100644
--- a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtml.java
@@ -13,28 +13,15 @@
*/
public final class MinifyHtml {
static {
- final String osName = System.getProperty("os.name").toLowerCase();
- final String osArch = System.getProperty("os.arch").toLowerCase();
-
- final String nativeLibNameOs = getNativeLibNameOs(osName);
- final String nativeLibNameArch = getNativeLibNameArch(osArch);
-
- if (nativeLibNameOs == null || nativeLibNameArch == null) {
- throw new RuntimeException(
- String.format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
- }
-
- final String nativeLibFile =
- String.format("/%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
-
- try (InputStream is = MinifyHtml.class.getResourceAsStream(nativeLibFile)) {
- final File temp =
- File.createTempFile("minify-html-java-nativelib", nativeLibFile.substring(1));
+ final String nativeLibFilePath = getNativeLibFilePath();
+ try (InputStream is = MinifyHtml.class.getResourceAsStream(nativeLibFilePath)) {
+ final String nativeLibFileName = nativeLibFilePath.substring(1);
+ final File temp = File.createTempFile("minify-html-java-nativelib", nativeLibFileName);
temp.deleteOnExit();
Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.load(temp.getAbsolutePath());
} catch (Exception e) {
- throw new RuntimeException("Failed to load native library", e);
+ throw new MinifyHtmlException("Failed to load native library", e);
}
}
@@ -61,6 +48,20 @@ public static String minify(String code, Configuration cfg) {
private static native String minifyRs(String code, Configuration cfg);
+ private static String getNativeLibFilePath() {
+ final String osName = System.getProperty("os.name").toLowerCase();
+ final String osArch = System.getProperty("os.arch").toLowerCase();
+
+ final String nativeLibNameOs = getNativeLibNameOs(osName);
+ final String nativeLibNameArch = getNativeLibNameArch(osArch);
+
+ if (nativeLibNameOs == null || nativeLibNameArch == null) {
+ throw new MinifyHtmlException(
+ String.format("Platform not supported (os.name=%s, os.arch=%s)", osName, osArch));
+ }
+ return String.format("/%s-%s.nativelib", nativeLibNameOs, nativeLibNameArch);
+ }
+
private static String getNativeLibNameOs(String osName) {
if (osName.startsWith("linux")) {
return "linux";
diff --git a/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtmlException.java b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtmlException.java
new file mode 100644
index 00000000..6703b905
--- /dev/null
+++ b/minify-html-java/src/main/java/in/wilsonl/minifyhtml/MinifyHtmlException.java
@@ -0,0 +1,11 @@
+package in.wilsonl.minifyhtml;
+
+public class MinifyHtmlException extends RuntimeException {
+ MinifyHtmlException(String message) {
+ super(message);
+ }
+
+ MinifyHtmlException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
From 3e3e4353b37ff1605019268e67f52e431a236ab2 Mon Sep 17 00:00:00 2001
From: jogerj <[email protected]>
Date: Sat, 28 Jun 2025 14:01:28 +0200
Subject: [PATCH 11/11] fix: wrong getter prefix for boolean added tests to
prevent this
Signed-off-by: jogerj <[email protected]>
---
minify-html-java/src/main/rust/lib.rs | 30 +++++------
.../in/wilsonl/minifyhtml/MinifyHtmlTest.java | 50 ++++++++++++++++++-
minify-html-java/update-java.sh | 2 +-
3 files changed, 64 insertions(+), 18 deletions(-)
diff --git a/minify-html-java/src/main/rust/lib.rs b/minify-html-java/src/main/rust/lib.rs
index c80ba3b8..2133c303 100644
--- a/minify-html-java/src/main/rust/lib.rs
+++ b/minify-html-java/src/main/rust/lib.rs
@@ -12,21 +12,21 @@ fn build_cfg(env: &JNIEnv, obj: &JObject) -> Cfg {
// This is a statement because "attributes on expressions are experimental".
let cfg = Cfg {
// BEGIN CONFIGURATION FIELDS
- allow_noncompliant_unquoted_attribute_values: env.call_method(*obj, "getAllowNoncompliantUnquotedAttributeValues", "()Z", &[]).unwrap().z().unwrap(),
- allow_optimal_entities: env.call_method(*obj, "getAllowOptimalEntities", "()Z", &[]).unwrap().z().unwrap(),
- allow_removing_spaces_between_attributes: env.call_method(*obj, "getAllowRemovingSpacesBetweenAttributes", "()Z", &[]).unwrap().z().unwrap(),
- keep_closing_tags: env.call_method(*obj, "getKeepClosingTags", "()Z", &[]).unwrap().z().unwrap(),
- keep_comments: env.call_method(*obj, "getKeepComments", "()Z", &[]).unwrap().z().unwrap(),
- keep_html_and_head_opening_tags: env.call_method(*obj, "getKeepHtmlAndHeadOpeningTags", "()Z", &[]).unwrap().z().unwrap(),
- keep_input_type_text_attr: env.call_method(*obj, "getKeepInputTypeTextAttr", "()Z", &[]).unwrap().z().unwrap(),
- keep_ssi_comments: env.call_method(*obj, "getKeepSsiComments", "()Z", &[]).unwrap().z().unwrap(),
- minify_css: env.call_method(*obj, "getMinifyCss", "()Z", &[]).unwrap().z().unwrap(),
- minify_doctype: env.call_method(*obj, "getMinifyDoctype", "()Z", &[]).unwrap().z().unwrap(),
- minify_js: env.call_method(*obj, "getMinifyJs", "()Z", &[]).unwrap().z().unwrap(),
- preserve_brace_template_syntax: env.call_method(*obj, "getPreserveBraceTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
- preserve_chevron_percent_template_syntax: env.call_method(*obj, "getPreserveChevronPercentTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
- remove_bangs: env.call_method(*obj, "getRemoveBangs", "()Z", &[]).unwrap().z().unwrap(),
- remove_processing_instructions: env.call_method(*obj, "getRemoveProcessingInstructions", "()Z", &[]).unwrap().z().unwrap(),
+ allow_noncompliant_unquoted_attribute_values: env.call_method(*obj, "isAllowNoncompliantUnquotedAttributeValues", "()Z", &[]).unwrap().z().unwrap(),
+ allow_optimal_entities: env.call_method(*obj, "isAllowOptimalEntities", "()Z", &[]).unwrap().z().unwrap(),
+ allow_removing_spaces_between_attributes: env.call_method(*obj, "isAllowRemovingSpacesBetweenAttributes", "()Z", &[]).unwrap().z().unwrap(),
+ keep_closing_tags: env.call_method(*obj, "isKeepClosingTags", "()Z", &[]).unwrap().z().unwrap(),
+ keep_comments: env.call_method(*obj, "isKeepComments", "()Z", &[]).unwrap().z().unwrap(),
+ keep_html_and_head_opening_tags: env.call_method(*obj, "isKeepHtmlAndHeadOpeningTags", "()Z", &[]).unwrap().z().unwrap(),
+ keep_input_type_text_attr: env.call_method(*obj, "isKeepInputTypeTextAttr", "()Z", &[]).unwrap().z().unwrap(),
+ keep_ssi_comments: env.call_method(*obj, "isKeepSsiComments", "()Z", &[]).unwrap().z().unwrap(),
+ minify_css: env.call_method(*obj, "isMinifyCss", "()Z", &[]).unwrap().z().unwrap(),
+ minify_doctype: env.call_method(*obj, "isMinifyDoctype", "()Z", &[]).unwrap().z().unwrap(),
+ minify_js: env.call_method(*obj, "isMinifyJs", "()Z", &[]).unwrap().z().unwrap(),
+ preserve_brace_template_syntax: env.call_method(*obj, "isPreserveBraceTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
+ preserve_chevron_percent_template_syntax: env.call_method(*obj, "isPreserveChevronPercentTemplateSyntax", "()Z", &[]).unwrap().z().unwrap(),
+ remove_bangs: env.call_method(*obj, "isRemoveBangs", "()Z", &[]).unwrap().z().unwrap(),
+ remove_processing_instructions: env.call_method(*obj, "isRemoveProcessingInstructions", "()Z", &[]).unwrap().z().unwrap(),
// END CONFIGURATION FIELDS
};
cfg
diff --git a/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java b/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
index f772bfc7..f6fef86d 100644
--- a/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
+++ b/minify-html-java/src/test/java/in/wilsonl/minifyhtml/MinifyHtmlTest.java
@@ -1,9 +1,11 @@
package in.wilsonl.minifyhtml;
+import java.lang.reflect.Method;
+import lombok.val;
import org.junit.jupiter.api.Test;
+import org.junit.platform.commons.util.ReflectionUtils;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.*;
class MinifyHtmlTest {
@@ -23,4 +25,48 @@ void testNullParametersHandled() {
assertThrows(IllegalArgumentException.class, () -> MinifyHtml.minify("", null));
assertThrows(IllegalArgumentException.class, () -> MinifyHtml.minify(null, null));
}
+
+ @Test
+ void testAllConfigsEnabled() {
+ // dynamically find all config flags in Configuration.Builder
+ val configSetters =
+ ReflectionUtils.findMethods(Configuration.Builder.class, this::isBooleanSetter);
+ val configBuilder = new Configuration.Builder();
+ // enable all boolean configuration options
+ assertDoesNotThrow(
+ () -> {
+ for (val method : configSetters) {
+ method.invoke(configBuilder, true);
+ }
+ });
+
+ val config = configBuilder.build();
+
+ val configGetters = ReflectionUtils.findMethods(Configuration.class, this::isBooleanGetter);
+ // verify all boolean configuration options are enabled
+ assertDoesNotThrow(
+ () -> {
+ for (val method : configGetters) {
+ assertTrue(
+ (boolean) method.invoke(config),
+ "Configuration option " + method.getName() + " should be true");
+ }
+ });
+
+ final String input = " Hello World! ";
+ final String expected = "Hello World!";
+ assertEquals(expected, MinifyHtml.minify(input, config));
+ }
+
+ private boolean isBooleanSetter(Method method) {
+ return method.getName().startsWith("set")
+ && method.getParameterCount() == 1
+ && method.getParameterTypes()[0] == boolean.class;
+ }
+
+ private boolean isBooleanGetter(Method method) {
+ return method.getName().startsWith("is")
+ && method.getParameterCount() == 0
+ && method.getReturnType() == boolean.class;
+ }
}
diff --git a/minify-html-java/update-java.sh b/minify-html-java/update-java.sh
index ff3718de..bbc8d2e1 100644
--- a/minify-html-java/update-java.sh
+++ b/minify-html-java/update-java.sh
@@ -65,7 +65,7 @@ rust_mappings=""
while IFS= read -r field; do
camel_field=$(snake_to_camel "$field")
- getter_name="get$(capitalize "$camel_field")"
+ getter_name="is$(capitalize "$camel_field")"
mapping=" $field: env.call_method(*obj, \"$getter_name\", \"()Z\", &[]).unwrap().z().unwrap(),"