mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-16 07:10:29 +05:30
104 lines
3.6 KiB
Kotlin
104 lines
3.6 KiB
Kotlin
|
package com.github.libretube.util
|
||
|
|
||
|
import android.text.Editable
|
||
|
import android.text.Html
|
||
|
import android.text.Spanned
|
||
|
import androidx.core.text.HtmlCompat
|
||
|
import org.xml.sax.*
|
||
|
import java.util.*
|
||
|
|
||
|
class HtmlParser private constructor(private val handler: TagHandler) : Html.TagHandler, ContentHandler {
|
||
|
private val tagStatus = ArrayDeque<Boolean>()
|
||
|
private var wrapped: ContentHandler? = null
|
||
|
private var text: Editable? = null
|
||
|
override fun handleTag(opening: Boolean, tag: String, output: Editable, xmlReader: XMLReader) {
|
||
|
if (wrapped == null) {
|
||
|
// record result object
|
||
|
text = output
|
||
|
|
||
|
// record current content handler
|
||
|
wrapped = xmlReader.contentHandler
|
||
|
|
||
|
// replace content handler with our own that forwards to calls to original when needed
|
||
|
xmlReader.contentHandler = this
|
||
|
|
||
|
// handle endElement() callback for <inject/> tag
|
||
|
tagStatus.addLast(java.lang.Boolean.FALSE)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun startElement(uri: String, localName: String, qName: String, attributes: Attributes) {
|
||
|
val isHandled = handler.handleTag(true, localName, text, attributes)
|
||
|
tagStatus.addLast(isHandled)
|
||
|
if (!isHandled) {
|
||
|
wrapped?.startElement(uri, localName, qName, attributes)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun endElement(uri: String, localName: String, qName: String) {
|
||
|
if (!tagStatus.removeLast()) {
|
||
|
wrapped?.endElement(uri, localName, qName)
|
||
|
}
|
||
|
handler.handleTag(false, localName, text, null)
|
||
|
}
|
||
|
|
||
|
override fun setDocumentLocator(locator: Locator) {
|
||
|
wrapped?.setDocumentLocator(locator)
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun startDocument() {
|
||
|
wrapped?.startDocument()
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun endDocument() {
|
||
|
wrapped?.endDocument()
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun startPrefixMapping(prefix: String, uri: String) {
|
||
|
wrapped?.startPrefixMapping(prefix, uri)
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun endPrefixMapping(prefix: String) {
|
||
|
wrapped?.endPrefixMapping(prefix)
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun characters(ch: CharArray, start: Int, length: Int) {
|
||
|
wrapped?.characters(ch, start, length)
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun ignorableWhitespace(ch: CharArray, start: Int, length: Int) {
|
||
|
wrapped?.ignorableWhitespace(ch, start, length)
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun processingInstruction(target: String, data: String) {
|
||
|
wrapped?.processingInstruction(target, data)
|
||
|
}
|
||
|
|
||
|
@Throws(SAXException::class) override fun skippedEntity(name: String) {
|
||
|
wrapped?.skippedEntity(name)
|
||
|
}
|
||
|
|
||
|
interface TagHandler {
|
||
|
fun handleTag(opening: Boolean, tag: String?, output: Editable?, attributes: Attributes?): Boolean
|
||
|
}
|
||
|
|
||
|
companion object {
|
||
|
fun createSpannedText(html: String, handler: TagHandler): Spanned {
|
||
|
// add a tag at the start that is not handled by default,
|
||
|
// allowing custom tag handler to replace xmlReader contentHandler
|
||
|
return HtmlCompat.fromHtml(html, HtmlCompat.FROM_HTML_MODE_LEGACY, null, HtmlParser(handler))
|
||
|
}
|
||
|
|
||
|
@JvmStatic fun getValue(attributes: Attributes, name: String): String? {
|
||
|
var i = 0
|
||
|
val n = attributes.length
|
||
|
while (i < n) {
|
||
|
if (name.equals(attributes.getLocalName(i), ignoreCase = true)) {
|
||
|
return attributes.getValue(i)
|
||
|
}
|
||
|
i++
|
||
|
}
|
||
|
return null
|
||
|
}
|
||
|
}
|
||
|
}
|