Merge pull request #1783 from vitorpamplona/claude/improve-urldetector-readability-lqyci

refactor: improve URLDetector readability
This commit is contained in:
Vitor Pamplona
2026-03-08 09:57:56 -04:00
committed by GitHub
2 changed files with 21 additions and 27 deletions
@@ -30,6 +30,17 @@ import com.vitorpamplona.quartz.utils.urldetector.detection.CharUtils.splitByDot
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
/** Returns true if the string is a percent-encoded dot (%2e or %2E). */
private fun String.isDotPercent() = this == "%2e" || this == "%2E"
/** Returns true if the string is an internationalized domain label using Punycode (xn-- prefix). */
private fun String.isXn() =
this.length > 3 &&
(this[0] == 'x' || this[0] == 'X') &&
(this[1] == 'n' || this[1] == 'N') &&
this[2] == '-' &&
this[3] == '-'
/** /**
* The domain name reader reads input from a InputTextReader and validates if the content being read is a valid domain name. * The domain name reader reads input from a InputTextReader and validates if the content being read is a valid domain name.
* After a domain name is read, the returning status is what to do next. If the domain is valid but a specific character is found, * After a domain name is read, the returning status is what to do next. If the domain is valid but a specific character is found,
@@ -134,7 +145,6 @@ class DomainNameReader(
var isIpV6 = false var isIpV6 = false
private set private set
fun String.isDotPercent() = this == "%2e" || this == "%2E"
/** /**
* Reads and parses the current string to make sure the domain name started where it was supposed to, * Reads and parses the current string to make sure the domain name started where it was supposed to,
@@ -424,13 +434,6 @@ class DomainNameReader(
return checkDomainNameValid(ReaderNextState.ValidDomainName, null) return checkDomainNameValid(ReaderNextState.ValidDomainName, null)
} }
fun String.isXn() =
this.length > 3 &&
(this[0] == 'x' || this[0] == 'X') &&
(this[1] == 'n' || this[1] == 'N') &&
this[2] == '-' &&
this[3] == '-'
fun labelCount() = dots + (if (currentLabelLength > 0) 1 else 0) fun labelCount() = dots + (if (currentLabelLength > 0) 1 else 0)
/** /**
@@ -700,7 +703,7 @@ class DomainNameReader(
hexSection = true // reset hex to true hexSection = true // reset hex to true
hexDigits = 0 // reset count for hex digits hexDigits = 0 // reset count for hex digits
numSections++ numSections++
lastSection.deleteRange(0, lastSection.length) // clear last section lastSection.clear() // clear last section
} }
else -> { else -> {
@@ -52,7 +52,7 @@ class UrlDetector(
/** /**
* Stores the found urls. * Stores the found urls.
*/ */
private val urlList: ArrayList<Url> = ArrayList<Url>() private val urlList = mutableListOf<Url>()
/** /**
* Keeps track of certain indices to create a Url object. * Keeps track of certain indices to create a Url object.
@@ -89,18 +89,12 @@ class UrlDetector(
// read the next char to process. // read the next char to process.
when (val curr = reader.read()) { when (val curr = reader.read()) {
' ' -> { ' ' -> {
// space was found, check if it's a valid single level domain. // space found; if we have a scheme, attempt to read the domain before resetting
if (buffer.isNotEmpty() && hasScheme) { if (buffer.isNotEmpty() && hasScheme) {
reader.goBack() reader.goBack()
val domain = buffer.substring(length) readDomainName(buffer.substring(length))
if (!readDomainName(domain)) {
readEnd(ReadEndState.InvalidUrl)
} else {
readEnd(ReadEndState.InvalidUrl)
}
} else {
readEnd(ReadEndState.InvalidUrl)
} }
readEnd(ReadEndState.InvalidUrl)
length = 0 length = 0
} }
@@ -220,8 +214,8 @@ class UrlDetector(
* @param length first index of the previous part (could be beginning of the buffer, beginning of the username/password, or beginning * @param length first index of the previous part (could be beginning of the buffer, beginning of the username/password, or beginning
* @return new index of where the domain starts * @return new index of where the domain starts
*/ */
private fun processColon(length: Int): Int { private fun processColon(startLength: Int): Int {
var length = length var length = startLength
if (hasScheme) { if (hasScheme) {
// read it as username/password if it has scheme // read it as username/password if it has scheme
if (!readUserPass(length)) { if (!readUserPass(length)) {
@@ -648,12 +642,9 @@ class UrlDetector(
private fun readEnd(state: ReadEndState?): Boolean { private fun readEnd(state: ReadEndState?): Boolean {
// if the url is valid and greater then 0 // if the url is valid and greater then 0
if (state == ReadEndState.ValidUrl && buffer.isNotEmpty()) { if (state == ReadEndState.ValidUrl && buffer.isNotEmpty()) {
// Add the url to the list of good urls. var url = buffer.toString()
if (buffer.isNotEmpty()) { if (url.lastOrNull() in CANNOT_END_URLS_WITH) url = url.dropLast(1)
var url = buffer.toString() urlList.add(currentUrlMarker.createUrl(url))
if (url.lastOrNull() in CANNOT_END_URLS_WITH) url = url.dropLast(1)
urlList.add(currentUrlMarker.createUrl(url))
}
} }
// clear out the buffer. // clear out the buffer.