Check
Check
if (file is EpubByteContentFile) {
content = file.Content;
} else if (file is EpubTextContentFile) {
content = convert.utf8.encode(file.Content);
}
arch.addFile(ArchiveFile(
ZipPathUtils.combine(book.Schema.ContentDirectoryPath, name),
content.length,
content));
});
return arch;
}
return ZipEncoder().encode(arch);
}
}
String FileName;
EpubContentType ContentType;
String ContentMimeType;
EpubContentFileRef(EpubBookRef epubBookRef) {
this.epubBookRef = epubBookRef;
}
@override
int get hashCode =>
hash3(FileName.hashCode, ContentMimeType.hashCode, ContentType.hashCode);
ArchiveFile getContentFileEntry() {
String contentFilePath =
ZipPathUtils.combine(epubBookRef.Schema.ContentDirectoryPath, FileName);
ArchiveFile contentFileEntry = epubBookRef.EpubArchive().files.firstWhere(
(ArchiveFile x) => x.name == contentFilePath,
orElse: () => null);
if (contentFileEntry == null) {
throw Exception(
"EPUB parsing error: file $contentFilePath not found in archive.");
}
return contentFileEntry;
}
List<int> getContentStream() {
return openContentStream(getContentFileEntry());
}
import 'epub_byte_content_file_ref.dart';
import 'epub_content_file_ref.dart';
import 'epub_text_content_file_ref.dart';
class EpubContentRef {
Map<String, EpubTextContentFileRef> Html;
Map<String, EpubTextContentFileRef> Css;
Map<String, EpubByteContentFileRef> Images;
Map<String, EpubByteContentFileRef> Fonts;
Map<String, EpubContentFileRef> AllFiles;
EpubContentRef() {
Html = Map<String, EpubTextContentFileRef>();
Css = Map<String, EpubTextContentFileRef>();
Images = Map<String, EpubByteContentFileRef>();
Fonts = Map<String, EpubByteContentFileRef>();
AllFiles = Map<String, EpubContentFileRef>();
}
@override
int get hashCode {
var objects = []
..addAll(Html.keys.map((key) => key.hashCode))
..addAll(Html.values.map((value) => value.hashCode))
..addAll(Css.keys.map((key) => key.hashCode))
..addAll(Css.values.map((value) => value.hashCode))
..addAll(Images.keys.map((key) => key.hashCode))
..addAll(Images.values.map((value) => value.hashCode))
..addAll(Fonts.keys.map((key) => key.hashCode))
..addAll(Fonts.values.map((value) => value.hashCode))
..addAll(AllFiles.keys.map((key) => key.hashCode))
..addAll(AllFiles.values.map((value) => value.hashCode));
return hashObjects(objects);
}
import 'dart:async';
import 'epub_text_content_file_ref.dart';
class EpubChapterRef {
EpubTextContentFileRef epubTextContentFileRef;
String Title;
String ContentFileName;
String Anchor;
List<EpubChapterRef> SubChapters;
EpubChapterRef(EpubTextContentFileRef epubTextContentFileRef) {
this.epubTextContentFileRef = epubTextContentFileRef;
}
@override
int get hashCode {
var objects = []
..add(Title.hashCode)
..add(ContentFileName.hashCode)
..add(Anchor.hashCode)
..add(epubTextContentFileRef.hashCode)
..addAll(SubChapters?.map((subChapter) => subChapter.hashCode) ?? [0]);
return hashObjects(objects);
}
import 'dart:async';
import 'epub_book_ref.dart';
import 'epub_content_file_ref.dart';
class SchemaReader {
static Future<EpubSchema> readSchema(Archive epubArchive) async {
EpubSchema result = EpubSchema();
EpubPackage package =
await PackageReader.readPackage(epubArchive, rootFilePath);
result.Package = package;
return result;
}
}
class RootFilePathReader {
static Future<String> getRootFilePath(Archive epubArchive) async {
const String EPUB_CONTAINER_FILE_PATH = "META-INF/container.xml";
xml.XmlDocument containerDocument =
xml.parse(convert.utf8.decode(containerFileEntry.content));
xml.XmlElement packageElement = containerDocument
.findAllElements("container",
namespace: "urn:oasis:names:tc:opendocument:xmlns:container")
.firstWhere((xml.XmlElement elem) => elem != null, orElse: () => null);
if (packageElement == null) {
throw Exception("EPUB parsing error: Invalid epub container");
}
return rootFileElement.getAttribute("full-path");
}
}
class PackageReader {
static EpubGuide readGuide(xml.XmlElement guideNode) {
EpubGuide result = EpubGuide();
result.Items = List<EpubGuideReference>();
guideNode.children
.whereType<xml.XmlElement>()
.forEach((xml.XmlElement guideReferenceNode) {
if (guideReferenceNode.name.local.toLowerCase() == "reference") {
EpubGuideReference guideReference = EpubGuideReference();
guideReferenceNode.attributes
.forEach((xml.XmlAttribute guideReferenceNodeAttribute) {
String attributeValue = guideReferenceNodeAttribute.value;
switch (guideReferenceNodeAttribute.name.local.toLowerCase()) {
case "type":
guideReference.Type = attributeValue;
break;
case "title":
guideReference.Title = attributeValue;
break;
case "href":
guideReference.Href = attributeValue;
break;
}
});
if (guideReference.Type == null || guideReference.Type.isEmpty) {
throw Exception("Incorrect EPUB guide: item type is missing");
}
if (guideReference.Href == null || guideReference.Href.isEmpty) {
throw Exception("Incorrect EPUB guide: item href is missing");
}
result.Items.add(guideReference);
}
});
return result;
}
import 'dart:async';
import 'package:archive/archive.dart';
import 'package:dart2_constant/convert.dart' as convert;
import 'package:nxbxaydung/vhmt_epub_reader/epub/src/schema/opf/epub_version.dart';
import 'package:xml/xml.dart' as xml;
import '../schema/navigation/epub_metadata.dart';
import '../schema/navigation/epub_navigation.dart';
import '../schema/navigation/epub_navigation_doc_author.dart';
import '../schema/navigation/epub_navigation_doc_title.dart';
import '../schema/navigation/epub_navigation_head.dart';
import '../schema/navigation/epub_navigation_head_meta.dart';
import '../schema/navigation/epub_navigation_label.dart';
import '../schema/navigation/epub_navigation_list.dart';
import '../schema/navigation/epub_navigation_map.dart';
import '../schema/navigation/epub_navigation_page_list.dart';
import '../schema/navigation/epub_navigation_page_target.dart';
import '../schema/navigation/epub_navigation_page_target_type.dart';
import '../schema/navigation/epub_navigation_point.dart';
import '../schema/navigation/epub_navigation_target.dart';
import '../schema/opf/epub_manifest_item.dart';
import '../schema/opf/epub_package.dart';
import '../utils/enum_from_string.dart';
import '../utils/zip_path_utils.dart';
class NavigationReader {
static Future<EpubNavigation> readNavigation(Archive epubArchive,
String contentDirectoryPath, EpubPackage package) async {
EpubNavigation result = EpubNavigation();
String tocId = package.Spine.TableOfContents;
if (tocId == null || tocId.isEmpty) {
if (package.Version == EpubVersion.Epub2) {
throw Exception("EPUB parsing error: TOC ID is empty.");
}
return null;
}
String tocFileEntryPath =
ZipPathUtils.combine(contentDirectoryPath, tocManifestItem.Href);
ArchiveFile tocFileEntry = epubArchive.files.firstWhere(
(ArchiveFile file) =>
file.name.toLowerCase() == tocFileEntryPath.toLowerCase(),
orElse: () => null);
if (tocFileEntry == null) {
throw Exception(
"EPUB parsing error: TOC file $tocFileEntryPath not found in archive.");
}
xml.XmlDocument containerDocument =
xml.parse(convert.utf8.decode(tocFileEntry.content));
EpubNavigationDocTitle navigationDocTitle =
readNavigationDocTitle(docTitleNode);
result.DocTitle = navigationDocTitle;
result.DocAuthors = List<EpubNavigationDocAuthor>();
ncxNode
.findElements("docAuthor", namespace: ncxNamespace)
.forEach((xml.XmlElement docAuthorNode) {
EpubNavigationDocAuthor navigationDocAuthor =
readNavigationDocAuthor(docAuthorNode);
result.DocAuthors.add(navigationDocAuthor);
});
result.NavLists = List<EpubNavigationList>();
ncxNode
.findElements("navList", namespace: ncxNamespace)
.forEach((xml.XmlElement navigationListNode) {
EpubNavigationList navigationList =
readNavigationList(navigationListNode);
result.NavLists.add(navigationList);
});
return result;
}
return result;
}
static EpubNavigationDocAuthor readNavigationDocAuthor(
xml.XmlElement docAuthorNode) {
EpubNavigationDocAuthor result = EpubNavigationDocAuthor();
result.Authors = List<String>();
docAuthorNode.children
.whereType<xml.XmlElement>()
.forEach((xml.XmlElement textNode) {
if (textNode.name.local.toLowerCase() == "text") {
result.Authors.add(textNode.text);
}
});
return result;
}
headNode.children
.whereType<xml.XmlElement>()
.forEach((xml.XmlElement metaNode) {
if (metaNode.name.local.toLowerCase() == "meta") {
EpubNavigationHeadMeta meta = EpubNavigationHeadMeta();
metaNode.attributes.forEach((xml.XmlAttribute metaNodeAttribute) {
String attributeValue = metaNodeAttribute.value;
switch (metaNodeAttribute.name.local.toLowerCase()) {
case "name":
meta.Name = attributeValue;
break;
case "content":
meta.Content = attributeValue;
break;
case "scheme":
meta.Scheme = attributeValue;
break;
}
});
result.Metadata.add(meta);
}
});
return result;
}
result.Text = navigationLabelTextNode.text;
return result;
}
return result;
}
navigationPageTargetNode.children
.whereType<xml.XmlElement>()
.forEach((xml.XmlElement navigationPageTargetChildNode) {
switch (navigationPageTargetChildNode.name.local.toLowerCase()) {
case "navlabel":
EpubNavigationLabel navigationLabel =
readNavigationLabel(navigationPageTargetChildNode);
result.NavigationLabels.add(navigationLabel);
break;
case "content":
EpubNavigationContent content =
readNavigationContent(navigationPageTargetChildNode);
result.Content = content;
break;
}
});
if (result.NavigationLabels.isEmpty) {
throw Exception(
"Incorrect EPUB navigation page target: at least one navLabel element is required.");
}
return result;
}
result.NavigationLabels = List<EpubNavigationLabel>();
result.ChildNavigationPoints = List<EpubNavigationPoint>();
navigationPointNode.children
.whereType<xml.XmlElement>()
.forEach((xml.XmlElement navigationPointChildNode) {
switch (navigationPointChildNode.name.local.toLowerCase()) {
case "navlabel":
EpubNavigationLabel navigationLabel =
readNavigationLabel(navigationPointChildNode);
result.NavigationLabels.add(navigationLabel);
break;
case "content":
EpubNavigationContent content =
readNavigationContent(navigationPointChildNode);
result.Content = content;
break;
case "navpoint":
EpubNavigationPoint childNavigationPoint =
readNavigationPoint(navigationPointChildNode);
result.ChildNavigationPoints.add(childNavigationPoint);
break;
}
});
if (result.NavigationLabels.isEmpty) {
throw Exception(
"EPUB parsing error: navigation point ${result.Id} should contain at least one navigation label.");
}
if (result.Content == null) {
throw Exception(
"EPUB parsing error: navigation point ${result.Id} should contain content.");
}
return result;
}
navigationTargetNode.children
.whereType<xml.XmlElement>()
.forEach((xml.XmlElement navigationTargetChildNode) {
switch (navigationTargetChildNode.name.local.toLowerCase()) {
case "navlabel":
EpubNavigationLabel navigationLabel =
readNavigationLabel(navigationTargetChildNode);
result.NavigationLabels.add(navigationLabel);
break;
case "content":
EpubNavigationContent content =
readNavigationContent(navigationTargetChildNode);
result.Content = content;
break;
}
});
if (result.NavigationLabels.isEmpty) {
throw Exception(
"Incorrect EPUB navigation target: at least one navLabel element is required.");
}
return result;
}
}
class ContentReader {
static EpubContentRef parseContentMap(EpubBookRef bookRef) {
EpubContentRef result = EpubContentRef();
result.Html = Map<String, EpubTextContentFileRef>();
result.Css = Map<String, EpubTextContentFileRef>();
result.Images = Map<String, EpubByteContentFileRef>();
result.Fonts = Map<String, EpubByteContentFileRef>();
result.AllFiles = Map<String, EpubContentFileRef>();
bookRef.Schema.Package.Manifest.Items
.forEach((EpubManifestItem manifestItem) {
String fileName = manifestItem.Href;
String contentMimeType = manifestItem.MediaType;
EpubContentType contentType =
getContentTypeByContentMimeType(contentMimeType);
switch (contentType) {
case EpubContentType.XHTML_1_1:
case EpubContentType.CSS:
case EpubContentType.OEB1_DOCUMENT:
case EpubContentType.OEB1_CSS:
case EpubContentType.XML:
case EpubContentType.DTBOOK:
case EpubContentType.DTBOOK_NCX:
EpubTextContentFileRef epubTextContentFile =
EpubTextContentFileRef(bookRef);
{
epubTextContentFile.FileName = Uri.decodeFull(fileName);
epubTextContentFile.ContentMimeType = contentMimeType;
epubTextContentFile.ContentType = contentType;
}
switch (contentType) {
case EpubContentType.XHTML_1_1:
result.Html[fileName] = epubTextContentFile;
break;
case EpubContentType.CSS:
result.Css[fileName] = epubTextContentFile;
break;
case EpubContentType.DTBOOK:
case EpubContentType.DTBOOK_NCX:
case EpubContentType.OEB1_DOCUMENT:
case EpubContentType.XML:
case EpubContentType.OEB1_CSS:
case EpubContentType.IMAGE_GIF:
case EpubContentType.IMAGE_JPEG:
case EpubContentType.IMAGE_PNG:
case EpubContentType.IMAGE_SVG:
case EpubContentType.FONT_TRUETYPE:
case EpubContentType.FONT_OPENTYPE:
case EpubContentType.OTHER:
break;
}
result.AllFiles[fileName] = epubTextContentFile;
break;
default:
EpubByteContentFileRef epubByteContentFile =
EpubByteContentFileRef(bookRef);
{
epubByteContentFile.FileName = Uri.decodeFull(fileName);
epubByteContentFile.ContentMimeType = contentMimeType;
epubByteContentFile.ContentType = contentType;
}
switch (contentType) {
case EpubContentType.IMAGE_GIF:
case EpubContentType.IMAGE_JPEG:
case EpubContentType.IMAGE_PNG:
case EpubContentType.IMAGE_SVG:
result.Images[fileName] = epubByteContentFile;
break;
case EpubContentType.FONT_TRUETYPE:
case EpubContentType.FONT_OPENTYPE:
result.Fonts[fileName] = epubByteContentFile;
break;
case EpubContentType.CSS:
case EpubContentType.XHTML_1_1:
case EpubContentType.DTBOOK:
case EpubContentType.DTBOOK_NCX:
case EpubContentType.OEB1_DOCUMENT:
case EpubContentType.XML:
case EpubContentType.OEB1_CSS:
case EpubContentType.OTHER:
break;
}
result.AllFiles[fileName] = epubByteContentFile;
break;
}
});
return result;
}
// ignore_for_file: deprecated_member_use
import '../ref_entities/epub_book_ref.dart';
import '../ref_entities/epub_chapter_ref.dart';
import '../ref_entities/epub_text_content_file_ref.dart';
import '../schema/navigation/epub_navigation_point.dart';
class ChapterReader {
static List<EpubChapterRef> getChapters(EpubBookRef bookRef) {
if (bookRef.Schema.Navigation == null) {
return List<EpubChapterRef>();
}
return getChaptersImpl(bookRef, bookRef.Schema.Navigation.NavMap.Points);
}
htmlContentFileRef = bookRef.Content.Html[contentFileName];
EpubChapterRef chapterRef = EpubChapterRef(htmlContentFileRef);
chapterRef.ContentFileName = contentFileName;
chapterRef.Anchor = anchor;
chapterRef.Title = navigationPoint.NavigationLabels.first.Text;
chapterRef.SubChapters =
getChaptersImpl(bookRef, navigationPoint.ChildNavigationPoints);
result.add(chapterRef);
});
return result;
}
}
import 'dart:async';
import '../ref_entities/epub_book_ref.dart';
import '../ref_entities/epub_byte_content_file_ref.dart';
import '../schema/opf/epub_manifest_item.dart';
import '../schema/opf/epub_metadata_meta.dart';
class BookCoverReader {
static Future<images.Image> readBookCover(EpubBookRef bookRef) async {
List<EpubMetadataMeta> metaItems =
bookRef.Schema.Package.Metadata.MetaItems;
if (metaItems == null || metaItems.isEmpty) return null;
EpubByteContentFileRef coverImageContentFileRef;
if (!bookRef.Content.Images.containsKey(coverManifestItem.Href)) {
throw Exception(
"Incorrect EPUB manifest: item with href = \"${coverManifestItem.Href}\" is missing.");
}
coverImageContentFileRef = bookRef.Content.Images[coverManifestItem.Href];
List<int> coverImageContent =
await coverImageContentFileRef.readContentAsBytes();
images.Image retval = images.decodeImage(coverImageContent);
return retval;
}
}