diff --git a/README.md b/README.md
index 636d1d2..e95eb63 100644
--- a/README.md
+++ b/README.md
@@ -37,6 +37,7 @@ compared to other solutions like the standard `URLEncoder` in the JDK.
UrlEncoder.encode("a test &") // -> a%20test%20%26
UrlEncoder.encode("%#okékÉȢ smile!😁") // -> %25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81
UrlEncoder.encode("?test=a test", allow = "?=") // -> ?test=a%20test
+UrlEncoder.endode("foo bar", spaceToPlus = true) // -> foo+bar
UrlEncoder.decode("a%20test%20%26") // -> a test &
UrlEncoder.decode("%25%23ok%C3%A9k%C3%89%C8%A2%20smile%21%F0%9F%98%81") // -> %#okékÉȢ smile!😁
diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts
index 4787125..19d997f 100644
--- a/lib/build.gradle.kts
+++ b/lib/build.gradle.kts
@@ -23,7 +23,7 @@ plugins {
description = "A simple defensive library to encode/decode URL components"
group = "net.thauvin.erik"
-version = "1.0.1"
+version = "1.2.1-SNAPSHOT"
val mavenName = "UrlEncoder"
@@ -40,7 +40,7 @@ repositories {
dependencies {
// testImplementation("com.willowtreeapps.assertk:assertk-jvm:0.25")
- testImplementation("org.junit.jupiter:junit-jupiter:5.9.0")
+ testImplementation("org.junit.jupiter:junit-jupiter:5.9.1")
}
base {
diff --git a/lib/detekt-baseline.xml b/lib/detekt-baseline.xml
index f4b9fda..571f54a 100644
--- a/lib/detekt-baseline.xml
+++ b/lib/detekt-baseline.xml
@@ -9,6 +9,6 @@
MagicNumber:UrlEncoder.kt$UrlEncoder$3
MagicNumber:UrlEncoder.kt$UrlEncoder$4
MaxLineLength:UrlEncoder.kt$UrlEncoder$*
- NestedBlockDepth:UrlEncoder.kt$UrlEncoder$@JvmStatic fun encode(source: String, allow: String): String
+ NestedBlockDepth:UrlEncoder.kt$UrlEncoder$@JvmStatic @JvmOverloads fun encode(source: String, allow: String = "", spaceToPlus: Boolean = false): String
diff --git a/lib/pom.xml b/lib/pom.xml
index 25f1f01..7a70ae1 100644
--- a/lib/pom.xml
+++ b/lib/pom.xml
@@ -8,7 +8,7 @@
4.0.0
net.thauvin.erik
urlencoder
- 1.0.1
+ 1.2.1-SNAPSHOT
UrlEncoder for Kotlin
A simple defensive library to encode/decode URL components
https://github.com/ethauvin/urlencoder
diff --git a/lib/src/main/kotlin/net/thauvin/erik/urlencoder/UrlEncoder.kt b/lib/src/main/kotlin/net/thauvin/erik/urlencoder/UrlEncoder.kt
index d39b354..37ea9c2 100644
--- a/lib/src/main/kotlin/net/thauvin/erik/urlencoder/UrlEncoder.kt
+++ b/lib/src/main/kotlin/net/thauvin/erik/urlencoder/UrlEncoder.kt
@@ -40,7 +40,7 @@ import kotlin.system.exitProcess
object UrlEncoder {
private val hexDigits = "0123456789ABCDEF".toCharArray()
internal val usage =
- "Usage : java -jar urlencoder-*all.jar [-ed] text" + System.lineSeparator() +
+ "Usage : java -jar urlencoder-*all.jar [-ed] " + System.lineSeparator() +
"Encode and decode URL components defensively." + System.lineSeparator() + " -e encode (default) " +
System.lineSeparator() + " -d decode"
@@ -85,7 +85,7 @@ object UrlEncoder {
*/
@JvmStatic
fun decode(source: String): String {
- if (source.isBlank()) {
+ if (source.isEmpty()) {
return source
}
@@ -142,7 +142,8 @@ object UrlEncoder {
* - Letters, numbers, unreserved (`_-!.'()*`) and allowed characters are left intact.
*/
@JvmStatic
- fun encode(source: String, allow: String): String {
+ @JvmOverloads
+ fun encode(source: String, allow: String = "", spaceToPlus: Boolean = false): String {
if (source.isEmpty()) {
return source
}
@@ -159,22 +160,27 @@ object UrlEncoder {
out = StringBuilder(source.length)
out.append(source, 0, i)
}
- val cp = source.codePointAt(i)
- if (cp < 0x80) {
- out.appendEncodedByte(cp)
+ if (spaceToPlus && ch == ' ') {
+ out.append('+')
i++
- } else if (Character.isBmpCodePoint(cp)) {
- for (b in ch.toString().toByteArray(StandardCharsets.UTF_8)) {
- out.appendEncodedByte(b.toInt())
+ } else {
+ val cp = source.codePointAt(i)
+ if (cp < 0x80) {
+ out.appendEncodedByte(cp)
+ i++
+ } else if (Character.isBmpCodePoint(cp)) {
+ for (b in ch.toString().toByteArray(StandardCharsets.UTF_8)) {
+ out.appendEncodedByte(b.toInt())
+ }
+ i++
+ } else if (Character.isSupplementaryCodePoint(cp)) {
+ val high = Character.highSurrogate(cp)
+ val low = Character.lowSurrogate(cp)
+ for (b in charArrayOf(high, low).concatToString().toByteArray(StandardCharsets.UTF_8)) {
+ out.appendEncodedByte(b.toInt())
+ }
+ i += 2
}
- i++
- } else if (Character.isSupplementaryCodePoint(cp)) {
- val high = Character.highSurrogate(cp)
- val low = Character.lowSurrogate(cp)
- for (b in charArrayOf(high, low).concatToString().toByteArray(StandardCharsets.UTF_8)) {
- out.appendEncodedByte(b.toInt())
- }
- i += 2
}
}
}
@@ -182,17 +188,6 @@ object UrlEncoder {
return out?.toString() ?: source
}
- /**
- * Transforms a provided [String] object into a new string, containing only valid URL characters in the UTF-8
- * encoding.
- *
- * - Letters, numbers, unreserved (`_-!.'()*`) and allowed characters are left intact.
- */
- @JvmStatic
- fun encode(source: String, vararg allow: Char): String {
- return encode(source, String(allow))
- }
-
/**
* Encodes and decodes URLs from the command line.
*
diff --git a/lib/src/test/kotlin/net/thauvin/erik/urlencoder/UrlEncoderTest.kt b/lib/src/test/kotlin/net/thauvin/erik/urlencoder/UrlEncoderTest.kt
index 79658e0..a99a29e 100644
--- a/lib/src/test/kotlin/net/thauvin/erik/urlencoder/UrlEncoderTest.kt
+++ b/lib/src/test/kotlin/net/thauvin/erik/urlencoder/UrlEncoderTest.kt
@@ -81,23 +81,29 @@ class UrlEncoderTest {
@Test
fun `Encode Empty or Blank`() {
- assertTrue(encode("", "").isEmpty(), "encode('','')")
+ assertTrue(encode("", allow = "").isEmpty(), "encode('','')")
assertEquals("", encode(""), "encode('')")
- assertEquals("%20", encode(" "), "encode('')")
+ assertEquals("%20", encode(" "), "encode(' ')")
}
@Test
fun `Encode when None needed`() {
assertSame(same, encode(same))
- assertSame(same, encode(same, ""), "with empty allow")
+ assertSame(same, encode(same, allow = ""), "with empty allow")
}
@Test
fun `Encode with Allow Arg`() {
- assertEquals("?test=a%20test", encode("?test=a test", '=', '?'), "encode(x, =, ?)")
- assertEquals("?test=a%20test", encode("?test=a test", "=?"), "encode(x, =?)")
- assertEquals("aaa", encode("aaa", 'a'), "encode(aaa, a)")
- assertEquals(" ", encode(" ", ' '), "encode(' ', ' ')")
+ assertEquals("?test=a%20test", encode("?test=a test", allow = "=?"), "encode(x, =?)")
+ assertEquals("aaa", encode("aaa", "a"), "encode(aaa, a)")
+ assertEquals(" ", encode(" ", " "), "encode(' ', ' ')")
+ }
+
+ @Test
+ fun `Encode with Space to Plus`() {
+ assertEquals("foo+bar", encode("foo bar", spaceToPlus = true))
+ assertEquals("foo+bar++foo", encode("foo bar foo", spaceToPlus = true))
+ assertEquals("foo bar", encode("foo bar", " ", true))
}
@ParameterizedTest(name = "processMain(-d {1}) should be {0}")