diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index b487ce2..91a3e02 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -17,7 +17,7 @@ jobs:
distribution: 'zulu'
java-version: 21
- name: Publish to MavenCentral
- run: ./gradlew publishToMavenCentral --no-configuration-cache
+ run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 8012ec0..a537b7e 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -10,6 +10,7 @@
+
diff --git a/README.md b/README.md
index 0230aed..ea90f46 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
# OpenGraphKt
+
+
+
[OpenGraphKt](https://github.com/jlengrand/OpenGraphKt) is a minimalist Kotlin library to work with the [Open Graph tags](https://ogp.me/) protocol.
OpenGraphKt is a tiny wrapper on top of JSoup.
diff --git a/demo-remote/build.gradle.kts b/demo-remote/build.gradle.kts
new file mode 100644
index 0000000..9b66ba2
--- /dev/null
+++ b/demo-remote/build.gradle.kts
@@ -0,0 +1,28 @@
+plugins {
+ kotlin("jvm")
+ application
+}
+
+group = "fr.lengrand"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation("org.jsoup:jsoup:1.20.1")
+ implementation("fr.lengrand:opengraphkt:0.0.1")
+ testImplementation(kotlin("test"))
+}
+
+tasks.test {
+ useJUnitPlatform()
+}
+
+kotlin {
+ jvmToolchain(23)
+}
+
+application {
+ mainClass = "fr.lengrand.opengraphkt.MainKt"
+}
diff --git a/demo-remote/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt b/demo-remote/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt
new file mode 100644
index 0000000..fdb0624
--- /dev/null
+++ b/demo-remote/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt
@@ -0,0 +1,38 @@
+package fr.lengrand.opengraphkt
+
+import org.jsoup.Jsoup
+
+/**
+ * This module is only here to verify that the latest Maven Central release can be imported and used as intended.
+ */
+fun main() {
+ val parser = OpenGraphParser()
+
+ val html = """
+
+
+
+ Open Graph Example
+
+
+
+
+
+
+
+
+
+
+ Example Page
+
+
+ """.trimIndent()
+
+ println("Parsing from JSoup Document")
+
+ val doc = Jsoup.parse(html)
+ val openGraphDataDoc = parser.parse(doc)
+
+ println("Title: ${openGraphDataDoc.title}")
+ println("Is valid: ${openGraphDataDoc.isValid()}")
+}
diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts
index 60bfb31..a5b42ca 100644
--- a/demo/build.gradle.kts
+++ b/demo/build.gradle.kts
@@ -1,12 +1,11 @@
import org.gradle.kotlin.dsl.implementation
plugins {
- kotlin("jvm") version "2.1.21"
+ kotlin("jvm")
application
}
-group = "nl.lengrand"
-version = "0.1-SNAPSHOT"
+group = "fr.lengrand"
repositories {
mavenCentral()
@@ -18,22 +17,10 @@ dependencies {
testImplementation(kotlin("test"))
}
-java {
- withSourcesJar()
-}
-
tasks.test {
useJUnitPlatform()
}
-tasks.jar {
- manifest {
- attributes(mapOf("Implementation-Title" to project.name,
- "Implementation-Version" to project.version))
- }
-}
-
-
kotlin {
jvmToolchain(23)
}
diff --git a/demo/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt b/demo/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt
index bf6f773..84d4109 100644
--- a/demo/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt
+++ b/demo/src/main/kotlin/fr/lengrand/opengraphkt/Main.kt
@@ -1,19 +1,19 @@
package fr.lengrand.opengraphkt
+import org.jsoup.Jsoup
import java.io.File
+import java.net.URI
/**
* Example demonstrating how to use the OpenGraphParser to extract Open Graph data from HTML.
*/
fun main() {
val parser = OpenGraphParser()
- val fetcher = DocumentFetcher()
// Example 1: Parse Open Graph data from a URL
println("Example 1: Parsing from URL")
try {
- val document = fetcher.fromUrl("https://www.imdb.com/title/tt0068646/")
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(URI("https://www.imdb.com/title/tt0068646/").toURL())
println("Title: ${openGraphData.title}")
println("Is valid: ${openGraphData.isValid()}")
@@ -28,8 +28,7 @@ fun main() {
val resourceFile = File(resourceUrl.toURI())
// Parse the file
- val document = fetcher.fromFile(resourceFile)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(resourceFile)
println("Title: ${openGraphData.title}")
println("Is valid: ${openGraphData.isValid()}")
@@ -38,7 +37,7 @@ fun main() {
}
// Example 3: Parse Open Graph data from an HTML string
- println("\nExample 2: Parsing from HTML string")
+ println("\nExample 3: Parsing from HTML string")
val html = """
@@ -59,9 +58,17 @@ fun main() {
""".trimIndent()
- val document = fetcher.fromString(html)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(html)
println("Title: ${openGraphData.title}")
println("Is valid: ${openGraphData.isValid()}")
+
+ // Example 4: Parse Open Graph data from a Jsoup Document
+ println("\nExample 4: Parsing from JSoup Document")
+
+ val doc = Jsoup.parse(html)
+ val openGraphDataDoc = parser.parse(doc)
+
+ println("Title: ${openGraphDataDoc.title}")
+ println("Is valid: ${openGraphDataDoc.isValid()}")
}
diff --git a/opengraphkt/src/main/resources/example.html b/demo/src/main/resources/example.html
similarity index 100%
rename from opengraphkt/src/main/resources/example.html
rename to demo/src/main/resources/example.html
diff --git a/opengraphkt/build.gradle.kts b/opengraphkt/build.gradle.kts
index 337ee2f..513f22e 100644
--- a/opengraphkt/build.gradle.kts
+++ b/opengraphkt/build.gradle.kts
@@ -1,7 +1,7 @@
import com.vanniktech.maven.publish.SonatypeHost
plugins {
- kotlin("jvm") version "2.1.21"
+ kotlin("jvm")
id("com.vanniktech.maven.publish") version "0.30.0"
}
diff --git a/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/DocumentFetcher.kt b/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/DocumentFetcher.kt
deleted file mode 100644
index e7e78ec..0000000
--- a/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/DocumentFetcher.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package fr.lengrand.opengraphkt
-
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Document
-import java.io.File
-
-/**
- * DocumentFetcher's job is to take any type of input and transform it into a JSoup document for the Parser to then do its job
- */
-class DocumentFetcher {
-
- fun fromUrl(url: String): Document {
- return Jsoup.connect(url).get()
- }
-
- fun fromString(html: String): Document {
- return Jsoup.parse(html)
- }
-
- /**
- * Parses HTML from a file and returns a JSoup Document
- * @param file The file to parse
- * @param charsetName The charset to use for parsing (default is UTF-8)
- * @return A JSoup Document representing the parsed HTML
- */
- fun fromFile(file: File, charsetName: String = "UTF-8") : Document {
- return Jsoup.parse(file, charsetName)
- }
-}
diff --git a/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/OpenGraphParser.kt b/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/OpenGraphParser.kt
index 776d1a7..12a8409 100644
--- a/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/OpenGraphParser.kt
+++ b/opengraphkt/src/main/kotlin/fr/lengrand/opengraphkt/OpenGraphParser.kt
@@ -1,7 +1,10 @@
package fr.lengrand.opengraphkt
+import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements
+import java.io.File
+import java.net.URL
data class OpenGraphTag(
val property: String,
@@ -149,6 +152,40 @@ class OpenGraphParser {
return buildOpenGraphData(openGraphTags)
}
+ /**
+ * Extracts all Open Graph tags from a URL and returns a structured OpenGraphData object.
+ *
+ * @param url The URL to be parsed for Open Graph information.
+ * @return An OpenGraphData object containing all extracted Open Graph data.
+ */
+ fun parse(url: URL) : OpenGraphData {
+ val doc = Jsoup.connect(url.toString()).get()
+ return parse(doc)
+ }
+
+ /**
+ * Extracts all Open Graph tags from a raw HTML String and returns a structured OpenGraphData object.
+ *
+ * @param html The raw HTML String to be parsed for Open Graph information.
+ * @return An OpenGraphData object containing all extracted Open Graph data.
+ */
+ fun parse(html: String) : OpenGraphData {
+ val doc = Jsoup.parse(html)
+ return parse(doc)
+ }
+
+ /**
+ * Extracts all Open Graph tags from a raw HTML String and returns a structured OpenGraphData object.
+ *
+ * @param file The file to parse
+ * @param charset The charset to use for parsing (default is UTF-8)
+ * @return An OpenGraphData object containing all extracted Open Graph data.
+ */
+ fun parse(file: File, charset: String = "UTF-8") : OpenGraphData {
+ val doc = Jsoup.parse(file, charset)
+ return parse(doc)
+ }
+
/**
* Extracts Open Graph tags from JSoup Elements and converts them to OpenGraphTag objects.
*
diff --git a/opengraphkt/src/test/kotlin/fr/lengrand/opengraphkt/OpenGraphParserTest.kt b/opengraphkt/src/test/kotlin/fr/lengrand/opengraphkt/OpenGraphParserTest.kt
index c1ee33e..b66c726 100644
--- a/opengraphkt/src/test/kotlin/fr/lengrand/opengraphkt/OpenGraphParserTest.kt
+++ b/opengraphkt/src/test/kotlin/fr/lengrand/opengraphkt/OpenGraphParserTest.kt
@@ -1,6 +1,8 @@
package fr.lengrand.opengraphkt
import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.io.TempDir
+import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
@@ -8,7 +10,6 @@ import kotlin.test.assertTrue
class OpenGraphParserTest {
private val parser = OpenGraphParser()
- private val fetcher = DocumentFetcher()
// Sample HTML with all required OpenGraph tags and some structured properties
private val completeHtml = """
@@ -139,14 +140,13 @@ class OpenGraphParserTest {
@Test
fun `test parse with complete OpenGraph tags`() {
- val document = fetcher.fromString(completeHtml)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(completeHtml)
// Verify that all required properties are extracted correctly
assertEquals("The Rock", openGraphData.title)
assertEquals("video.movie", openGraphData.type)
assertEquals("https://example.com/the-rock", openGraphData.url)
-
+
// Verify that the OpenGraphData object is valid
assertTrue(openGraphData.isValid())
@@ -184,96 +184,116 @@ class OpenGraphParserTest {
@Test
fun `test parse with article-specific tags`() {
- val document = fetcher.fromString(articleHtml)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(articleHtml)
// Verify basic properties
assertEquals("Breaking News", openGraphData.title)
assertEquals("article", openGraphData.type)
assertEquals("https://example.com/news/breaking", openGraphData.url)
assertEquals("Latest breaking news", openGraphData.description)
-
+
// Verify article-specific properties
assertNotNull(openGraphData.article)
- assertEquals("2023-01-01T00:00:00Z", openGraphData.article?.publishedTime)
- assertEquals("2023-01-02T12:00:00Z", openGraphData.article?.modifiedTime)
- assertEquals("News", openGraphData.article?.section)
- assertEquals(2, openGraphData.article?.authors?.size)
- assertTrue(openGraphData.article?.authors?.contains("John Doe") ?: false)
- assertTrue(openGraphData.article?.authors?.contains("Jane Smith") ?: false)
- assertEquals(2, openGraphData.article?.tags?.size)
- assertTrue(openGraphData.article?.tags?.contains("breaking") ?: false)
- assertTrue(openGraphData.article?.tags?.contains("news") ?: false)
+ assertEquals("2023-01-01T00:00:00Z", openGraphData.article.publishedTime)
+ assertEquals("2023-01-02T12:00:00Z", openGraphData.article.modifiedTime)
+ assertEquals("News", openGraphData.article.section)
+ assertEquals(2, openGraphData.article.authors.size)
+ assertTrue(openGraphData.article.authors.contains("John Doe"))
+ assertTrue(openGraphData.article.authors.contains("Jane Smith"))
+ assertEquals(2, openGraphData.article.tags.size)
+ assertTrue(openGraphData.article.tags.contains("breaking"))
+ assertTrue(openGraphData.article.tags.contains("news"))
}
@Test
fun `test parse with profile-specific tags`() {
- val document = fetcher.fromString(profileHtml)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(profileHtml)
// Verify basic properties
assertEquals("John Doe", openGraphData.title)
assertEquals("profile", openGraphData.type)
assertEquals("https://example.com/profile/johndoe", openGraphData.url)
assertEquals("John Doe's profile", openGraphData.description)
-
+
// Verify profile-specific properties
assertNotNull(openGraphData.profile)
- assertEquals("John", openGraphData.profile?.firstName)
- assertEquals("Doe", openGraphData.profile?.lastName)
- assertEquals("johndoe", openGraphData.profile?.username)
- assertEquals("male", openGraphData.profile?.gender)
+ assertEquals("John", openGraphData.profile.firstName)
+ assertEquals("Doe", openGraphData.profile.lastName)
+ assertEquals("johndoe", openGraphData.profile.username)
+ assertEquals("male", openGraphData.profile.gender)
}
@Test
fun `test parse with book-specific tags`() {
- val document = fetcher.fromString(bookHtml)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(bookHtml)
// Verify basic properties
assertEquals("The Great Novel", openGraphData.title)
assertEquals("book", openGraphData.type)
assertEquals("https://example.com/books/great-novel", openGraphData.url)
assertEquals("A great novel", openGraphData.description)
-
+
// Verify book-specific properties
assertNotNull(openGraphData.book)
- assertEquals(1, openGraphData.book?.authors?.size)
- assertEquals("Famous Author", openGraphData.book?.authors?.get(0))
- assertEquals("1234567890123", openGraphData.book?.isbn)
- assertEquals("2023-01-01", openGraphData.book?.releaseDate)
- assertEquals(2, openGraphData.book?.tags?.size)
- assertTrue(openGraphData.book?.tags?.contains("fiction") ?: false)
- assertTrue(openGraphData.book?.tags?.contains("novel") ?: false)
+ assertEquals(1, openGraphData.book.authors.size)
+ assertEquals("Famous Author", openGraphData.book.authors.get(0))
+ assertEquals("1234567890123", openGraphData.book.isbn)
+ assertEquals("2023-01-01", openGraphData.book.releaseDate)
+ assertEquals(2, openGraphData.book.tags.size)
+ assertTrue(openGraphData.book.tags.contains("fiction"))
+ assertTrue(openGraphData.book.tags.contains("novel"))
}
@Test
fun `test parse with multiple images`() {
- val document = fetcher.fromString(multipleImagesHtml)
- val openGraphData = parser.parse(document)
+ val openGraphData = parser.parse(multipleImagesHtml)
// Verify basic properties
assertEquals("Photo Gallery", openGraphData.title)
assertEquals("website", openGraphData.type)
assertEquals("https://example.com/gallery", openGraphData.url)
assertEquals("A gallery of images", openGraphData.description)
-
+
// Verify multiple images
assertEquals(3, openGraphData.images.size)
-
+
// First image
assertEquals("https://example.com/image1.jpg", openGraphData.images[0].url)
assertEquals(800, openGraphData.images[0].width)
assertEquals(600, openGraphData.images[0].height)
-
+
// Second image
assertEquals("https://example.com/image2.jpg", openGraphData.images[1].url)
assertEquals(1024, openGraphData.images[1].width)
assertEquals(768, openGraphData.images[1].height)
-
+
// Third image
assertEquals("https://example.com/image3.jpg", openGraphData.images[2].url)
assertEquals(1200, openGraphData.images[2].width)
assertEquals(900, openGraphData.images[2].height)
}
-}
\ No newline at end of file
+
+ @Test
+ fun `test parse with File`(@TempDir tempDir: File) {
+ // Create a temporary HTML file
+ val htmlFile = File(tempDir, "test.html")
+ htmlFile.writeText(articleHtml)
+
+ val openGraphData = parser.parse(htmlFile)
+
+ // Verify basic properties
+ assertEquals("Breaking News", openGraphData.title)
+ assertEquals("article", openGraphData.type)
+ assertEquals("https://example.com/news/breaking", openGraphData.url)
+ assertEquals("Latest breaking news", openGraphData.description)
+
+ // Verify article-specific properties
+ assertNotNull(openGraphData.article)
+ assertEquals("2023-01-01T00:00:00Z", openGraphData.article.publishedTime)
+ assertEquals("2023-01-02T12:00:00Z", openGraphData.article.modifiedTime)
+ assertEquals("News", openGraphData.article.section)
+ assertEquals(2, openGraphData.article.authors.size)
+ assertTrue(openGraphData.article.authors.contains("John Doe"))
+ assertTrue(openGraphData.article.authors.contains("Jane Smith"))
+ }
+}
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 5867f24..9c6f925 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,6 +1,12 @@
+pluginManagement {
+ plugins {
+ kotlin("jvm") version "2.1.21"
+ }
+}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "OpenGraphKt"
include("opengraphkt")
-include("demo")
\ No newline at end of file
+include("demo")
+include("demo-remote")
\ No newline at end of file