diff --git a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt index 8e526b60f..a903ed654 100644 --- a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt @@ -119,23 +119,18 @@ class EpubFile(var book: Book) { private fun getContent(chapter: BookChapter): String? { /*获取当前章节文本*/ - return getChildChapter(chapter, chapter.url) - } - - private fun getChildChapter(chapter: BookChapter, href: String): String? { epubBook?.let { - val body = Jsoup.parse(String(it.resources.getByHref(href).data, mCharset)).body() + val body = + Jsoup.parse(String(it.resources.getByHref(chapter.url).data, mCharset)).body() - if (chapter.url == href) { - val startFragmentId = chapter.startFragmentId - val endFragmentId = chapter.endFragmentId - /*一些书籍依靠href索引的resource会包含多个章节,需要依靠fragmentId来截取到当前章节的内容*/ - /*注:这里较大增加了内容加载的时间,所以首次获取内容后可存储到本地cache,减少重复加载*/ - if (!startFragmentId.isNullOrBlank()) - body.getElementById(startFragmentId)?.previousElementSiblings()?.remove() - if (!endFragmentId.isNullOrBlank() && endFragmentId != startFragmentId) - body.getElementById(endFragmentId)?.nextElementSiblings()?.remove() - } + val startFragmentId = chapter.startFragmentId + val endFragmentId = chapter.endFragmentId + /*一些书籍依靠href索引的resource会包含多个章节,需要依靠fragmentId来截取到当前章节的内容*/ + /*注:这里较大增加了内容加载的时间,所以首次获取内容后可存储到本地cache,减少重复加载*/ + if (!startFragmentId.isNullOrBlank()) + body.getElementById(startFragmentId)?.previousElementSiblings()?.remove() + if (!endFragmentId.isNullOrBlank() && endFragmentId != startFragmentId) + body.getElementById(endFragmentId)?.nextElementSiblings()?.remove() /*选择去除正文中的H标签,部分书籍标题与阅读标题重复待优化*/ var tag = Book.hTag diff --git a/epublib/src/main/java/me/ag2s/epublib/domain/TableOfContents.java b/epublib/src/main/java/me/ag2s/epublib/domain/TableOfContents.java index 6c268358d..7692d258d 100644 --- a/epublib/src/main/java/me/ag2s/epublib/domain/TableOfContents.java +++ b/epublib/src/main/java/me/ag2s/epublib/domain/TableOfContents.java @@ -10,251 +10,255 @@ import java.util.Set; /** * The table of contents of the book. * The TableOfContents is a tree structure at the root it is a list of TOCReferences, each if which may have as children another list of TOCReferences. - * + *

* The table of contents is used by epub as a quick index to chapters and sections within chapters. * It may contain duplicate entries, may decide to point not to certain chapters, etc. - * + *

* See the spine for the complete list of sections in the order in which they should be read. * - * @see Spine - * * @author paul + * @see Spine */ public class TableOfContents implements Serializable { - private static final long serialVersionUID = -3147391239966275152L; + private static final long serialVersionUID = -3147391239966275152L; - public static final String DEFAULT_PATH_SEPARATOR = "/"; + public static final String DEFAULT_PATH_SEPARATOR = "/"; - private List tocReferences; + private List tocReferences; - public TableOfContents() { - this(new ArrayList<>()); - } + public TableOfContents() { + this(new ArrayList<>()); + } - public TableOfContents(List tocReferences) { - this.tocReferences = tocReferences; - } + public TableOfContents(List tocReferences) { + this.tocReferences = tocReferences; + } - public List getTocReferences() { - return tocReferences; - } + public List getTocReferences() { + return tocReferences; + } - public void setTocReferences(List tocReferences) { - this.tocReferences = tocReferences; - } + public void setTocReferences(List tocReferences) { + this.tocReferences = tocReferences; + } - /** - * Calls addTOCReferenceAtLocation after splitting the path using the DEFAULT_PATH_SEPARATOR. - * @return the new TOCReference - */ - @SuppressWarnings("unused") - public TOCReference addSection(Resource resource, String path) { - return addSection(resource, path, DEFAULT_PATH_SEPARATOR); - } + /** + * Calls addTOCReferenceAtLocation after splitting the path using the DEFAULT_PATH_SEPARATOR. + * + * @return the new TOCReference + */ + @SuppressWarnings("unused") + public TOCReference addSection(Resource resource, String path) { + return addSection(resource, path, DEFAULT_PATH_SEPARATOR); + } - /** - * Calls addTOCReferenceAtLocation after splitting the path using the given pathSeparator. - * - * @param resource resource - * @param path path - * @param pathSeparator pathSeparator - * @return the new TOCReference - */ - public TOCReference addSection(Resource resource, String path, - String pathSeparator) { - String[] pathElements = path.split(pathSeparator); - return addSection(resource, pathElements); - } + /** + * Calls addTOCReferenceAtLocation after splitting the path using the given pathSeparator. + * + * @param resource resource + * @param path path + * @param pathSeparator pathSeparator + * @return the new TOCReference + */ + public TOCReference addSection(Resource resource, String path, + String pathSeparator) { + String[] pathElements = path.split(pathSeparator); + return addSection(resource, pathElements); + } - /** - * Finds the first TOCReference in the given list that has the same title as the given Title. - * - * @param title title - * @param tocReferences tocReferences - * @return null if not found. - */ - private static TOCReference findTocReferenceByTitle(String title, - List tocReferences) { - for (TOCReference tocReference : tocReferences) { - if (title.equals(tocReference.getTitle())) { + /** + * Finds the first TOCReference in the given list that has the same title as the given Title. + * + * @param title title + * @param tocReferences tocReferences + * @return null if not found. + */ + private static TOCReference findTocReferenceByTitle(String title, + List tocReferences) { + for (TOCReference tocReference : tocReferences) { + if (title.equals(tocReference.getTitle())) { + return tocReference; + } + } + return null; + } + + /** + * Adds the given Resources to the TableOfContents at the location specified by the pathElements. + *

+ * Example: + * Calling this method with a Resource and new String[] {"chapter1", "paragraph1"} will result in the following: + *

+ * + * @param resource resource + * @param pathElements pathElements + * @return the new TOCReference + */ + public TOCReference addSection(Resource resource, String[] pathElements) { + if (pathElements == null || pathElements.length == 0) { + return null; + } + TOCReference result = null; + List currentTocReferences = this.tocReferences; + for (String currentTitle : pathElements) { + result = findTocReferenceByTitle(currentTitle, currentTocReferences); + if (result == null) { + result = new TOCReference(currentTitle, null); + currentTocReferences.add(result); + } + currentTocReferences = result.getChildren(); + } + result.setResource(resource); + return result; + } + + /** + * Adds the given Resources to the TableOfContents at the location specified by the pathElements. + *

+ * Example: + * Calling this method with a Resource and new int[] {0, 0} will result in the following: + *

+ * + * @param resource resource + * @param pathElements pathElements + * @return the new TOCReference + */ + @SuppressWarnings("unused") + public TOCReference addSection(Resource resource, int[] pathElements, + String sectionTitlePrefix, String sectionNumberSeparator) { + if (pathElements == null || pathElements.length == 0) { + return null; + } + TOCReference result = null; + List currentTocReferences = this.tocReferences; + for (int i = 0; i < pathElements.length; i++) { + int currentIndex = pathElements[i]; + if (currentIndex > 0 && currentIndex < (currentTocReferences.size() + - 1)) { + result = currentTocReferences.get(currentIndex); + } else { + result = null; + } + if (result == null) { + paddTOCReferences(currentTocReferences, pathElements, i, + sectionTitlePrefix, sectionNumberSeparator); + result = currentTocReferences.get(currentIndex); + } + currentTocReferences = result.getChildren(); + } + result.setResource(resource); + return result; + } + + private void paddTOCReferences(List currentTocReferences, + int[] pathElements, int pathPos, String sectionPrefix, + String sectionNumberSeparator) { + for (int i = currentTocReferences.size(); i <= pathElements[pathPos]; i++) { + String sectionTitle = createSectionTitle(pathElements, pathPos, i, + sectionPrefix, + sectionNumberSeparator); + currentTocReferences.add(new TOCReference(sectionTitle, null)); + } + } + + private String createSectionTitle(int[] pathElements, int pathPos, + int lastPos, + String sectionPrefix, String sectionNumberSeparator) { + StringBuilder title = new StringBuilder(sectionPrefix); + for (int i = 0; i < pathPos; i++) { + if (i > 0) { + title.append(sectionNumberSeparator); + } + title.append(pathElements[i] + 1); + } + if (pathPos > 0) { + title.append(sectionNumberSeparator); + } + title.append(lastPos + 1); + return title.toString(); + } + + public TOCReference addTOCReference(TOCReference tocReference) { + if (tocReferences == null) { + tocReferences = new ArrayList<>(); + } + tocReferences.add(tocReference); return tocReference; - } } - return null; - } - /** - * Adds the given Resources to the TableOfContents at the location specified by the pathElements. - * - * Example: - * Calling this method with a Resource and new String[] {"chapter1", "paragraph1"} will result in the following: - *
    - *
  • a TOCReference with the title "chapter1" at the root level.
    - * If this TOCReference did not yet exist it will have been created and does not point to any resource
  • - *
  • A TOCReference that has the title "paragraph1". This TOCReference will be the child of TOCReference "chapter1" and - * will point to the given Resource
  • - *
- * - * @param resource resource - * @param pathElements pathElements - * @return the new TOCReference - */ - public TOCReference addSection(Resource resource, String[] pathElements) { - if (pathElements == null || pathElements.length == 0) { - return null; + /** + * All unique references (unique by href) in the order in which they are referenced to in the table of contents. + * + * @return All unique references (unique by href) in the order in which they are referenced to in the table of contents. + */ + public List getAllUniqueResources() { + Set uniqueHrefs = new HashSet<>(); + List result = new ArrayList<>(); + getAllUniqueResources(uniqueHrefs, result, tocReferences); + return result; } - TOCReference result = null; - List currentTocReferences = this.tocReferences; - for (String currentTitle : pathElements) { - result = findTocReferenceByTitle(currentTitle, currentTocReferences); - if (result == null) { - result = new TOCReference(currentTitle, null); - currentTocReferences.add(result); - } - currentTocReferences = result.getChildren(); - } - result.setResource(resource); - return result; - } - /** - * Adds the given Resources to the TableOfContents at the location specified by the pathElements. - * - * Example: - * Calling this method with a Resource and new int[] {0, 0} will result in the following: - *
    - *
  • a TOCReference at the root level.
    - * If this TOCReference did not yet exist it will have been created with a title of "" and does not point to any resource
  • - *
  • A TOCReference that points to the given resource and is a child of the previously created TOCReference.
    - * If this TOCReference didn't exist yet it will be created and have a title of ""
  • - *
- * - * @param resource resource - * @param pathElements pathElements - * @return the new TOCReference - */ - @SuppressWarnings("unused") - public TOCReference addSection(Resource resource, int[] pathElements, - String sectionTitlePrefix, String sectionNumberSeparator) { - if (pathElements == null || pathElements.length == 0) { - return null; + private static void getAllUniqueResources( + Set uniqueHrefs, + List result, + List tocReferences + ) { + for (TOCReference tocReference : tocReferences) { + Resource resource = tocReference.getResource(); + if (resource != null && !uniqueHrefs.contains(resource.getHref())) { + uniqueHrefs.add(resource.getHref()); + result.add(resource); + } + getAllUniqueResources(uniqueHrefs, result, tocReference.getChildren()); + } } - TOCReference result = null; - List currentTocReferences = this.tocReferences; - for (int i = 0; i < pathElements.length; i++) { - int currentIndex = pathElements[i]; - if (currentIndex > 0 && currentIndex < (currentTocReferences.size() - - 1)) { - result = currentTocReferences.get(currentIndex); - } else { - result = null; - } - if (result == null) { - paddTOCReferences(currentTocReferences, pathElements, i, - sectionTitlePrefix, sectionNumberSeparator); - result = currentTocReferences.get(currentIndex); - } - currentTocReferences = result.getChildren(); + + /** + * The total number of references in this table of contents. + * + * @return The total number of references in this table of contents. + */ + public int size() { + return getTotalSize(tocReferences); } - result.setResource(resource); - return result; - } - private void paddTOCReferences(List currentTocReferences, - int[] pathElements, int pathPos, String sectionPrefix, - String sectionNumberSeparator) { - for (int i = currentTocReferences.size(); i <= pathElements[pathPos]; i++) { - String sectionTitle = createSectionTitle(pathElements, pathPos, i, - sectionPrefix, - sectionNumberSeparator); - currentTocReferences.add(new TOCReference(sectionTitle, null)); + private static int getTotalSize(Collection tocReferences) { + int result = tocReferences.size(); + for (TOCReference tocReference : tocReferences) { + result += getTotalSize(tocReference.getChildren()); + } + return result; } - } - private String createSectionTitle(int[] pathElements, int pathPos, - int lastPos, - String sectionPrefix, String sectionNumberSeparator) { - StringBuilder title = new StringBuilder(sectionPrefix); - for (int i = 0; i < pathPos; i++) { - if (i > 0) { - title.append(sectionNumberSeparator); - } - title.append(pathElements[i] + 1); + /** + * The maximum depth of the reference tree + * + * @return The maximum depth of the reference tree + */ + public int calculateDepth() { + return calculateDepth(tocReferences, 0); } - if (pathPos > 0) { - title.append(sectionNumberSeparator); + + private int calculateDepth(List tocReferences, + int currentDepth) { + int maxChildDepth = 0; + for (TOCReference tocReference : tocReferences) { + int childDepth = calculateDepth(tocReference.getChildren(), 1); + if (childDepth > maxChildDepth) { + maxChildDepth = childDepth; + } + } + return currentDepth + maxChildDepth; } - title.append(lastPos + 1); - return title.toString(); - } - - public TOCReference addTOCReference(TOCReference tocReference) { - if (tocReferences == null) { - tocReferences = new ArrayList<>(); - } - tocReferences.add(tocReference); - return tocReference; - } - - /** - * All unique references (unique by href) in the order in which they are referenced to in the table of contents. - * - * @return All unique references (unique by href) in the order in which they are referenced to in the table of contents. - */ - public List getAllUniqueResources() { - Set uniqueHrefs = new HashSet<>(); - List result = new ArrayList<>(); - getAllUniqueResources(uniqueHrefs, result, tocReferences); - return result; - } - - private static void getAllUniqueResources(Set uniqueHrefs, - List result, List tocReferences) { - for (TOCReference tocReference : tocReferences) { - Resource resource = tocReference.getResource(); - if (resource != null && !uniqueHrefs.contains(resource.getHref())) { - uniqueHrefs.add(resource.getHref()); - result.add(resource); - } - getAllUniqueResources(uniqueHrefs, result, tocReference.getChildren()); - } - } - - /** - * The total number of references in this table of contents. - * - * @return The total number of references in this table of contents. - */ - public int size() { - return getTotalSize(tocReferences); - } - - private static int getTotalSize(Collection tocReferences) { - int result = tocReferences.size(); - for (TOCReference tocReference : tocReferences) { - result += getTotalSize(tocReference.getChildren()); - } - return result; - } - - /** - * The maximum depth of the reference tree - * @return The maximum depth of the reference tree - */ - public int calculateDepth() { - return calculateDepth(tocReferences, 0); - } - - private int calculateDepth(List tocReferences, - int currentDepth) { - int maxChildDepth = 0; - for (TOCReference tocReference : tocReferences) { - int childDepth = calculateDepth(tocReference.getChildren(), 1); - if (childDepth > maxChildDepth) { - maxChildDepth = childDepth; - } - } - return currentDepth + maxChildDepth; - } }