diff --git a/README.md b/README.md
index b8be514..88d690d 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,17 @@ To get the estimated reading time in seconds use the `calcReadingTimeInSec()` fu
- View [Kotlin](https://github.com/ethauvin/readingtime/blob/master/examples/src/main/kotlin/com/example/ReadingTimeExample.kt) or [Java](https://github.com/ethauvin/readingtime/blob/master/examples/src/main/java/com/example/ReadingTimeSample.java) Examples.
+### Gradle, Maven, etc.
+To use with [Gradle](https://gradle.org/), include the following dependency in your [build](https://github.com/ethauvin/readingtime/blob/master/examples/build.gradle.kts) file:
+
+```gradle
+dependencies {
+ implementation("net.thauvin.erik:readingtime:0.9.1")
+}
+```
+
+Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://search.maven.org/artifact/net.thauvin.erik/readingtime/0.9.0/jar).
### Properties
@@ -30,24 +40,26 @@ The following properties are available:
```kotlin
ReadingTime(
- text = "some_text",
+ text,
wpm = 275,
postfix = "min read",
plural = "min read",
excludeImages = false,
- extra = 0
+ extra = 0,
+ round = RoundingMode.HALF_DOWN
)
```
-Property | Description
-:-------------------------- |:-------------------------------------------------------------------
-`text` | The text to be evaluated.
+Property | Description
+:-------------------------- |:-----------------------------------------------------------------------------------------------------------------------
+`text` | The text to be evaluated. (Required)
`wpm` | The words per minute reading average.
`postfix` | The value to be appended to the reading time.
`plural` | The value to be appended if the reading time is more than 1 minute.
`excludeImages` | Images are excluded from the reading time when set.
`extra` | Additional seconds to be added to the total reading time.
+`round` | The [rounding mode](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/math/RoundingMode.html) to apply.
### Functions
@@ -73,15 +85,3 @@ A JSP tag is also available for easy incorporation into web applications:
```
None of the attributes are required.
-
-### Gradle, Maven, etc.
-
-To use with [Gradle](https://gradle.org/), include the following dependency in your [build](https://github.com/ethauvin/readingtime/blob/master/examples/build.gradle.kts) file:
-
-```gradle
-dependencies {
- implementation("net.thauvin.erik:readingtime:0.9.0")
-}
-```
-
-Instructions for using with Maven, Ivy, etc. can be found on [Maven Central](https://search.maven.org/artifact/net.thauvin.erik/readingtime/0.9.0/jar).
diff --git a/build.gradle.kts b/build.gradle.kts
index 50ea9d2..f85863a 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -6,16 +6,16 @@ import java.io.FileInputStream
import java.util.*
plugins {
- id("com.github.ben-manes.versions") version "0.38.0"
+ id("com.github.ben-manes.versions") version "0.39.0"
id("io.gitlab.arturbosch.detekt") version "1.17.1"
+ id("jacoco")
+ id("java")
+ id("java-library")
+ id("maven-publish")
id("org.jetbrains.dokka") version "1.4.32"
- id("org.jetbrains.kotlin.jvm") version "1.5.0"
id("org.sonarqube") version "3.2.0"
- java
- `java-library`
- `maven-publish`
- jacoco
- signing
+ id("signing")
+ kotlin("jvm") version "1.5.10"
}
description = "Estimated Reading Time for Blog Posts, Articles, etc."
@@ -34,12 +34,12 @@ repositories {
}
dependencies {
- implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
+ implementation(platform(kotlin("bom")))
implementation("org.jsoup:jsoup:1.13.1")
- testImplementation("org.jetbrains.kotlin:kotlin-test")
- testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
+ testImplementation(kotlin("test"))
+ testImplementation(kotlin("test-junit"))
}
java {
diff --git a/config/detekt/baseline.xml b/config/detekt/baseline.xml
index 4e17654..2dd4ebc 100644
--- a/config/detekt/baseline.xml
+++ b/config/detekt/baseline.xml
@@ -1,11 +1,11 @@
-
+
+ LongParameterList:ReadingTime.kt$ReadingTime$( text: String, wpm: Int = 275, var postfix: String = "min read", var plural: String = "min read", excludeImages: Boolean = false, extra: Int = 0, var round: RoundingMode = RoundingMode.HALF_DOWN )
MagicNumber:ReadingTime.kt$ReadingTime$10
MagicNumber:ReadingTime.kt$ReadingTime$12
MagicNumber:ReadingTime.kt$ReadingTime$3
- MagicNumber:ReadingTime.kt$ReadingTime$60
MagicNumber:ReadingTime.kt$ReadingTime$60.0
diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts
index 94f1e9f..5ea0c36 100644
--- a/examples/build.gradle.kts
+++ b/examples/build.gradle.kts
@@ -1,7 +1,7 @@
plugins {
- id("org.jetbrains.kotlin.jvm") version "1.5.0"
- id("com.github.ben-manes.versions") version "0.38.0"
- application
+ id("application")
+ id("com.github.ben-manes.versions") version "0.39.0"
+ kotlin("jvm") version "1.5.10"
}
// ./gradlew run
diff --git a/pom.xml b/pom.xml
index 080401e..c3ec90c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,7 +40,7 @@
org.jetbrains.kotlin
kotlin-bom
- 1.5.0
+ 1.5.10
pom
import
@@ -50,7 +50,7 @@
org.jetbrains.kotlin
kotlin-stdlib-jdk8
- 1.5.0
+ 1.5.10
compile
diff --git a/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt b/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt
index f662f11..6934023 100644
--- a/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt
+++ b/src/main/kotlin/net/thauvin/erik/readingtime/ReadingTime.kt
@@ -49,6 +49,7 @@ import java.math.RoundingMode
* @param plural The value to be appended if the reading time is more than 1 minute.
* @param excludeImages Images are excluded from the reading time when set.
* @param extra Additional seconds to be added to the total reading time.
+ * @param round The [RoundingMode] to apply. Default is [RoundingMode.HALF_DOWN].
*/
class ReadingTime @JvmOverloads constructor(
text: String,
@@ -56,7 +57,8 @@ class ReadingTime @JvmOverloads constructor(
var postfix: String = "min read",
var plural: String = "min read",
excludeImages: Boolean = false,
- extra: Int = 0
+ extra: Int = 0,
+ var round: RoundingMode = RoundingMode.HALF_DOWN
) {
companion object {
private const val INVALID: Double = -1.0
@@ -108,7 +110,9 @@ class ReadingTime @JvmOverloads constructor(
}
/**
- * Calculates and returns the reading time in seconds.
+ * Calculates and returns the reading time in seconds.
+ *
+ * `((word count / wpm) * 60) + images + extra`
*/
fun calcReadingTimeInSec(): Double {
if (readTime == INVALID) {
@@ -121,9 +125,11 @@ class ReadingTime @JvmOverloads constructor(
/**
* Calculates and returns the reading time. (eg. 1 min read)
+ *
+ * `(reading time in sec / 60) + postfix`
*/
fun calcReadingTime(): String {
- val time = BigDecimal((calcReadingTimeInSec() / 60.0)).setScale(0, RoundingMode.HALF_DOWN)
+ val time = BigDecimal((calcReadingTimeInSec() / 60.0)).setScale(0, round)
return if (time.compareTo(BigDecimal.ONE) == 1) {
"$time $plural".trim()
} else {
@@ -131,6 +137,10 @@ class ReadingTime @JvmOverloads constructor(
}
}
+ /**
+ * 12 seconds for the first image, 11 for the second, and minus an additional second for each subsequent image.
+ * Any images after the tenth image are counted at 3 seconds.
+ */
private fun calcImgReadingTime(): Int {
var time = 0
val imgCount = imgCount(text)
diff --git a/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt b/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt
index dd26929..3a2b334 100644
--- a/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt
+++ b/src/test/kotlin/net/thauvin/erik/readingtime/ReadingTimeTest.kt
@@ -33,28 +33,16 @@
package net.thauvin.erik.readingtime
import java.io.File
+import java.math.RoundingMode
import kotlin.test.Test
import kotlin.test.assertEquals
class ReadingTimeTest {
- private val rt = ReadingTime("This is a test.\nWith an image:
")
+ private val img = """
"""
+ private val rt = ReadingTime("This is a test.\nWith an image: $img")
private val blogPost = File("src/test/resources/post.html").readText()
private val mediumPost = File("src/test/resources/medium.html").readText()
- private val twoSeventyFive = """one two three four five six seven eight nine ten one two three four five six seven
-eight nine ten one two three four five six seven eight nine ten one two three four five six seven eight nine
-ten one two three four five six seven eight nine ten one two three four five six seven eight nine ten one two
-three four five six seven eight nine ten one two three four five six seven eight nine ten one two three four
-five six seven eight nine ten one two three four five six seven eight nine ten one two three four five six
-seven eight nine ten one two three four five six seven eight nine ten one two three four five six seven eight
-nine ten one two three four five six seven eight nine ten one two three four five six seven eight nine ten
-one two three four five six seven eight nine ten one two three four five six seven eight nine ten one two
-three four five six seven eight nine ten one two three four five six seven eight nine ten one two three four
-five six seven eight nine ten one two three four five six seven eight nine ten one two three four five six
-seven eight nine ten one two three four five six seven eight nine ten one two three four five six seven eight
-nine ten one two three four five six seven eight nine ten one two three four five six seven eight nine ten
-one two three four five six seven eight nine ten one two three four five"""
- private val tenImages = "
" +
- "
"
+ private val twoSeventyFive = "word ".repeat(275)
private fun calcImgTime(imgCount: Int): Double {
var time = 0.0
@@ -75,100 +63,111 @@ one two three four five six seven eight nine ten one two three four five"""
@Test
fun testWordCount() {
- assertEquals(0, ReadingTime.wordCount(" "))
- assertEquals(3, ReadingTime.wordCount("one two three"))
- assertEquals(2, ReadingTime.wordCount(" one two "))
- assertEquals(7, ReadingTime.wordCount(rt.text))
- assertEquals(505, ReadingTime.wordCount(blogPost))
- assertEquals(391, ReadingTime.wordCount(mediumPost))
- assertEquals(275, ReadingTime.wordCount(twoSeventyFive))
- assertEquals(275, ReadingTime.wordCount("$twoSeventyFive
"))
+ assertEquals(1, ReadingTime.imgCount(rt.text), "text")
+ assertEquals(11, ReadingTime.imgCount(blogPost), "blogPost")
+ assertEquals(3, ReadingTime.imgCount(mediumPost), "mediumPost")
+ assertEquals(1, ReadingTime.imgCount("$twoSeventyFive $img"), "275 + image")
+ assertEquals(2, ReadingTime.imgCount("$twoSeventyFive $img $img"), "275 + 2 images")
}
@Test
fun testReadingTimeInSec() {
- assertEquals(calcReadingTime(rt.text, rt.wpm) + calcImgTime(1), rt.calcReadingTimeInSec())
+ assertEquals(calcReadingTime(rt.text, rt.wpm) + calcImgTime(1), rt.calcReadingTimeInSec(), "text + image")
- rt.text = "
"
- assertEquals(calcImgTime(2), rt.calcReadingTimeInSec())
+ rt.text = "$img ${img.uppercase()}"
+ assertEquals(calcImgTime(2), rt.calcReadingTimeInSec(), "2 images")
rt.excludeImages = true
- assertEquals(0.0, rt.calcReadingTimeInSec())
+ assertEquals(0.0, rt.calcReadingTimeInSec(), "image uppercase")
rt.excludeImages = false
rt.text = blogPost
assertEquals(
- calcReadingTime(rt.text, rt.wpm) + calcImgTime(11), rt.calcReadingTimeInSec()
+ calcReadingTime(rt.text, rt.wpm) + calcImgTime(11), rt.calcReadingTimeInSec(), "blogPost"
)
rt.excludeImages = true
- assertEquals(calcReadingTime(rt.text, rt.wpm), rt.calcReadingTimeInSec())
+ assertEquals(calcReadingTime(rt.text, rt.wpm), rt.calcReadingTimeInSec(), "exclude images")
rt.extra = 60
- assertEquals(calcReadingTime(rt.text, rt.wpm) + 60L, rt.calcReadingTimeInSec())
+ assertEquals(calcReadingTime(rt.text, rt.wpm) + 60L, rt.calcReadingTimeInSec(), "extra 60")
rt.extra = 0
rt.excludeImages = false
rt.text = mediumPost
rt.wpm = 300
- assertEquals(calcReadingTime(rt.text, 300) + calcImgTime(3), rt.calcReadingTimeInSec())
+ assertEquals(calcReadingTime(rt.text, 300) + calcImgTime(3), rt.calcReadingTimeInSec(), "mediumPost 300 wpm")
rt.wpm = 275
rt.text = "This is a test"
- assertEquals(0.0, rt.calcReadingTimeInSec())
+ assertEquals(0.0, rt.calcReadingTimeInSec(), "test")
rt.text = twoSeventyFive
- assertEquals(60.0, rt.calcReadingTimeInSec())
+ assertEquals(60.0, rt.calcReadingTimeInSec(), "275")
- rt.text = "$twoSeventyFive
"
- assertEquals(72.0, rt.calcReadingTimeInSec())
+ rt.text = "$twoSeventyFive $img"
+ assertEquals(72.0, rt.calcReadingTimeInSec(), "275 + image")
- rt.text = "$twoSeventyFive
"
- assertEquals(83.0, rt.calcReadingTimeInSec())
+ rt.text = "$twoSeventyFive $img $img"
+ assertEquals(83.0, rt.calcReadingTimeInSec(), "275 + 2 images")
- rt.text = "$twoSeventyFive $tenImages"
- assertEquals(60.0 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3, rt.calcReadingTimeInSec())
+ rt.text = "$twoSeventyFive ${img.repeat(10)}"
+ assertEquals(60.0 + 12 + 11 + 10 + 9 + 8 + 7 + 6 + 5 + 4 + 3, rt.calcReadingTimeInSec(), "10 images")
- rt.text = "$twoSeventyFive $tenImages
"
- assertEquals(135.0 + 3, rt.calcReadingTimeInSec())
+ rt.text = "$twoSeventyFive ${img.repeat(10)} $img"
+ assertEquals(135.0 + 3, rt.calcReadingTimeInSec(), "11 images")
rt.text = "$twoSeventyFive $twoSeventyFive"
- assertEquals(120.0, rt.calcReadingTimeInSec())
+ assertEquals(120.0, rt.calcReadingTimeInSec(), "275*2")
rt.text = ""
- assertEquals(0.0, rt.calcReadingTimeInSec())
+ assertEquals(0.0, rt.calcReadingTimeInSec(), "empty")
}
@Test
fun testReadingTime() {
rt.text = blogPost
- assertEquals("2 min read", rt.calcReadingTime())
+ assertEquals("2 min read", rt.calcReadingTime(), "blogPost")
rt.plural = "mins read"
- assertEquals("2 mins read", rt.calcReadingTime())
+ assertEquals("2 mins read", rt.calcReadingTime(), "plural")
rt.text = mediumPost
rt.plural = ""
- assertEquals("2", rt.calcReadingTime())
+ assertEquals("2", rt.calcReadingTime(), "mediumPost")
rt.text = "This is a test."
rt.postfix = ""
- assertEquals("0", rt.calcReadingTime())
+ assertEquals("0", rt.calcReadingTime(), "test")
rt.text = ""
- assertEquals("0", rt.calcReadingTime())
+ assertEquals("0", rt.calcReadingTime(), "empty")
rt.text = twoSeventyFive
- assertEquals("1", rt.calcReadingTime())
+ assertEquals("1", rt.calcReadingTime(), "275")
rt.text = "$twoSeventyFive $twoSeventyFive"
- assertEquals("2", rt.calcReadingTime())
+ assertEquals("2", rt.calcReadingTime(), "275 * 2")
+ }
+
+ @Test
+ fun testRoundingMode() {
+ rt.text = blogPost
+ rt.round = RoundingMode.UP
+ assertEquals("3 min read", rt.calcReadingTime(), "UP")
+
+ rt.text = mediumPost
+ rt.round = RoundingMode.DOWN
+ assertEquals("1 min read", rt.calcReadingTime(), "DOWN")
}
}