parent
d9f7e53338
commit
41789f5bc5
@ -0,0 +1,69 @@ |
|||||||
|
package io.legado.app.utils |
||||||
|
|
||||||
|
import org.jsoup.internal.StringUtil |
||||||
|
import org.jsoup.nodes.CDataNode |
||||||
|
import org.jsoup.nodes.Element |
||||||
|
import org.jsoup.nodes.Node |
||||||
|
import org.jsoup.nodes.TextNode |
||||||
|
import org.jsoup.select.NodeTraversor |
||||||
|
import org.jsoup.select.NodeVisitor |
||||||
|
|
||||||
|
|
||||||
|
fun Element.textArray(): Array<String> { |
||||||
|
val accum = StringUtil.borrowBuilder() |
||||||
|
NodeTraversor.traverse(object : NodeVisitor { |
||||||
|
override fun head(node: Node, depth: Int) { |
||||||
|
if (node is TextNode) { |
||||||
|
appendNormalisedText(accum, node) |
||||||
|
} else if (node is Element) { |
||||||
|
if (accum.isNotEmpty() && |
||||||
|
(node.isBlock || node.tag().name == "br") && |
||||||
|
!lastCharIsWhitespace(accum) |
||||||
|
) accum.append("\n") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun tail(node: Node, depth: Int) { |
||||||
|
// make sure there is a space between block tags and immediately following text nodes <div>One</div>Two should be "One Two". |
||||||
|
if (node is Element) { |
||||||
|
if (node.isBlock && node.nextSibling() is TextNode && !lastCharIsWhitespace( |
||||||
|
accum |
||||||
|
) |
||||||
|
) accum.append("\n") |
||||||
|
} |
||||||
|
} |
||||||
|
}, this) |
||||||
|
val text = StringUtil.releaseBuilder(accum).trim { it <= ' ' } |
||||||
|
return text.splitNotBlank("\n") |
||||||
|
} |
||||||
|
|
||||||
|
private fun appendNormalisedText( |
||||||
|
accum: StringBuilder, |
||||||
|
textNode: TextNode |
||||||
|
) { |
||||||
|
val text = textNode.wholeText |
||||||
|
if (preserveWhitespace(textNode.parentNode()) || textNode is CDataNode) accum.append(text) else StringUtil.appendNormalisedWhitespace( |
||||||
|
accum, |
||||||
|
text, |
||||||
|
lastCharIsWhitespace(accum) |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
private fun preserveWhitespace(node: Node?): Boolean { |
||||||
|
// looks only at this element and five levels up, to prevent recursion & needless stack searches |
||||||
|
if (node is Element) { |
||||||
|
var el = node as Element? |
||||||
|
var i = 0 |
||||||
|
do { |
||||||
|
if (el!!.tag().preserveWhitespace()) return true |
||||||
|
el = el.parent() |
||||||
|
i++ |
||||||
|
} while (i < 6 && el != null) |
||||||
|
} |
||||||
|
return false |
||||||
|
} |
||||||
|
|
||||||
|
private fun lastCharIsWhitespace(sb: java.lang.StringBuilder): Boolean { |
||||||
|
return sb.isNotEmpty() && sb[sb.length - 1] == ' ' |
||||||
|
} |
||||||
|
|
Loading…
Reference in new issue