diff --git a/app/src/main/java/io/legado/app/data/entities/BookChapter.kt b/app/src/main/java/io/legado/app/data/entities/BookChapter.kt index e42f9795c..0fc72569a 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookChapter.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookChapter.kt @@ -5,6 +5,7 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Ignore import androidx.room.Index +import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.utils.GSON import io.legado.app.utils.MD5Utils import io.legado.app.utils.NetworkUtils @@ -61,12 +62,11 @@ data class BookChapter( return false } - fun getAbsoluteURL(): String { - val urlBefore = url.substringBefore(',') - val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl, urlBefore) - return if (urlBefore.length == url.length) urlAbsoluteBefore else urlAbsoluteBefore + url.substring( - urlBefore.length - ) + fun getAbsoluteURL():String{ + val urlMatcher = AnalyzeUrl.paramPattern.matcher(url) + val urlBefore = if(urlMatcher.find())url.substring(0,urlMatcher.start()) else url + val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl,urlBefore) + return if(urlBefore.length == url.length) urlAbsoluteBefore else urlAbsoluteBefore + ',' + url.substring(urlMatcher.end()) } fun getFileName(): String = String.format("%05d-%s.nb", index, MD5Utils.md5Encode16(title)) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index 52eade600..b959987b3 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -65,7 +65,8 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions { fun setRedirectUrl(url: String): URL? { kotlin.runCatching { - redirectUrl = URL(url.substringBefore(',')) + val urlMatcher = AnalyzeUrl.paramPattern.matcher(url) + redirectUrl = URL( if(urlMatcher.find())url.substring(0,urlMatcher.start()) else url) } return redirectUrl } diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index 78a1fd56d..6e9807aad 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -39,6 +39,7 @@ class AnalyzeUrl( headerMapF: Map? = null ) : JsExtensions { companion object { + val paramPattern = Pattern.compile("\\s*,\\s*(?=\\{)") private val pagePattern = Pattern.compile("<(.*?)>") } @@ -55,7 +56,8 @@ class AnalyzeUrl( private var retry: Int = 0 init { - baseUrl = baseUrl.substringBefore(',') + val urlMatcher = paramPattern.matcher(baseUrl) + if(urlMatcher.find())baseUrl = baseUrl.substring(0,urlMatcher.start()) headerMapF?.let { headerMap.putAll(it) if (it.containsKey("proxy")) { @@ -141,17 +143,14 @@ class AnalyzeUrl( * 处理URL */ private fun initUrl() { //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。 - - urlHasQuery = ruleUrl.substringBefore(',') - url = NetworkUtils.getAbsoluteURL(baseUrl, urlHasQuery) + val urlMatcher = paramPattern.matcher(ruleUrl) + urlHasQuery = if(urlMatcher.find())ruleUrl.substring(0,urlMatcher.start()) else ruleUrl + url = NetworkUtils.getAbsoluteURL(baseUrl,urlHasQuery ) NetworkUtils.getBaseUrl(url)?.let { baseUrl = it } - - if (urlHasQuery.length != ruleUrl.length) { - GSON.fromJsonObject( - ruleUrl.substring(urlHasQuery.length + 1).trim { it < '!' })?.let { option -> - + if(urlHasQuery.length != ruleUrl.length ) { + GSON.fromJsonObject(ruleUrl.substring(urlMatcher.end()))?.let { option -> option.method?.let { if (it.equals("POST", true)) method = RequestMethod.POST } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt index 2672849d2..740f36c6f 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt @@ -146,7 +146,7 @@ object ChapterProvider { return TextChapter( bookChapter.index, bookChapter.title, - bookChapter.getAbsoluteURL().substringBefore(','), + bookChapter.getAbsoluteURL().substringBefore(",{"), //getAbsoluteURL已经格式过 textPages, chapterSize ) } diff --git a/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt b/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt index 61a15a9a4..3e6fa92b1 100644 --- a/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt +++ b/app/src/main/java/io/legado/app/utils/HtmlFormatter.kt @@ -1,5 +1,6 @@ package io.legado.app.utils +import io.legado.app.model.analyzeRule.AnalyzeUrl import java.net.URL import java.util.regex.Pattern @@ -26,43 +27,66 @@ object HtmlFormatter { .replace("[\\n\\s]+\$|^[\\n\\s]+".toRegex(), "") .replace("\\s*\\n+\\s*".toRegex(), "\n") - val sb = StringBuffer() + var str = "" var endPos = 0 - for (pattern in listOf( - "]*data-[^=]*= *\"([^\"])\"[^>]*>", - "]*src *= *\"([^\"{]+(?:\\{(?:[^{}]|\\{[^{}]*\\})*\\})?)\"[^>]*>" - )) { + var hasMatch = true //普通图片标签是否还未处理过 + var hasMatchX = false //是否存在带参数或带数据属性的图片标签 + var pos = -1 + val list = listOf("]*src *= *\"([^\"{]+\\{(?:[^{}]|\\{[^}]+\\})+\\})\"[^>]*>","]*data-[^=]*= *\"([^\"]+)\"[^>]*>","]*src *= *\"([^\"]+)\"[^>]*>") //优先匹配用户处理过所以带参数的图片标签,其次匹配带数据属性的图片标签 + while(++pos<3){ + if(pos == 2) { + if(hasMatchX)break //普通图片标签只在不存在存在带参数或带数据属性的图片标签的时候匹配 + else hasMatch = false //匹配带参数或带数据属性的图片标签同时也会格式化普通图片标签 + } var appendPos = 0 - val matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(keepImgHtml) - while (matcher.find()) { - val url = matcher.group(1)!! - val urlBefore = url.substringBefore(',') - val strBefore = keepImgHtml.substring(appendPos, matcher.start()) - sb.append( - if (strBefore.isBlank()) strBefore else strBefore.replace( - "\n", - "\n  " - ) //缩进图片之间的非空白段落 - ) - sb.append( - "" - ) - appendPos = matcher.end() + val matcher = + Pattern.compile(list[pos], Pattern.CASE_INSENSITIVE).matcher(keepImgHtml) + val sb = StringBuffer() + if (matcher.find()) { + do { + var strBefore = keepImgHtml.substring(appendPos, matcher.start()) + + if (hasMatch) { //格式化不带参数和数据属性的普通图片标签 + var appendPos0 = 0 + val matcher0 = Pattern.compile("]*src *= *\"([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE).matcher(strBefore) //格式化普通图片标签 + while (matcher0.find()) { + val strBefore0 = strBefore.substring(appendPos0, matcher.start()) + sb.append( if (strBefore0.isBlank()) strBefore0 else strBefore0.replace("\n","\n  ")) + sb.append("") + appendPos0 = matcher.end() + } + strBefore = if (appendPos0 < strBefore.length) strBefore.substring(appendPos0, strBefore.length) else "" + } + + sb.append( + if (strBefore.isBlank()) strBefore else strBefore.replace("\n","\n  ") //缩进图片之间的非空白段落 + ) + + if (pos == 0) { + val url = matcher.group(1)!! + val urlMatcher = AnalyzeUrl.paramPattern.matcher(url) + val find = urlMatcher.find() + sb.append("") + + } else sb.append("") + + appendPos = matcher.end() + } while (matcher.find()) + hasMatch = false //普通图片标签已经处理过 } - if (appendPos != 0) endPos = appendPos - } - if (endPos < keepImgHtml.length) { - sb.append( - keepImgHtml.substring(endPos, keepImgHtml.length).replace("\n", "\n  ") - ) //缩进图片之后的非空白段落 + if (appendPos != 0) { + hasMatchX = true //存在带参数或带数据属性的图片标签 + endPos = appendPos //存在匹配,更新位置 + str = sb.toString() //存在匹配,更新字符串 + } } - return sb.toString() - } + return if (endPos < keepImgHtml.length) { + str + keepImgHtml.substring( endPos, keepImgHtml.length ).replace("\n","\n  ") //缩进图片之后的非空白段落 + }else str + } }