Skip to content

Commit

Permalink
Merge pull request #35 from fleeksoft/kotlinx-io
Browse files Browse the repository at this point in the history
replace okio with Kotlinx.io
  • Loading branch information
itboy87 authored Jul 25, 2024
2 parents 6fea1b0 + 6f73015 commit 32c9218
Show file tree
Hide file tree
Showing 58 changed files with 319 additions and 439 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ local.properties
xcuserdata
/gpg/
/kotlin-js-store/
.kotlin
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

**Ksoup** is a Kotlin Multiplatform library for working with real-world HTML and XML. It's a port of the renowned Java library, **jsoup**, and offers an easy-to-use API for URL fetching, data parsing, extraction, and manipulation using DOM and CSS selectors.

[![Kotlin](https://img.shields.io/badge/Kotlin-1.9.22-blue.svg?style=flat&logo=kotlin)](https://kotlinlang.org)
[![Kotlin](https://img.shields.io/badge/Kotlin-2.0.0-blue.svg?style=flat&logo=kotlin)](https://kotlinlang.org)
[![Maven Central](https://img.shields.io/maven-central/v/com.fleeksoft.ksoup/ksoup.svg)](https://mvnrepository.com/artifact/com.fleeksoft.ksoup)

![badge-android](http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat)
![badge-ios](http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat)
![badge-mac](http://img.shields.io/badge/platform-macos-111111.svg?style=flat)
![badge-watchos](http://img.shields.io/badge/platform-watchos-C0C0C0.svg?style=flat)
![badge-tvos](http://img.shields.io/badge/platform-tvos-808080.svg?style=flat)
![badge-jvm](http://img.shields.io/badge/platform-jvm-DB413D.svg?style=flat)
![badge-linux](http://img.shields.io/badge/platform-linux-2D3F6C.svg?style=flat)
![badge-windows](http://img.shields.io/badge/platform-windows-4D76CD.svg?style=flat)
![badge-nodejs](https://img.shields.io/badge/platform-jsNode-F8DB5D.svg?style=flat)

Ksoup implements the [WHATWG HTML5](https://html.spec.whatwg.org/multipage/) specification, parsing HTML to the same DOM as modern browsers do, but with support for Android, JVM, and native platforms.
Expand Down
22 changes: 10 additions & 12 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
[versions]
agp = "8.2.0"
kotlin = "1.9.22"
agp = "8.2.2" #kmp max gradle support 8.2 right now
kotlin = "2.0.0"
compileSdk = "34"
minSdk = "21"
libraryVersion = "0.1.2"
ktor = "2.3.7"
coroutines = "1.7.3"
okio = "3.7.0"
kotlinxDatetime = "0.5.0"
kotlinx-io = "0.3.0"
codepoints = "0.6.1"
dokka = "1.9.10"
ktor = "3.0.0-beta-2"
coroutines = "1.8.1"
kotlinx-io = "0.5.1"
kotlinxDatetime = "0.6.0"
codepoints = "0.9.0"
dokka = "1.9.20"


[libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" }
ktor-client-win = { module = "io.ktor:ktor-client-winhttp", version.ref = "ktor" }
okio = { module = "com.squareup.okio:okio", version.ref = "okio" }
okio-nodefilesystem = { module = "com.squareup.okio:okio-nodefilesystem", version.ref = "okio" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
codepoints = { module = "de.cketti.unicode:kotlin-codepoints-deluxe", version.ref = "codepoints" }

[plugins]
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
20 changes: 10 additions & 10 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand All @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand Down
6 changes: 3 additions & 3 deletions ksoup-network/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
jvmTarget = "11"
}
}
}
Expand Down Expand Up @@ -118,8 +118,8 @@ android {
minSdk = libs.versions.minSdk.get().toInt()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}

Expand Down
11 changes: 5 additions & 6 deletions ksoup/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ kotlin {
androidTarget {
compilations.all {
kotlinOptions {
jvmTarget = "17"
jvmTarget = "11"
}
}
}
Expand Down Expand Up @@ -61,13 +61,13 @@ kotlin {
implementation(libs.ktor.client.core)
implementation(libs.kotlinx.datetime)
implementation(libs.codepoints)
api(libs.okio)
api(libs.kotlinx.io)
}
commonTest {
this.kotlin.srcDir(layout.buildDirectory.file(rootPath))
dependencies {
implementation(libs.kotlin.test)
implementation(projects.ksoupNetwork)
implementation(libs.kotlinx.coroutines.test)
}
}

Expand All @@ -84,7 +84,6 @@ kotlin {
}

jsMain.dependencies {
implementation(libs.okio.nodefilesystem)
}

val jvmAndroidCommonMain by creating {
Expand Down Expand Up @@ -117,8 +116,8 @@ android {
minSdk = libs.versions.minSdk.get().toInt()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package com.fleeksoft.ksoup

import okio.*
import io.ktor.utils.io.streams.*
import kotlinx.io.RawSource
import kotlinx.io.asSource
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
import java.util.zip.GZIPInputStream

internal actual fun readGzipFile(file: Path): BufferedSource {
return readFile(file).gzip().buffer()
}

internal actual fun readFile(file: Path): BufferedSource {
return FileSystem.SYSTEM.source(file).buffer()
internal actual fun readGzipFile(file: Path): RawSource {
return GZIPInputStream(SystemFileSystem.source(file).buffered().inputStream()).asSource()
}

public actual object Platform {
Expand Down

This file was deleted.

14 changes: 7 additions & 7 deletions ksoup/src/appleMain/kotlin/com/fleeksoft/ksoup/Platform.apple.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package com.fleeksoft.ksoup

import okio.*
import kotlinx.io.Buffer
import kotlinx.io.RawSource
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.readByteArray

internal actual fun readGzipFile(file: Path): BufferedSource {
internal actual fun readGzipFile(file: Path): RawSource {
// TODO: optimize for BufferedSource without reading all bytes
return Buffer().apply {
write(decompressGzip(readFile(file).buffer().readByteArray()))
write(decompressGzip(readFile(file).buffered().readByteArray()))
}
}

internal actual fun readFile(file: Path): BufferedSource {
return FileSystem.SYSTEM.source(file).buffer()
}

public actual object Platform {
public actual val current: PlatformType
get() = PlatformType.IOS
Expand Down
22 changes: 8 additions & 14 deletions ksoup/src/commonMain/kotlin/com/fleeksoft/ksoup/Ksoup.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import com.fleeksoft.ksoup.parser.Parser
import com.fleeksoft.ksoup.ported.BufferReader
import com.fleeksoft.ksoup.safety.Cleaner
import com.fleeksoft.ksoup.safety.Safelist
import okio.IOException
import okio.Path.Companion.toPath
import kotlinx.io.IOException
import kotlinx.io.files.Path

/**
* The core public access point to the com.fleeksoft.ksoup functionality.
Expand Down Expand Up @@ -88,13 +88,12 @@ public object Ksoup {
* @return sane HTML
* @throws IOException if the file could not be found, or read, or if the charsetName is invalid.
*/
@Throws(IOException::class)
public fun parseFile(
file: String,
baseUri: String,
charsetName: String? = null,
): Document {
val filePath = file.toPath()
val filePath = Path(file)
return DataUtil.load(filePath, charsetName, baseUri)
}

Expand All @@ -108,12 +107,11 @@ public object Ksoup {
* @throws IOException if the file could not be found, or read, or if the charsetName is invalid.
* @see .parse
*/
@Throws(IOException::class)
public fun parseFile(
file: String,
charsetName: String? = null,
): Document {
val filePath = file.toPath()
val filePath = Path(file)
return DataUtil.load(filePath, charsetName, filePath.toString())
}

Expand All @@ -130,9 +128,8 @@ public object Ksoup {
* @throws IOException if the file could not be found or read.
* @see .parse
*/
@Throws(IOException::class)
public fun parseFile(file: String): Document {
val filePath = file.toPath()
val filePath = Path(file)
return DataUtil.load(filePath, null, filePath.toString())
}

Expand All @@ -147,14 +144,13 @@ public object Ksoup {
* @return sane HTML
* @throws IOException if the file could not be found, or read, or if the charsetName is invalid.
*/
@Throws(IOException::class)
public fun parseFile(
file: String,
baseUri: String,
charsetName: String?,
parser: Parser,
): Document {
return DataUtil.load(file.toPath(), charsetName, baseUri, parser)
return DataUtil.load(Path(file), charsetName, baseUri, parser)
}

/**
Expand All @@ -167,7 +163,6 @@ public object Ksoup {
* @return sane HTML
* @throws IOException if the file could not be found, or read, or if the charsetName is invalid.
*/
@Throws(IOException::class)
public fun parse(
bufferReader: BufferReader,
baseUri: String,
Expand All @@ -188,7 +183,6 @@ public object Ksoup {
* @return sane HTML
* @throws IOException if the file could not be found, or read, or if the charsetName is invalid.
*/
@Throws(IOException::class)
public fun parse(
bufferReader: BufferReader,
baseUri: String,
Expand Down Expand Up @@ -270,7 +264,7 @@ public object Ksoup {
*
* // html is: 5 is < 6.
* // text is: 5 is < 6.
`</pre> *
`</pre> *
*
* @param bodyHtml input untrusted HTML (body fragment)
* @param safelist list of permitted HTML elements
Expand Down Expand Up @@ -327,7 +321,7 @@ public object Ksoup {
* <pre>`val safelist = Safelist.relaxed()
* val isValid = Ksoup.isValid(sourceBodyHtml, safelist)
* val normalizedHtml = Ksoup.clean(sourceBodyHtml, "https://example.com/", safelist)
`</pre> *
`</pre> *
*
* Assumes the HTML is a body fragment (i.e. will be used in an existing HTML document body.)
* @param bodyHtml HTML to test
Expand Down
16 changes: 11 additions & 5 deletions ksoup/src/commonMain/kotlin/com/fleeksoft/ksoup/Platform.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package com.fleeksoft.ksoup

import okio.BufferedSource
import okio.Path
import kotlinx.io.RawSource
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem

internal expect fun readGzipFile(file: Path): BufferedSource
internal expect fun readGzipFile(file: Path): RawSource

internal expect fun readFile(file: Path): BufferedSource
internal fun readFile(file: Path): RawSource {
return SystemFileSystem.source(file)
}

// js don't support ?i
internal fun jsSupportedRegex(regex: String): Regex {
return if (Platform.current == PlatformType.JS && regex.contains("(?i)")) {
return if (Platform.isJS() && regex.contains("(?i)")) {
Regex(regex.replace("(?i)", ""), RegexOption.IGNORE_CASE)
} else {
Regex(regex)
Expand All @@ -22,6 +25,7 @@ public enum class PlatformType {
IOS,
LINUX,
JS,
WASM,
MAC,
WINDOWS,
}
Expand All @@ -37,3 +41,5 @@ public fun Platform.isWindows(): Boolean = this.current == PlatformType.WINDOWS
public fun Platform.isJvmOrAndroid(): Boolean = this.current == PlatformType.JVM || this.current == PlatformType.ANDROID

public fun Platform.isJvm(): Boolean = this.current == PlatformType.JVM

public fun Platform.isJS(): Boolean = this.current == PlatformType.JS
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.fleeksoft.ksoup

import okio.IOException
import kotlinx.io.IOException

public class UncheckedIOException : Exception {
public constructor(cause: IOException?) : super(cause)
Expand Down
Loading

0 comments on commit 32c9218

Please sign in to comment.