package org.terst.feedreader.readability
/**
* Removes "recirculation" widgets -- the promo blocks a publisher's widget platform injects
* into the middle of the article body to send the reader off to other stories.
*
* Reported live: West Hawaii Today articles "get a bunch of stray 'Trending' headers".
* Confirmed by running the vendored Readability.js over the rendered page for the 12 articles
* in that feed: 9 carried two surviving widgets each. The three that didn't were paywalled
* stubs too short for the widgets to be reached.
*
* Readability keeps them because they are not in a sidebar -- they are inside the article's own
* container, between real paragraphs, so every structural signal says they belong. What arrives
* is a heading labelling nothing, because the list of links under it is filled in later by a
* script that never runs in the reader:
*
* ```
*
]*>", RegexOption.IGNORE_CASE)
private val TAG_REGEX = Regex("<[^>]*>")
private val WHITESPACE_REGEX = Regex("\\s+")
private const val OPEN_DIV = "
` closing the div that opened before [from], or null when
* the markup never closes it.
*/
private fun matchingClose(html: String, from: Int): Int? {
var depth = 1
var i = from
var end: Int? = null
while (end == null && i < html.length) {
val next = html.indexOf('<', i)
when {
next < 0 -> i = html.length
html.startsWith(CLOSE_DIV, next, ignoreCase = true) -> {
val close = html.indexOf('>', next)
depth--
when {
close < 0 -> i = html.length
depth == 0 -> end = close + 1
else -> i = close + 1
}
}
html.startsWith(OPEN_DIV, next, ignoreCase = true) -> {
depth++
i = next + OPEN_DIV.length
}
else -> i = next + 1
}
}
return end
}
private fun tooLongToBeAWidget(block: String): Boolean =
block.replace(TAG_REGEX, " ").replace(WHITESPACE_REGEX, " ").trim().length > MAX_WIDGET_TEXT_LENGTH
}