Merge remote-tracking branch 'origin/master'

This commit is contained in:
kunfei
2023-03-11 22:40:22 +08:00
12 changed files with 107 additions and 701 deletions
@@ -142,99 +142,111 @@ class EpubFile(var book: Book) {
return "<img src=\"cover.jpeg\" />"
}
/*获取当前章节文本*/
epubBook?.let { epubBook ->
val nextChapterFirstResourceHref = chapter.getVariable("nextUrl")?.substringBeforeLast("#")
val currentChapterFirstResourceHref = chapter.url.substringBeforeLast("#")
val isLastChapter = nextChapterFirstResourceHref.isNullOrBlank()
val startFragmentId = chapter.startFragmentId
val endFragmentId = chapter.endFragmentId
val elements = Elements()
var findChapterFirstSource = false
val includeNextChapterResource = !endFragmentId.isNullOrBlank()
/*一些书籍依靠href索引的resource会包含多个章节,需要依靠fragmentId来截取到当前章节的内容*/
/*注:这里较大增加了内容加载的时间,所以首次获取内容后可存储到本地cache,减少重复加载*/
val contents = epubBookContents ?: return null
for (res in contents) {
if (!findChapterFirstSource) {
if (currentChapterFirstResourceHref != res.href) continue
findChapterFirstSource = true
// 第一个xhtml文件
elements.add(
getBody(res, startFragmentId, endFragmentId)
)
// 不是最后章节 且 已经遍历到下一章节的内容时停止
if (!isLastChapter && res.href == nextChapterFirstResourceHref) break
continue
}
if (nextChapterFirstResourceHref != res.href) {
// 其余部分
elements.add(getBody(res, null, null))
} else {
// 下一章节的第一个xhtml
if (includeNextChapterResource) {
//有Fragment 则添加到上一章节
elements.add(getBody(res, null, endFragmentId))
}
break
}
val contents = epubBookContents ?: return null
val nextChapterFirstResourceHref = chapter.getVariable("nextUrl")?.substringBeforeLast("#")
val currentChapterFirstResourceHref = chapter.url.substringBeforeLast("#")
val isLastChapter = nextChapterFirstResourceHref.isNullOrBlank()
val startFragmentId = chapter.startFragmentId
val endFragmentId = chapter.endFragmentId
val elements = Elements()
var findChapterFirstSource = false
val includeNextChapterResource = !endFragmentId.isNullOrBlank()
/*一些书籍依靠href索引的resource会包含多个章节,需要依靠fragmentId来截取到当前章节的内容*/
/*注:这里较大增加了内容加载的时间,所以首次获取内容后可存储到本地cache,减少重复加载*/
for (res in contents) {
if (!findChapterFirstSource) {
if (currentChapterFirstResourceHref != res.href) continue
findChapterFirstSource = true
// 第一个xhtml文件
elements.add(
getBody(res, startFragmentId, endFragmentId)
)
// 不是最后章节 且 已经遍历到下一章节的内容时停止
if (!isLastChapter && res.href == nextChapterFirstResourceHref) break
continue
}
//title标签中的内容不需要显示在正文中,去除
elements.select("title").remove()
elements.select("img").forEach {
val src = it.attr("src")
val path = chapter.url.substringBeforeLast("/", "")
val absSrc = if (path.isEmpty()) {
src
} else {
StringUtil.collapsePathDots("$path/$src")
if (nextChapterFirstResourceHref != res.href) {
// 其余部分
elements.add(getBody(res, null, null))
} else {
// 下一章节的第一个xhtml
if (includeNextChapterResource) {
//有Fragment 则添加到上一章节
elements.add(getBody(res, null, endFragmentId))
}
it.attr("src", absSrc)
break
}
var html = elements.outerHtml()
val tag = Book.rubyTag
if (book.getDelTag(tag)) {
html = html.replace("<ruby>\\s?([\\u4e00-\\u9fa5])\\s?.*?</ruby>".toRegex(), "$1")
}
return HtmlFormatter.formatKeepImg(html)
}
return null
//title标签中的内容不需要显示在正文中,去除
elements.select("title").remove()
elements.select("img").forEach {
val src = it.attr("src")
val path = chapter.url.substringBeforeLast("/", "")
val absSrc = if (path.isEmpty()) {
src
} else {
StringUtil.collapsePathDots("$path/$src")
}
it.attr("src", absSrc)
}
var html = elements.outerHtml()
val tag = Book.rubyTag
if (book.getDelTag(tag)) {
html = html.replace("<ruby>\\s?([\\u4e00-\\u9fa5])\\s?.*?</ruby>".toRegex(), "$1")
}
return HtmlFormatter.formatKeepImg(html)
}
private fun getBody(res: Resource, startFragmentId: String?, endFragmentId: String?): Element {
val originHtml = String(res.data, mCharset)
var html = originHtml
var doc = Jsoup.parse(html)
var body = doc.body()
// Jsoup可能会修复不规范的xhtml文件 解析处理后再获取
var bodyElement = Jsoup.parse(String(res.data, mCharset)).body()
bodyElement.children().run {
select("script").remove()
select("style").remove()
}
// 获取body对应的文本
var bodyString = bodyElement.outerHtml()
val originBodyString = bodyString
/**
* 某些xhtml文件 章节标题和内容不在一个节点或者不是兄弟节点
* <div>
* <a class="mulu1>目录1</a>
* </div>
* <p>....</p>
* <div>
* <a class="mulu2>目录2</a>
* </div>
* <p>....</p>
* 先找到FragmentId对应的Element 然后直接截取之间的html
*/
if (!startFragmentId.isNullOrBlank()) {
body.getElementById(startFragmentId)?.outerHtml()?.let {
html = html.substringAfter(it)
bodyElement.getElementById(startFragmentId)?.outerHtml()?.let {
bodyString = bodyString.substringAfter(it)
}
}
if (!endFragmentId.isNullOrBlank() && endFragmentId != startFragmentId) {
body.getElementById(endFragmentId)?.outerHtml()?.let {
html = html.substringBefore(it)
bodyElement.getElementById(endFragmentId)?.outerHtml()?.let {
bodyString = bodyString.substringBefore(it)
}
}
if (html != originHtml) {
doc = Jsoup.parse(html)
body = doc.body()
//截取过再重新解析
if (bodyString != originBodyString) {
bodyElement = Jsoup.parse(bodyString).body()
}
/*选择去除正文中的H标签,部分书籍标题与阅读标题重复待优化*/
val tag = Book.hTag
if (book.getDelTag(tag)) {
body.getElementsByTag("h1").remove()
body.getElementsByTag("h2").remove()
body.getElementsByTag("h3").remove()
body.getElementsByTag("h4").remove()
body.getElementsByTag("h5").remove()
body.getElementsByTag("h6").remove()
//body.getElementsMatchingOwnText(chapter.title)?.remove()
bodyElement.run {
getElementsByTag("h1").remove()
getElementsByTag("h2").remove()
getElementsByTag("h3").remove()
getElementsByTag("h4").remove()
getElementsByTag("h5").remove()
getElementsByTag("h6").remove()
//getElementsMatchingOwnText(chapter.title)?.remove()
}
}
val children = body.children()
children.select("script").remove()
children.select("style").remove()
return doc.body()
return bodyElement
}
private fun getImage(href: String): InputStream? {
@@ -117,6 +117,7 @@ class BookInfoActivity :
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.book_info, menu)
menu.findItem(R.id.menu_edit)?.isVisible = viewModel.inBookshelf
return super.onCompatCreateOptionsMenu(menu)
}
@@ -137,23 +138,21 @@ class BookInfoActivity :
viewModel.bookData.value?.isLocalTxt ?: false
menu.findItem(R.id.menu_upload)?.isVisible =
viewModel.bookData.value?.isLocal ?: false
menu.findItem(R.id.menu_edit)?.isVisible =
!(viewModel.bookData.value?.isWebFile ?: true)
return super.onMenuOpened(featureId, menu)
}
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_edit -> {
if (viewModel.inBookshelf) {
// if (viewModel.inBookshelf) {
viewModel.bookData.value?.let {
infoEditResult.launch {
putExtra("bookUrl", it.bookUrl)
}
}
} else {
toastOnUi(R.string.after_add_bookshelf)
}
// } else {
// toastOnUi(R.string.after_add_bookshelf)
//}
}
R.id.menu_share_it -> {
viewModel.bookData.value?.let {