From 744124349d93862246cb36391c5f7f4d61ba6e74 Mon Sep 17 00:00:00 2001 From: vers-one <12114169+vers-one@users.noreply.github.com> Date: Sun, 18 Sep 2022 04:10:41 -0400 Subject: [PATCH] Remote manifest items support (#62) --- .../Unit/Comparers/EpubContentComparer.cs | 2 + .../Unit/Comparers/EpubContentRefComparer.cs | 2 + .../Unit/Readers/BookCoverReaderTests.cs | 2 +- .../Unit/Readers/ContentReaderTests.cs | 68 +++++--- .../Unit/Readers/NavigationReaderTests.cs | 2 +- .../Unit/Readers/SpineReaderTests.cs | 2 +- .../Unit/RefEntities/EpubBookRefTests.cs | 4 +- .../RefEntities/EpubContentFileRefTests.cs | 146 +++++++++++++++--- .../Unit/Root/EpubReaderTests.cs | 124 +++++++++++++-- .../Entities/EpubByteContentFile.cs | 2 +- Source/VersOne.Epub/Entities/EpubContent.cs | 10 +- .../VersOne.Epub/Entities/EpubContentFile.cs | 13 ++ .../Entities/EpubContentLocation.cs | 18 +++ .../Entities/EpubTextContentFile.cs | 2 +- Source/VersOne.Epub/EpubReader.cs | 43 +++--- Source/VersOne.Epub/Readers/ContentReader.cs | 21 +-- .../RefEntities/EpubByteContentFileRef.cs | 13 +- .../RefEntities/EpubContentFileRef.cs | 48 +++++- .../RefEntities/EpubContentRef.cs | 10 +- .../RefEntities/EpubTextContentFileRef.cs | 13 +- .../Utils/TaskExtensionMethods.cs | 20 +++ 21 files changed, 454 insertions(+), 111 deletions(-) create mode 100644 Source/VersOne.Epub/Entities/EpubContentLocation.cs create mode 100644 Source/VersOne.Epub/Utils/TaskExtensionMethods.cs diff --git a/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentComparer.cs b/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentComparer.cs index 696538d..8dda8d5 100644 --- a/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentComparer.cs +++ b/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentComparer.cs @@ -50,6 +50,8 @@ private static void CompareEpubContentFiles(EpubContentFile expected, EpubConten Assert.NotNull(actual); Assert.Equal(expected.FileName, actual.FileName); Assert.Equal(expected.FilePathInEpubArchive, actual.FilePathInEpubArchive); + Assert.Equal(expected.Href, actual.Href); + Assert.Equal(expected.ContentLocation, actual.ContentLocation); Assert.Equal(expected.ContentType, actual.ContentType); Assert.Equal(expected.ContentMimeType, actual.ContentMimeType); } diff --git a/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentRefComparer.cs b/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentRefComparer.cs index 6741d7f..7649e30 100644 --- a/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentRefComparer.cs +++ b/Source/VersOne.Epub.Test/Unit/Comparers/EpubContentRefComparer.cs @@ -27,6 +27,8 @@ private static void CompareEpubContentFileRefs(EpubContentFileRef expected, Epub Assert.Equal(expected.GetType(), actual.GetType()); Assert.Equal(expected.FileName, actual.FileName); Assert.Equal(expected.FilePathInEpubArchive, actual.FilePathInEpubArchive); + Assert.Equal(expected.Href, actual.Href); + Assert.Equal(expected.ContentLocation, actual.ContentLocation); Assert.Equal(expected.ContentType, actual.ContentType); Assert.Equal(expected.ContentMimeType, actual.ContentMimeType); } diff --git a/Source/VersOne.Epub.Test/Unit/Readers/BookCoverReaderTests.cs b/Source/VersOne.Epub.Test/Unit/Readers/BookCoverReaderTests.cs index 08b635e..ec593f4 100644 --- a/Source/VersOne.Epub.Test/Unit/Readers/BookCoverReaderTests.cs +++ b/Source/VersOne.Epub.Test/Unit/Readers/BookCoverReaderTests.cs @@ -305,7 +305,7 @@ private EpubBookRef CreateEmptyEpubBookRef(EpubVersion epubVersion) private EpubByteContentFileRef CreateTestImageFileRef(EpubBookRef epubBookRef) { - return new(epubBookRef, "cover.jpg", EpubContentType.IMAGE_JPEG, "image/jpeg"); + return new(epubBookRef, "cover.jpg", EpubContentLocation.LOCAL, EpubContentType.IMAGE_JPEG, "image/jpeg"); } private Dictionary CreateImageContentRefs(EpubByteContentFileRef imageFileRef) diff --git a/Source/VersOne.Epub.Test/Unit/Readers/ContentReaderTests.cs b/Source/VersOne.Epub.Test/Unit/Readers/ContentReaderTests.cs index 1b991e9..6232425 100644 --- a/Source/VersOne.Epub.Test/Unit/Readers/ContentReaderTests.cs +++ b/Source/VersOne.Epub.Test/Unit/Readers/ContentReaderTests.cs @@ -149,27 +149,43 @@ public void ParseContentMapWithFullEpubBookRefTest() { EpubManifestProperty.NAV } + }, + new EpubManifestItem() + { + Id = "item-19", + Href = "https://example.com/books/123/test.html", + MediaType = "application/xhtml+xml" + }, + new EpubManifestItem() + { + Id = "item-20", + Href = "https://example.com/books/123/image.jpg", + MediaType = "image/jpeg" } } }; - EpubTextContentFileRef expectedFileRef1 = new(epubBookRef, "text.html", EpubContentType.XHTML_1_1, "application/xhtml+xml"); - EpubTextContentFileRef expectedFileRef2 = new(epubBookRef, "doc.dtb", EpubContentType.DTBOOK, "application/x-dtbook+xml"); - EpubTextContentFileRef expectedFileRef3 = new(epubBookRef, "toc.ncx", EpubContentType.DTBOOK_NCX, "application/x-dtbncx+xml"); - EpubTextContentFileRef expectedFileRef4 = new(epubBookRef, "oeb.html", EpubContentType.OEB1_DOCUMENT, "text/x-oeb1-document"); - EpubTextContentFileRef expectedFileRef5 = new(epubBookRef, "file.xml", EpubContentType.XML, "application/xml"); - EpubTextContentFileRef expectedFileRef6 = new(epubBookRef, "styles.css", EpubContentType.CSS, "text/css"); - EpubTextContentFileRef expectedFileRef7 = new(epubBookRef, "oeb.css", EpubContentType.OEB1_CSS, "text/x-oeb1-css"); - EpubByteContentFileRef expectedFileRef8 = new(epubBookRef, "image1.gif", EpubContentType.IMAGE_GIF, "image/gif"); - EpubByteContentFileRef expectedFileRef9 = new(epubBookRef, "image2.jpg", EpubContentType.IMAGE_JPEG, "image/jpeg"); - EpubByteContentFileRef expectedFileRef10 = new(epubBookRef, "image3.png", EpubContentType.IMAGE_PNG, "image/png"); - EpubByteContentFileRef expectedFileRef11 = new(epubBookRef, "image4.svg", EpubContentType.IMAGE_SVG, "image/svg+xml"); - EpubByteContentFileRef expectedFileRef12 = new(epubBookRef, "font1.ttf", EpubContentType.FONT_TRUETYPE, "font/truetype"); - EpubByteContentFileRef expectedFileRef13 = new(epubBookRef, "font2.ttf", EpubContentType.FONT_TRUETYPE, "application/x-font-truetype"); - EpubByteContentFileRef expectedFileRef14 = new(epubBookRef, "font3.otf", EpubContentType.FONT_OPENTYPE, "font/opentype"); - EpubByteContentFileRef expectedFileRef15 = new(epubBookRef, "font4.otf", EpubContentType.FONT_OPENTYPE, "application/vnd.ms-opentype"); - EpubByteContentFileRef expectedFileRef16 = new(epubBookRef, "video.mp4", EpubContentType.OTHER, "video/mp4"); - EpubByteContentFileRef expectedFileRef17 = new(epubBookRef, "cover.jpg", EpubContentType.IMAGE_JPEG, "image/jpeg"); - EpubTextContentFileRef expectedFileRef18 = new(epubBookRef, "toc.html", EpubContentType.XHTML_1_1, "application/xhtml+xml"); + EpubTextContentFileRef expectedFileRef1 = new(epubBookRef, "text.html", EpubContentLocation.LOCAL, EpubContentType.XHTML_1_1, "application/xhtml+xml"); + EpubTextContentFileRef expectedFileRef2 = new(epubBookRef, "doc.dtb", EpubContentLocation.LOCAL, EpubContentType.DTBOOK, "application/x-dtbook+xml"); + EpubTextContentFileRef expectedFileRef3 = new(epubBookRef, "toc.ncx", EpubContentLocation.LOCAL, EpubContentType.DTBOOK_NCX, "application/x-dtbncx+xml"); + EpubTextContentFileRef expectedFileRef4 = new(epubBookRef, "oeb.html", EpubContentLocation.LOCAL, EpubContentType.OEB1_DOCUMENT, "text/x-oeb1-document"); + EpubTextContentFileRef expectedFileRef5 = new(epubBookRef, "file.xml", EpubContentLocation.LOCAL, EpubContentType.XML, "application/xml"); + EpubTextContentFileRef expectedFileRef6 = new(epubBookRef, "styles.css", EpubContentLocation.LOCAL, EpubContentType.CSS, "text/css"); + EpubTextContentFileRef expectedFileRef7 = new(epubBookRef, "oeb.css", EpubContentLocation.LOCAL, EpubContentType.OEB1_CSS, "text/x-oeb1-css"); + EpubByteContentFileRef expectedFileRef8 = new(epubBookRef, "image1.gif", EpubContentLocation.LOCAL, EpubContentType.IMAGE_GIF, "image/gif"); + EpubByteContentFileRef expectedFileRef9 = new(epubBookRef, "image2.jpg", EpubContentLocation.LOCAL, EpubContentType.IMAGE_JPEG, "image/jpeg"); + EpubByteContentFileRef expectedFileRef10 = new(epubBookRef, "image3.png", EpubContentLocation.LOCAL, EpubContentType.IMAGE_PNG, "image/png"); + EpubByteContentFileRef expectedFileRef11 = new(epubBookRef, "image4.svg", EpubContentLocation.LOCAL, EpubContentType.IMAGE_SVG, "image/svg+xml"); + EpubByteContentFileRef expectedFileRef12 = new(epubBookRef, "font1.ttf", EpubContentLocation.LOCAL, EpubContentType.FONT_TRUETYPE, "font/truetype"); + EpubByteContentFileRef expectedFileRef13 = new(epubBookRef, "font2.ttf", EpubContentLocation.LOCAL, EpubContentType.FONT_TRUETYPE, "application/x-font-truetype"); + EpubByteContentFileRef expectedFileRef14 = new(epubBookRef, "font3.otf", EpubContentLocation.LOCAL, EpubContentType.FONT_OPENTYPE, "font/opentype"); + EpubByteContentFileRef expectedFileRef15 = new(epubBookRef, "font4.otf", EpubContentLocation.LOCAL, EpubContentType.FONT_OPENTYPE, "application/vnd.ms-opentype"); + EpubByteContentFileRef expectedFileRef16 = new(epubBookRef, "video.mp4", EpubContentLocation.LOCAL, EpubContentType.OTHER, "video/mp4"); + EpubByteContentFileRef expectedFileRef17 = new(epubBookRef, "cover.jpg", EpubContentLocation.LOCAL, EpubContentType.IMAGE_JPEG, "image/jpeg"); + EpubTextContentFileRef expectedFileRef18 = new(epubBookRef, "toc.html", EpubContentLocation.LOCAL, EpubContentType.XHTML_1_1, "application/xhtml+xml"); + EpubTextContentFileRef expectedFileRef19 = + new(epubBookRef, "https://example.com/books/123/test.html", EpubContentLocation.REMOTE, EpubContentType.XHTML_1_1, "application/xhtml+xml"); + EpubByteContentFileRef expectedFileRef20 = + new(epubBookRef, "https://example.com/books/123/image.jpg", EpubContentLocation.REMOTE, EpubContentType.IMAGE_JPEG, "image/jpeg"); EpubContentRef expectedContentMap = new() { Html = new Dictionary() @@ -181,6 +197,10 @@ public void ParseContentMapWithFullEpubBookRefTest() { "toc.html", expectedFileRef18 + }, + { + "https://example.com/books/123/test.html", + expectedFileRef19 } }, Css = new Dictionary() @@ -211,6 +231,10 @@ public void ParseContentMapWithFullEpubBookRefTest() { "cover.jpg", expectedFileRef17 + }, + { + "https://example.com/books/123/image.jpg", + expectedFileRef20 } }, Fonts = new Dictionary() @@ -305,6 +329,14 @@ public void ParseContentMapWithFullEpubBookRefTest() { "toc.html", expectedFileRef18 + }, + { + "https://example.com/books/123/test.html", + expectedFileRef19 + }, + { + "https://example.com/books/123/image.jpg", + expectedFileRef20 } }, NavigationHtmlFile = expectedFileRef18, diff --git a/Source/VersOne.Epub.Test/Unit/Readers/NavigationReaderTests.cs b/Source/VersOne.Epub.Test/Unit/Readers/NavigationReaderTests.cs index 3ef48c2..e09f135 100644 --- a/Source/VersOne.Epub.Test/Unit/Readers/NavigationReaderTests.cs +++ b/Source/VersOne.Epub.Test/Unit/Readers/NavigationReaderTests.cs @@ -573,7 +573,7 @@ private EpubTextContentFileRef CreateTestNavigationFile(EpubBookRef epubBookRef) private EpubTextContentFileRef CreateTestHtmlFile(EpubBookRef epubBookRef, string htmlFileName) { - return new(epubBookRef, htmlFileName, EpubContentType.XHTML_1_1, "application/xhtml+xml"); + return new(epubBookRef, htmlFileName, EpubContentLocation.LOCAL, EpubContentType.XHTML_1_1, "application/xhtml+xml"); } private EpubNavigationItemRef CreateNavigationLink(string title, string htmlFileUrl, EpubTextContentFileRef htmlFileRef) diff --git a/Source/VersOne.Epub.Test/Unit/Readers/SpineReaderTests.cs b/Source/VersOne.Epub.Test/Unit/Readers/SpineReaderTests.cs index 9fd2a4e..f214014 100644 --- a/Source/VersOne.Epub.Test/Unit/Readers/SpineReaderTests.cs +++ b/Source/VersOne.Epub.Test/Unit/Readers/SpineReaderTests.cs @@ -176,7 +176,7 @@ private EpubBookRef CreateEmptyEpubBookRef() private EpubTextContentFileRef CreateTestHtmlFileRef(EpubBookRef epubBookRef, string fileName) { - return new(epubBookRef, fileName, EpubContentType.XHTML_1_1, "application/xhtml+xml"); + return new(epubBookRef, fileName, EpubContentLocation.LOCAL, EpubContentType.XHTML_1_1, "application/xhtml+xml"); } } } diff --git a/Source/VersOne.Epub.Test/Unit/RefEntities/EpubBookRefTests.cs b/Source/VersOne.Epub.Test/Unit/RefEntities/EpubBookRefTests.cs index 5ee71fe..f33ac4b 100644 --- a/Source/VersOne.Epub.Test/Unit/RefEntities/EpubBookRefTests.cs +++ b/Source/VersOne.Epub.Test/Unit/RefEntities/EpubBookRefTests.cs @@ -116,7 +116,7 @@ private EpubBookRef CreateEpubBookRefWithCover(byte[] coverFileContent) TestZipFile testZipFile = new(); testZipFile.AddEntry(COVER_FILE_PATH, coverFileContent); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - epubBookRef.Content.Cover = new EpubByteContentFileRef(epubBookRef, COVER_FILE_NAME, COVER_FILE_CONTENT_TYPE, COVER_FILE_CONTENT_MIME_TYPE); + epubBookRef.Content.Cover = new EpubByteContentFileRef(epubBookRef, COVER_FILE_NAME, EpubContentLocation.LOCAL, COVER_FILE_CONTENT_TYPE, COVER_FILE_CONTENT_MIME_TYPE); return epubBookRef; } @@ -237,7 +237,7 @@ private EpubBookRef CreateEpubBookRef(TestZipFile testZipFile) private EpubTextContentFileRef CreateTestHtmlFileRef(EpubBookRef epubBookRef, string fileName) { - return new(epubBookRef, fileName, EpubContentType.XHTML_1_1, "application/xhtml+xml"); + return new(epubBookRef, fileName, EpubContentLocation.LOCAL, EpubContentType.XHTML_1_1, "application/xhtml+xml"); } private EpubNavigationItemRef CreateTestNavigationLink(string title, string htmlFileUrl, EpubTextContentFileRef htmlFileRef) diff --git a/Source/VersOne.Epub.Test/Unit/RefEntities/EpubContentFileRefTests.cs b/Source/VersOne.Epub.Test/Unit/RefEntities/EpubContentFileRefTests.cs index 16bc7f4..ced1a31 100644 --- a/Source/VersOne.Epub.Test/Unit/RefEntities/EpubContentFileRefTests.cs +++ b/Source/VersOne.Epub.Test/Unit/RefEntities/EpubContentFileRefTests.cs @@ -7,22 +7,72 @@ namespace VersOne.Epub.Test.Unit.RefEntities public class EpubContentFileRefTests { private const string CONTENT_DIRECTORY_PATH = "Content"; - private const string TEXT_FILE_NAME = "test.html"; - private const string TEXT_FILE_PATH = $"{CONTENT_DIRECTORY_PATH}/{TEXT_FILE_NAME}"; + private const string LOCAL_TEXT_FILE_NAME = "test.html"; + private const string TEXT_FILE_PATH = $"{CONTENT_DIRECTORY_PATH}/{LOCAL_TEXT_FILE_NAME}"; + private const string REMOTE_TEXT_CONTENT_HREF = "https://example.com/books/123/test.html"; private const string TEXT_FILE_CONTENT = "Test HTML

Test content

"; private const EpubContentType TEXT_FILE_CONTENT_TYPE = EpubContentType.XHTML_1_1; private const string TEXT_FILE_CONTENT_MIME_TYPE = "application/xhtml+xml"; - private const string BYTE_FILE_NAME = "image.jpg"; - private const string BYTE_FILE_PATH = $"{CONTENT_DIRECTORY_PATH}/{BYTE_FILE_NAME}"; + private const string LOCAL_BYTE_FILE_NAME = "image.jpg"; + private const string BYTE_FILE_PATH = $"{CONTENT_DIRECTORY_PATH}/{LOCAL_BYTE_FILE_NAME}"; + private const string REMOTE_BYTE_CONTENT_HREF = "https://example.com/books/123/image.jpg"; private const EpubContentType BYTE_FILE_CONTENT_TYPE = EpubContentType.IMAGE_JPEG; private const string BYTE_FILE_CONTENT_MIME_TYPE = "image/jpeg"; private static readonly byte[] BYTE_FILE_CONTENT = new byte[] { 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46 }; + [Fact(DisplayName = "EpubTextContentFileRef with ContentLocation = LOCAL should have non-null FileName and FilePathInEpubArchive properties and null Href property")] + public void LocalTextContentItemPropertiesTest() + { + TestZipFile testZipFile = new(); + EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + Assert.Equal(LOCAL_TEXT_FILE_NAME, epubTextContentFileRef.FileName); + Assert.Equal(TEXT_FILE_PATH, epubTextContentFileRef.FilePathInEpubArchive); + Assert.Null(epubTextContentFileRef.Href); + } + + [Fact(DisplayName = "EpubByteContentFileRef with ContentLocation = LOCAL should have non-null FileName and FilePathInEpubArchive properties and null Href property")] + public void LocalByteContentItemPropertiesTest() + { + TestZipFile testZipFile = new(); + EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); + EpubByteContentFileRef epubByteContentFileRef = + new(epubBookRef, LOCAL_BYTE_FILE_NAME, EpubContentLocation.LOCAL, BYTE_FILE_CONTENT_TYPE, BYTE_FILE_CONTENT_MIME_TYPE); + Assert.Equal(LOCAL_BYTE_FILE_NAME, epubByteContentFileRef.FileName); + Assert.Equal(BYTE_FILE_PATH, epubByteContentFileRef.FilePathInEpubArchive); + Assert.Null(epubByteContentFileRef.Href); + } + + [Fact(DisplayName = "EpubTextContentFileRef with ContentLocation = REMOTE should have null FileName and FilePathInEpubArchive properties and non-null Href property")] + public void RemoteTextContentItemPropertiesTest() + { + TestZipFile testZipFile = new(); + EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, REMOTE_TEXT_CONTENT_HREF, EpubContentLocation.REMOTE, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + Assert.Equal(REMOTE_TEXT_CONTENT_HREF, epubTextContentFileRef.Href); + Assert.Null(epubTextContentFileRef.FileName); + Assert.Null(epubTextContentFileRef.FilePathInEpubArchive); + } + + [Fact(DisplayName = "EpubByteContentFileRef with ContentLocation = REMOTE should have null FileName and FilePathInEpubArchive properties and non-null Href property")] + public void RemoteByteContentItemPropertiesTest() + { + TestZipFile testZipFile = new(); + EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); + EpubByteContentFileRef epubByteContentFileRef = + new(epubBookRef, REMOTE_BYTE_CONTENT_HREF, EpubContentLocation.REMOTE, BYTE_FILE_CONTENT_TYPE, BYTE_FILE_CONTENT_MIME_TYPE); + Assert.Equal(REMOTE_BYTE_CONTENT_HREF, epubByteContentFileRef.Href); + Assert.Null(epubByteContentFileRef.FileName); + Assert.Null(epubByteContentFileRef.FilePathInEpubArchive); + } + [Fact(DisplayName = "Reading content of an existing text file synchronously should succeed")] public void ReadTextContentTest() { - EpubTextContentFileRef epubTextContentFileRef = CreateTextContentFileRef(); + EpubTextContentFileRef epubTextContentFileRef = CreateLocalTextContentFileRef(); string textContent = epubTextContentFileRef.ReadContent(); Assert.Equal(TEXT_FILE_CONTENT, textContent); } @@ -30,7 +80,7 @@ public void ReadTextContentTest() [Fact(DisplayName = "Reading content of an existing text file asynchronously should succeed")] public async void ReadTextContentAsyncTest() { - EpubTextContentFileRef epubTextContentFileRef = CreateTextContentFileRef(); + EpubTextContentFileRef epubTextContentFileRef = CreateLocalTextContentFileRef(); string textContent = await epubTextContentFileRef.ReadContentAsync(); Assert.Equal(TEXT_FILE_CONTENT, textContent); } @@ -38,7 +88,7 @@ public async void ReadTextContentAsyncTest() [Fact(DisplayName = "Reading content of an existing byte file synchronously should succeed")] public void ReadByteContentTest() { - EpubByteContentFileRef epubByteContentFileRef = CreateByteContentFileRef(); + EpubByteContentFileRef epubByteContentFileRef = CreateLocalByteContentFileRef(); byte[] byteContent = epubByteContentFileRef.ReadContent(); Assert.Equal(BYTE_FILE_CONTENT, byteContent); } @@ -46,7 +96,7 @@ public void ReadByteContentTest() [Fact(DisplayName = "Reading content of an existing byte file asynchronously should succeed")] public async void ReadByteContentAsyncTest() { - EpubByteContentFileRef epubByteContentFileRef = CreateByteContentFileRef(); + EpubByteContentFileRef epubByteContentFileRef = CreateLocalByteContentFileRef(); byte[] byteContent = await epubByteContentFileRef.ReadContentAsync(); Assert.Equal(BYTE_FILE_CONTENT, byteContent); } @@ -56,7 +106,7 @@ public void GetContentStreamWithEmptyFileNameTest() { TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, String.Empty, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, String.Empty, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); Assert.Throws(() => epubTextContentFileRef.GetContentStream()); } @@ -65,7 +115,7 @@ public void GetContentStreamWithMissingFileTest() { TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); Assert.Throws(() => epubTextContentFileRef.GetContentStream()); } @@ -75,7 +125,7 @@ public void GetContentStreamWithLargeFileTest() TestZipFile testZipFile = new(); testZipFile.AddEntry(TEXT_FILE_PATH, new Test4GbZipFileEntry()); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); Assert.Throws(() => epubTextContentFileRef.GetContentStream()); } @@ -86,7 +136,8 @@ public void ReadContentWithMissingFileAndSuppressExceptionTrueTest() contentReaderOptions.ContentFileMissing += (sender, e) => e.SuppressException = true; TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); string textContent = epubTextContentFileRef.ReadContent(); Assert.Equal(String.Empty, textContent); } @@ -98,7 +149,8 @@ public void ReadContentWithMissingFileAndReplacementContentStreamSetTest() contentReaderOptions.ContentFileMissing += (sender, e) => e.ReplacementContentStream = new MemoryStream(Encoding.UTF8.GetBytes(TEXT_FILE_CONTENT)); TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); string textContent = epubTextContentFileRef.ReadContent(); Assert.Equal(TEXT_FILE_CONTENT, textContent); } @@ -110,7 +162,8 @@ public void ReadContentWithReplacementContentMultipleTimesTest() contentReaderOptions.ContentFileMissing += (sender, e) => e.ReplacementContentStream = new MemoryStream(Encoding.UTF8.GetBytes(TEXT_FILE_CONTENT)); TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); string textContent = epubTextContentFileRef.ReadContent(); Assert.Equal(TEXT_FILE_CONTENT, textContent); textContent = epubTextContentFileRef.ReadContent(); @@ -123,7 +176,8 @@ public void GetContentStreamWithMissingFileAndNoContentFileMissingHandlersTest() ContentReaderOptions contentReaderOptions = new(); TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); Assert.Throws(() => epubTextContentFileRef.GetContentStream()); } @@ -139,28 +193,78 @@ public void ContentFileMissingEventArgsTest() }; TestZipFile testZipFile = new(); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - EpubTextContentFileRef epubTextContentFileRef = new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); + EpubTextContentFileRef epubTextContentFileRef = + new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE, contentReaderOptions); epubTextContentFileRef.ReadContent(); - Assert.Equal(TEXT_FILE_NAME, contentFileMissingEventArgs.FileName); + Assert.Equal(LOCAL_TEXT_FILE_NAME, contentFileMissingEventArgs.FileName); Assert.Equal(TEXT_FILE_PATH, contentFileMissingEventArgs.FilePathInEpubArchive); Assert.Equal(TEXT_FILE_CONTENT_TYPE, contentFileMissingEventArgs.ContentType); Assert.Equal(TEXT_FILE_CONTENT_MIME_TYPE, contentFileMissingEventArgs.ContentMimeType); } - private EpubTextContentFileRef CreateTextContentFileRef() + [Fact(DisplayName = "ReadContent should throw InvalidOperationException for remote text content items")] + public void ReadContentForRemoteTextContentItemTest() + { + EpubTextContentFileRef epubTextContentFileRef = CreateRemoteTextContentFileRef(); + Assert.Throws(() => epubTextContentFileRef.ReadContent()); + } + + [Fact(DisplayName = "ReadContentAsync should throw InvalidOperationException for remote text content items")] + public async void ReadContentAsyncForRemoteTextContentItemTest() + { + EpubTextContentFileRef epubTextContentFileRef = CreateRemoteTextContentFileRef(); + await Assert.ThrowsAsync(() => epubTextContentFileRef.ReadContentAsync()); + } + + [Fact(DisplayName = "ReadContent should throw InvalidOperationException for remote byte content items")] + public void ReadContentForRemoteByteContentItemTest() + { + EpubByteContentFileRef epubByteContentFileRef = CreateRemoteByteContentFileRef(); + Assert.Throws(() => epubByteContentFileRef.ReadContent()); + } + + [Fact(DisplayName = "ReadContentAsync should throw InvalidOperationException for remote byte content items")] + public async void ReadContentAsyncForRemoteByteContentItemTest() + { + EpubByteContentFileRef epubByteContentFileRef = CreateRemoteByteContentFileRef(); + await Assert.ThrowsAsync(() => epubByteContentFileRef.ReadContentAsync()); + } + + [Fact(DisplayName = "GetContentStream should throw InvalidOperationException for remote content items")] + public void GetContentStreamForRemoteContentItemTest() + { + EpubTextContentFileRef epubTextContentFileRef = CreateRemoteTextContentFileRef(); + Assert.Throws(() => epubTextContentFileRef.GetContentStream()); + } + + private EpubTextContentFileRef CreateLocalTextContentFileRef() { TestZipFile testZipFile = new(); testZipFile.AddEntry(TEXT_FILE_PATH, TEXT_FILE_CONTENT); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - return new(epubBookRef, TEXT_FILE_NAME, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + return new(epubBookRef, LOCAL_TEXT_FILE_NAME, EpubContentLocation.LOCAL, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); } - private EpubByteContentFileRef CreateByteContentFileRef() + private EpubByteContentFileRef CreateLocalByteContentFileRef() { TestZipFile testZipFile = new(); testZipFile.AddEntry(BYTE_FILE_PATH, BYTE_FILE_CONTENT); EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); - return new(epubBookRef, BYTE_FILE_NAME, BYTE_FILE_CONTENT_TYPE, BYTE_FILE_CONTENT_MIME_TYPE); + return new(epubBookRef, LOCAL_BYTE_FILE_NAME, EpubContentLocation.LOCAL, BYTE_FILE_CONTENT_TYPE, BYTE_FILE_CONTENT_MIME_TYPE); + } + + private EpubTextContentFileRef CreateRemoteTextContentFileRef() + { + TestZipFile testZipFile = new(); + EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); + return new(epubBookRef, REMOTE_TEXT_CONTENT_HREF, EpubContentLocation.REMOTE, TEXT_FILE_CONTENT_TYPE, TEXT_FILE_CONTENT_MIME_TYPE); + } + + private EpubByteContentFileRef CreateRemoteByteContentFileRef() + { + TestZipFile testZipFile = new(); + EpubBookRef epubBookRef = CreateEpubBookRef(testZipFile); + return new(epubBookRef, REMOTE_BYTE_CONTENT_HREF, EpubContentLocation.REMOTE, BYTE_FILE_CONTENT_TYPE, BYTE_FILE_CONTENT_MIME_TYPE); } private EpubBookRef CreateEpubBookRef(TestZipFile testZipFile) diff --git a/Source/VersOne.Epub.Test/Unit/Root/EpubReaderTests.cs b/Source/VersOne.Epub.Test/Unit/Root/EpubReaderTests.cs index e5139c2..d2d708b 100644 --- a/Source/VersOne.Epub.Test/Unit/Root/EpubReaderTests.cs +++ b/Source/VersOne.Epub.Test/Unit/Root/EpubReaderTests.cs @@ -47,6 +47,8 @@ public class EpubReaderTests private const string AUDIO_MPEG_CONTENT_MIME_TYPE = "audio/mpeg"; private const string AUDIO_FILE_NAME = "audio.mp3"; private const string AUDIO_FILE_PATH = $"{CONTENT_DIRECTORY_PATH}/{AUDIO_FILE_NAME}"; + private const string REMOTE_TEXT_CONTENT_ITEM_HREF = "https://example.com/books/123/test.html"; + private const string REMOTE_BYTE_CONTENT_ITEM_HREF = "https://example.com/books/123/image.jpg"; private const string BOOK_TITLE = "Test title"; private const string BOOK_AUTHOR = "John Doe"; private const string BOOK_DESCRIPTION = "Test description"; @@ -85,7 +87,7 @@ public class EpubReaderTests {BOOK_TITLE} {BOOK_AUTHOR} {BOOK_DESCRIPTION} - + @@ -96,6 +98,8 @@ public class EpubReaderTests + + @@ -406,7 +410,7 @@ private EpubBookRef CreateMinimalExpectedEpubBookRef(TestZipFile epubFile, strin Cover = null } }; - EpubTextContentFileRef navFileRef = new(result, NAV_FILE_NAME, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); + EpubTextContentFileRef navFileRef = new(result, NAV_FILE_NAME, EpubContentLocation.LOCAL, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); result.Content.Html[NAV_FILE_NAME] = navFileRef; result.Content.AllFiles[NAV_FILE_NAME] = navFileRef; result.Content.NavigationHtmlFile = navFileRef; @@ -419,6 +423,8 @@ private EpubBook CreateMinimalExpectedEpubBook(string epubFilePath) { FileName = NAV_FILE_NAME, FilePathInEpubArchive = NAV_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = HTML_CONTENT_TYPE, ContentMimeType = HTML_CONTENT_MIME_TYPE, Content = MINIMAL_NAV_FILE_CONTENT @@ -528,18 +534,20 @@ private EpubBookRef CreateFullExpectedEpubBookRef(TestZipFile epubFile, string e Description = BOOK_DESCRIPTION, Schema = CreateFullExpectedEpubSchema() }; - EpubTextContentFileRef chapter1FileRef = new(result, CHAPTER1_FILE_NAME, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); - EpubTextContentFileRef chapter2FileRef = new(result, CHAPTER2_FILE_NAME, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); - EpubTextContentFileRef styles1FileRef = new(result, STYLES1_FILE_NAME, CSS_CONTENT_TYPE, CSS_CONTENT_MIME_TYPE); - EpubTextContentFileRef styles2FileRef = new(result, STYLES2_FILE_NAME, CSS_CONTENT_TYPE, CSS_CONTENT_MIME_TYPE); - EpubByteContentFileRef image1FileRef = new(result, IMAGE1_FILE_NAME, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); - EpubByteContentFileRef image2FileRef = new(result, IMAGE2_FILE_NAME, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); - EpubByteContentFileRef font1FileRef = new(result, FONT1_FILE_NAME, FONT_CONTENT_TYPE, FONT_CONTENT_MIME_TYPE); - EpubByteContentFileRef font2FileRef = new(result, FONT2_FILE_NAME, FONT_CONTENT_TYPE, FONT_CONTENT_MIME_TYPE); - EpubByteContentFileRef audioFileRef = new(result, AUDIO_FILE_NAME, OTHER_CONTENT_TYPE, AUDIO_MPEG_CONTENT_MIME_TYPE); - EpubTextContentFileRef navFileRef = new(result, NAV_FILE_NAME, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); - EpubByteContentFileRef coverFileRef = new(result, COVER_FILE_NAME, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); - EpubTextContentFileRef ncxFileRef = new(result, NCX_FILE_NAME, NCX_CONTENT_TYPE, NCX_CONTENT_MIME_TYPE); + EpubTextContentFileRef chapter1FileRef = new(result, CHAPTER1_FILE_NAME, EpubContentLocation.LOCAL, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); + EpubTextContentFileRef chapter2FileRef = new(result, CHAPTER2_FILE_NAME, EpubContentLocation.LOCAL, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); + EpubTextContentFileRef styles1FileRef = new(result, STYLES1_FILE_NAME, EpubContentLocation.LOCAL, CSS_CONTENT_TYPE, CSS_CONTENT_MIME_TYPE); + EpubTextContentFileRef styles2FileRef = new(result, STYLES2_FILE_NAME, EpubContentLocation.LOCAL, CSS_CONTENT_TYPE, CSS_CONTENT_MIME_TYPE); + EpubByteContentFileRef image1FileRef = new(result, IMAGE1_FILE_NAME, EpubContentLocation.LOCAL, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); + EpubByteContentFileRef image2FileRef = new(result, IMAGE2_FILE_NAME, EpubContentLocation.LOCAL, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); + EpubByteContentFileRef font1FileRef = new(result, FONT1_FILE_NAME, EpubContentLocation.LOCAL, FONT_CONTENT_TYPE, FONT_CONTENT_MIME_TYPE); + EpubByteContentFileRef font2FileRef = new(result, FONT2_FILE_NAME, EpubContentLocation.LOCAL, FONT_CONTENT_TYPE, FONT_CONTENT_MIME_TYPE); + EpubByteContentFileRef audioFileRef = new(result, AUDIO_FILE_NAME, EpubContentLocation.LOCAL, OTHER_CONTENT_TYPE, AUDIO_MPEG_CONTENT_MIME_TYPE); + EpubTextContentFileRef remoteTextContentItemRef = new(result, REMOTE_TEXT_CONTENT_ITEM_HREF, EpubContentLocation.REMOTE, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); + EpubByteContentFileRef remoteByteContentItemRef = new(result, REMOTE_BYTE_CONTENT_ITEM_HREF, EpubContentLocation.REMOTE, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); + EpubTextContentFileRef navFileRef = new(result, NAV_FILE_NAME, EpubContentLocation.LOCAL, HTML_CONTENT_TYPE, HTML_CONTENT_MIME_TYPE); + EpubByteContentFileRef coverFileRef = new(result, COVER_FILE_NAME, EpubContentLocation.LOCAL, IMAGE_CONTENT_TYPE, IMAGE_CONTENT_MIME_TYPE); + EpubTextContentFileRef ncxFileRef = new(result, NCX_FILE_NAME, EpubContentLocation.LOCAL, NCX_CONTENT_TYPE, NCX_CONTENT_MIME_TYPE); result.Content = new EpubContentRef() { Html = new Dictionary() @@ -552,6 +560,10 @@ private EpubBookRef CreateFullExpectedEpubBookRef(TestZipFile epubFile, string e CHAPTER2_FILE_NAME, chapter2FileRef }, + { + REMOTE_TEXT_CONTENT_ITEM_HREF, + remoteTextContentItemRef + }, { NAV_FILE_NAME, navFileRef @@ -578,6 +590,10 @@ private EpubBookRef CreateFullExpectedEpubBookRef(TestZipFile epubFile, string e IMAGE2_FILE_NAME, image2FileRef }, + { + REMOTE_BYTE_CONTENT_ITEM_HREF, + remoteByteContentItemRef + }, { COVER_FILE_NAME, coverFileRef @@ -632,6 +648,14 @@ private EpubBookRef CreateFullExpectedEpubBookRef(TestZipFile epubFile, string e AUDIO_FILE_NAME, audioFileRef }, + { + REMOTE_TEXT_CONTENT_ITEM_HREF, + remoteTextContentItemRef + }, + { + REMOTE_BYTE_CONTENT_ITEM_HREF, + remoteByteContentItemRef + }, { NAV_FILE_NAME, navFileRef @@ -657,6 +681,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = CHAPTER1_FILE_NAME, FilePathInEpubArchive = CHAPTER1_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = HTML_CONTENT_TYPE, ContentMimeType = HTML_CONTENT_MIME_TYPE, Content = CHAPTER1_FILE_CONTENT @@ -665,6 +691,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = CHAPTER2_FILE_NAME, FilePathInEpubArchive = CHAPTER2_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = HTML_CONTENT_TYPE, ContentMimeType = HTML_CONTENT_MIME_TYPE, Content = CHAPTER2_FILE_CONTENT @@ -673,6 +701,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = STYLES1_FILE_NAME, FilePathInEpubArchive = STYLES1_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = CSS_CONTENT_TYPE, ContentMimeType = CSS_CONTENT_MIME_TYPE, Content = STYLES1_FILE_CONTENT @@ -681,6 +711,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = STYLES2_FILE_NAME, FilePathInEpubArchive = STYLES2_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = CSS_CONTENT_TYPE, ContentMimeType = CSS_CONTENT_MIME_TYPE, Content = STYLES2_FILE_CONTENT @@ -689,6 +721,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = IMAGE1_FILE_NAME, FilePathInEpubArchive = IMAGE1_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = IMAGE_CONTENT_TYPE, ContentMimeType = IMAGE_CONTENT_MIME_TYPE, Content = IMAGE1_FILE_CONTENT @@ -697,6 +731,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = IMAGE2_FILE_NAME, FilePathInEpubArchive = IMAGE2_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = IMAGE_CONTENT_TYPE, ContentMimeType = IMAGE_CONTENT_MIME_TYPE, Content = IMAGE2_FILE_CONTENT @@ -705,6 +741,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = FONT1_FILE_NAME, FilePathInEpubArchive = FONT1_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = FONT_CONTENT_TYPE, ContentMimeType = FONT_CONTENT_MIME_TYPE, Content = FONT1_FILE_CONTENT @@ -713,6 +751,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = FONT2_FILE_NAME, FilePathInEpubArchive = FONT2_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = FONT_CONTENT_TYPE, ContentMimeType = FONT_CONTENT_MIME_TYPE, Content = FONT2_FILE_CONTENT @@ -721,14 +761,38 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = AUDIO_FILE_NAME, FilePathInEpubArchive = AUDIO_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = OTHER_CONTENT_TYPE, ContentMimeType = AUDIO_MPEG_CONTENT_MIME_TYPE, Content = AUDIO_FILE_CONTENT }; + EpubTextContentFile remoteTextContentItem = new() + { + FileName = null, + FilePathInEpubArchive = null, + Href = REMOTE_TEXT_CONTENT_ITEM_HREF, + ContentLocation = EpubContentLocation.REMOTE, + ContentType = HTML_CONTENT_TYPE, + ContentMimeType = HTML_CONTENT_MIME_TYPE, + Content = null + }; + EpubByteContentFile remoteByteContentItem = new() + { + FileName = null, + FilePathInEpubArchive = null, + Href = REMOTE_BYTE_CONTENT_ITEM_HREF, + ContentLocation = EpubContentLocation.REMOTE, + ContentType = IMAGE_CONTENT_TYPE, + ContentMimeType = IMAGE_CONTENT_MIME_TYPE, + Content = null + }; EpubTextContentFile navFile = new() { FileName = NAV_FILE_NAME, FilePathInEpubArchive = NAV_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = HTML_CONTENT_TYPE, ContentMimeType = HTML_CONTENT_MIME_TYPE, Content = FULL_NAV_FILE_CONTENT @@ -737,6 +801,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = COVER_FILE_NAME, FilePathInEpubArchive = COVER_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = IMAGE_CONTENT_TYPE, ContentMimeType = IMAGE_CONTENT_MIME_TYPE, Content = COVER_FILE_CONTENT @@ -745,6 +811,8 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) { FileName = NCX_FILE_NAME, FilePathInEpubArchive = NCX_FILE_PATH, + Href = null, + ContentLocation = EpubContentLocation.LOCAL, ContentType = NCX_CONTENT_TYPE, ContentMimeType = NCX_CONTENT_MIME_TYPE, Content = NCX_FILE_CONTENT @@ -792,6 +860,10 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) CHAPTER2_FILE_NAME, chapter2File }, + { + REMOTE_TEXT_CONTENT_ITEM_HREF, + remoteTextContentItem + }, { NAV_FILE_NAME, navFile @@ -818,6 +890,10 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) IMAGE2_FILE_NAME, image2File }, + { + REMOTE_BYTE_CONTENT_ITEM_HREF, + remoteByteContentItem + }, { COVER_FILE_NAME, coverFile @@ -872,6 +948,14 @@ private EpubBook CreateFullExpectedEpubBook(string epubFilePath) AUDIO_FILE_NAME, audioFile }, + { + REMOTE_TEXT_CONTENT_ITEM_HREF, + remoteTextContentItem + }, + { + REMOTE_BYTE_CONTENT_ITEM_HREF, + remoteByteContentItem + }, { NAV_FILE_NAME, navFile @@ -986,6 +1070,18 @@ private EpubSchema CreateFullExpectedEpubSchema() MediaType = AUDIO_MPEG_CONTENT_MIME_TYPE }, new EpubManifestItem() + { + Id = "item-10", + Href = REMOTE_TEXT_CONTENT_ITEM_HREF, + MediaType = HTML_CONTENT_MIME_TYPE + }, + new EpubManifestItem() + { + Id = "item-11", + Href = REMOTE_BYTE_CONTENT_ITEM_HREF, + MediaType = IMAGE_CONTENT_MIME_TYPE + }, + new EpubManifestItem() { Id = "item-toc", Href = NAV_FILE_NAME, diff --git a/Source/VersOne.Epub/Entities/EpubByteContentFile.cs b/Source/VersOne.Epub/Entities/EpubByteContentFile.cs index 02429fc..3276c5c 100644 --- a/Source/VersOne.Epub/Entities/EpubByteContentFile.cs +++ b/Source/VersOne.Epub/Entities/EpubByteContentFile.cs @@ -7,7 +7,7 @@ public class EpubByteContentFile : EpubContentFile { /// - /// Gets the content of the file. + /// Gets the content of the file. Returns null if is . /// public byte[] Content { get; internal set; } } diff --git a/Source/VersOne.Epub/Entities/EpubContent.cs b/Source/VersOne.Epub/Entities/EpubContent.cs index 6ff7d7c..0874bbf 100644 --- a/Source/VersOne.Epub/Entities/EpubContent.cs +++ b/Source/VersOne.Epub/Entities/EpubContent.cs @@ -18,27 +18,27 @@ public class EpubContent public EpubTextContentFile NavigationHtmlFile { get; internal set; } /// - /// Gets all HTML/XHTML content files of the EPUB book keyed by their relative file paths. + /// Gets all HTML/XHTML content files of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Html { get; internal set; } /// - /// Gets all CSS files of the EPUB book keyed by their relative file paths. + /// Gets all CSS files of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Css { get; internal set; } /// - /// Gets all image files of the EPUB book keyed by their relative file paths. + /// Gets all image files of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Images { get; internal set; } /// - /// Gets all embedded font files of the EPUB book keyed by their relative file paths. + /// Gets all embedded font files of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Fonts { get; internal set; } /// - /// Gets all content files of the EPUB book keyed by their relative file paths. + /// Gets all content files of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary AllFiles { get; internal set; } } diff --git a/Source/VersOne.Epub/Entities/EpubContentFile.cs b/Source/VersOne.Epub/Entities/EpubContentFile.cs index 855539b..0edbd5f 100644 --- a/Source/VersOne.Epub/Entities/EpubContentFile.cs +++ b/Source/VersOne.Epub/Entities/EpubContentFile.cs @@ -8,14 +8,27 @@ public abstract class EpubContentFile { /// /// Gets the relative file path of the content file (as it is specified in the EPUB manifest). + /// Returns null if is . /// public string FileName { get; internal set; } /// /// Gets the absolute file path of the content file in the EPUB archive. + /// Returns null if is . /// public string FilePathInEpubArchive { get; internal set; } + /// + /// Gets the absolute URI of the content item (as it is specified in the EPUB manifest). + /// Returns null if is . + /// + public string Href { get; internal set; } + + /// + /// Gets the location of the content item (local or remote). + /// + public EpubContentLocation ContentLocation { get; internal set; } + /// /// Gets the type of the content of the file. /// diff --git a/Source/VersOne.Epub/Entities/EpubContentLocation.cs b/Source/VersOne.Epub/Entities/EpubContentLocation.cs new file mode 100644 index 0000000..02234af --- /dev/null +++ b/Source/VersOne.Epub/Entities/EpubContentLocation.cs @@ -0,0 +1,18 @@ +namespace VersOne.Epub +{ + /// + /// The location of a single EPUB content item (e.g. a chapter or an image). + /// + public enum EpubContentLocation + { + /// + /// Content item is located inside the EPUB file. + /// + LOCAL = 1, + + /// + /// Content item is located outside the EPUB file and available via absolute URI. + /// + REMOTE + } +} diff --git a/Source/VersOne.Epub/Entities/EpubTextContentFile.cs b/Source/VersOne.Epub/Entities/EpubTextContentFile.cs index 910b595..08ab1ca 100644 --- a/Source/VersOne.Epub/Entities/EpubTextContentFile.cs +++ b/Source/VersOne.Epub/Entities/EpubTextContentFile.cs @@ -7,7 +7,7 @@ public class EpubTextContentFile : EpubContentFile { /// - /// Gets the content of the file. + /// Gets the content of the file. Returns null if is . /// public string Content { get; internal set; } } diff --git a/Source/VersOne.Epub/EpubReader.cs b/Source/VersOne.Epub/EpubReader.cs index 20213ae..4848d0f 100644 --- a/Source/VersOne.Epub/EpubReader.cs +++ b/Source/VersOne.Epub/EpubReader.cs @@ -6,6 +6,7 @@ using VersOne.Epub.Environment; using VersOne.Epub.Internal; using VersOne.Epub.Options; +using VersOne.Epub.Utils; namespace VersOne.Epub { @@ -24,7 +25,7 @@ public static class EpubReader /// EPUB book reference. This object holds a handle to the EPUB file. public static EpubBookRef OpenBook(string filePath, EpubReaderOptions epubReaderOptions = null) { - return ExecuteAndUnwrapAggregateException(() => OpenBookAsync(filePath, epubReaderOptions)); + return OpenBookAsync(filePath, epubReaderOptions).ExecuteAndUnwrapAggregateException(); } /// @@ -35,7 +36,7 @@ public static EpubBookRef OpenBook(string filePath, EpubReaderOptions epubReader /// EPUB book reference. This object holds a handle to the EPUB file. public static EpubBookRef OpenBook(Stream stream, EpubReaderOptions epubReaderOptions = null) { - return ExecuteAndUnwrapAggregateException(() => OpenBookAsync(stream, epubReaderOptions)); + return OpenBookAsync(stream, epubReaderOptions).ExecuteAndUnwrapAggregateException(); } /// @@ -72,7 +73,7 @@ public static Task OpenBookAsync(Stream stream, EpubReaderOptions e /// EPUB book with all its content. This object does not retain a handle to the EPUB file. public static EpubBook ReadBook(string filePath, EpubReaderOptions epubReaderOptions = null) { - return ExecuteAndUnwrapAggregateException(() => ReadBookAsync(filePath, epubReaderOptions)); + return ReadBookAsync(filePath, epubReaderOptions).ExecuteAndUnwrapAggregateException(); } /// @@ -83,7 +84,7 @@ public static EpubBook ReadBook(string filePath, EpubReaderOptions epubReaderOpt /// EPUB book with all its content. This object does not retain a handle to the EPUB file. public static EpubBook ReadBook(Stream stream, EpubReaderOptions epubReaderOptions = null) { - return ExecuteAndUnwrapAggregateException(() => ReadBookAsync(stream, epubReaderOptions)); + return ReadBookAsync(stream, epubReaderOptions).ExecuteAndUnwrapAggregateException(); } /// @@ -234,10 +235,19 @@ private static async Task ReadTextContentFile(EpubContentFi { FileName = contentFileRef.FileName, FilePathInEpubArchive = contentFileRef.FilePathInEpubArchive, + Href = contentFileRef.Href, + ContentLocation = contentFileRef.ContentLocation, ContentType = contentFileRef.ContentType, ContentMimeType = contentFileRef.ContentMimeType }; - result.Content = await contentFileRef.ReadContentAsTextAsync().ConfigureAwait(false); + if (result.ContentLocation == EpubContentLocation.LOCAL) + { + result.Content = await contentFileRef.ReadContentAsTextAsync().ConfigureAwait(false); + } + else + { + result.Content = null; + } return result; } @@ -247,10 +257,19 @@ private static async Task ReadByteContentFile(EpubContentFi { FileName = contentFileRef.FileName, FilePathInEpubArchive = contentFileRef.FilePathInEpubArchive, + Href = contentFileRef.Href, + ContentLocation = contentFileRef.ContentLocation, ContentType = contentFileRef.ContentType, ContentMimeType = contentFileRef.ContentMimeType }; - result.Content = await contentFileRef.ReadContentAsBytesAsync().ConfigureAwait(false); + if (result.ContentLocation == EpubContentLocation.LOCAL) + { + result.Content = await contentFileRef.ReadContentAsBytesAsync().ConfigureAwait(false); + } + else + { + result.Content = null; + } return result; } @@ -278,17 +297,5 @@ private static List ReadNavigation(EpubBook epubBook, List(Func> asyncOperation) - { - try - { - return asyncOperation().Result; - } - catch (AggregateException aggregateException) - { - throw aggregateException.InnerException; - } - } } } diff --git a/Source/VersOne.Epub/Readers/ContentReader.cs b/Source/VersOne.Epub/Readers/ContentReader.cs index df3b10b..568d827 100644 --- a/Source/VersOne.Epub/Readers/ContentReader.cs +++ b/Source/VersOne.Epub/Readers/ContentReader.cs @@ -18,7 +18,8 @@ public static EpubContentRef ParseContentMap(EpubBookRef bookRef, ContentReaderO }; foreach (EpubManifestItem manifestItem in bookRef.Schema.Package.Manifest.Items) { - string fileName = manifestItem.Href; + string href = manifestItem.Href; + EpubContentLocation contentLocation = href.Contains("://") ? EpubContentLocation.REMOTE : EpubContentLocation.LOCAL; string contentMimeType = manifestItem.MediaType; EpubContentType contentType = GetContentTypeByContentMimeType(contentMimeType); switch (contentType) @@ -30,38 +31,40 @@ public static EpubContentRef ParseContentMap(EpubBookRef bookRef, ContentReaderO case EpubContentType.XML: case EpubContentType.DTBOOK: case EpubContentType.DTBOOK_NCX: - EpubTextContentFileRef epubTextContentFile = new EpubTextContentFileRef(bookRef, fileName, contentType, contentMimeType, contentReaderOptions); + EpubTextContentFileRef epubTextContentFile = + new EpubTextContentFileRef(bookRef, href, contentLocation, contentType, contentMimeType, contentReaderOptions); switch (contentType) { case EpubContentType.XHTML_1_1: - result.Html[fileName] = epubTextContentFile; + result.Html[href] = epubTextContentFile; if (result.NavigationHtmlFile == null && manifestItem.Properties != null && manifestItem.Properties.Contains(EpubManifestProperty.NAV)) { result.NavigationHtmlFile = epubTextContentFile; } break; case EpubContentType.CSS: - result.Css[fileName] = epubTextContentFile; + result.Css[href] = epubTextContentFile; break; } - result.AllFiles[fileName] = epubTextContentFile; + result.AllFiles[href] = epubTextContentFile; break; default: - EpubByteContentFileRef epubByteContentFile = new EpubByteContentFileRef(bookRef, fileName, contentType, contentMimeType, contentReaderOptions); + EpubByteContentFileRef epubByteContentFile = + new EpubByteContentFileRef(bookRef, href, contentLocation, contentType, contentMimeType, contentReaderOptions); switch (contentType) { case EpubContentType.IMAGE_GIF: case EpubContentType.IMAGE_JPEG: case EpubContentType.IMAGE_PNG: case EpubContentType.IMAGE_SVG: - result.Images[fileName] = epubByteContentFile; + result.Images[href] = epubByteContentFile; break; case EpubContentType.FONT_TRUETYPE: case EpubContentType.FONT_OPENTYPE: - result.Fonts[fileName] = epubByteContentFile; + result.Fonts[href] = epubByteContentFile; break; } - result.AllFiles[fileName] = epubByteContentFile; + result.AllFiles[href] = epubByteContentFile; break; } } diff --git a/Source/VersOne.Epub/RefEntities/EpubByteContentFileRef.cs b/Source/VersOne.Epub/RefEntities/EpubByteContentFileRef.cs index d0a3a05..252c17d 100644 --- a/Source/VersOne.Epub/RefEntities/EpubByteContentFileRef.cs +++ b/Source/VersOne.Epub/RefEntities/EpubByteContentFileRef.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using VersOne.Epub.Options; namespace VersOne.Epub @@ -14,17 +15,20 @@ public class EpubByteContentFileRef : EpubContentFileRef /// and a MIME type of the file's content. /// /// EPUB book reference object which contains this content file reference. - /// Relative file path of the content file (as it is specified in the EPUB manifest). + /// Relative file path or absolute URI of the content item (as it is specified in the EPUB manifest). + /// Location of the content item (local or remote). /// The type of the content of the file. /// The MIME type of the content of the file. /// Optional content reader options determining how to handle missing content files. - public EpubByteContentFileRef(EpubBookRef epubBookRef, string fileName, EpubContentType contentType, string contentMimeType, ContentReaderOptions contentReaderOptions = null) - : base(epubBookRef, fileName, contentType, contentMimeType, contentReaderOptions) + public EpubByteContentFileRef(EpubBookRef epubBookRef, string href, EpubContentLocation contentLocation, EpubContentType contentType, string contentMimeType, + ContentReaderOptions contentReaderOptions = null) + : base(epubBookRef, href, contentLocation, contentType, contentMimeType, contentReaderOptions) { } /// /// Reads the whole content of the referenced file and returns it as a byte array. + /// Throws if is . /// /// Content of the referenced file. public byte[] ReadContent() @@ -34,6 +38,7 @@ public byte[] ReadContent() /// /// Asynchronously reads the whole content of the referenced file and returns it as a byte array. + /// Throws if is . /// /// A task that represents the asynchronous read operation. The value of the TResult parameter contains the content of the referenced file. public Task ReadContentAsync() diff --git a/Source/VersOne.Epub/RefEntities/EpubContentFileRef.cs b/Source/VersOne.Epub/RefEntities/EpubContentFileRef.cs index bab79d5..9f3488d 100644 --- a/Source/VersOne.Epub/RefEntities/EpubContentFileRef.cs +++ b/Source/VersOne.Epub/RefEntities/EpubContentFileRef.cs @@ -4,6 +4,7 @@ using VersOne.Epub.Environment; using VersOne.Epub.Internal; using VersOne.Epub.Options; +using VersOne.Epub.Utils; namespace VersOne.Epub { @@ -22,15 +23,28 @@ public abstract class EpubContentFileRef /// and a MIME type of the file's content. /// /// EPUB book reference object which contains this content file reference. - /// Relative file path of the content file (as it is specified in the EPUB manifest). + /// Relative file path or absolute URI of the content item (as it is specified in the EPUB manifest). + /// Location of the content item (local or remote). /// The type of the content of the file. /// The MIME type of the content of the file. /// Optional content reader options determining how to handle missing content files. - protected EpubContentFileRef(EpubBookRef epubBookRef, string fileName, EpubContentType contentType, string contentMimeType, ContentReaderOptions contentReaderOptions = null) + protected EpubContentFileRef(EpubBookRef epubBookRef, string href, EpubContentLocation contentLocation, EpubContentType contentType, string contentMimeType, + ContentReaderOptions contentReaderOptions = null) { this.epubBookRef = epubBookRef; - FileName = fileName; - FilePathInEpubArchive = ZipPathUtils.Combine(epubBookRef.Schema.ContentDirectoryPath, FileName); + ContentLocation = contentLocation; + if (contentLocation == EpubContentLocation.LOCAL) + { + FileName = href; + FilePathInEpubArchive = ZipPathUtils.Combine(epubBookRef.Schema.ContentDirectoryPath, FileName); + Href = null; + } + else + { + FileName = null; + FilePathInEpubArchive = null; + Href = href; + } ContentType = contentType; ContentMimeType = contentMimeType; this.contentReaderOptions = contentReaderOptions; @@ -39,14 +53,27 @@ protected EpubContentFileRef(EpubBookRef epubBookRef, string fileName, EpubConte /// /// Gets the relative file path of the content file (as it is specified in the EPUB manifest). + /// Returns null if is . /// public string FileName { get; } /// /// Gets the absolute file path of the content file in the EPUB archive. + /// Returns null if is . /// public string FilePathInEpubArchive { get; } + /// + /// Gets the absolute URI of the content item (as it is specified in the EPUB manifest). + /// Returns null if is . + /// + public string Href { get; internal set; } + + /// + /// Gets the location of the content item (local or remote). + /// + public EpubContentLocation ContentLocation { get; internal set; } + /// /// Gets the type of the content of the file. /// @@ -59,15 +86,17 @@ protected EpubContentFileRef(EpubBookRef epubBookRef, string fileName, EpubConte /// /// Reads the whole content of the referenced file and returns it as a byte array. + /// Throws if is . /// /// Content of the referenced file. public byte[] ReadContentAsBytes() { - return ReadContentAsBytesAsync().Result; + return ReadContentAsBytesAsync().ExecuteAndUnwrapAggregateException(); } /// /// Asynchronously reads the whole content of the referenced file and returns it as a byte array. + /// Throws if is . /// /// A task that represents the asynchronous read operation. The value of the TResult parameter contains the content of the referenced file. public async Task ReadContentAsBytesAsync() @@ -84,15 +113,17 @@ public async Task ReadContentAsBytesAsync() /// /// Reads the whole content of the referenced file and returns it as a string. + /// Throws if is . /// /// Content of the referenced file. public string ReadContentAsText() { - return ReadContentAsTextAsync().Result; + return ReadContentAsTextAsync().ExecuteAndUnwrapAggregateException(); } /// /// Asynchronously reads the whole content of the referenced file and returns it as a string. + /// Throws if is . /// /// A task that represents the asynchronous read operation. The value of the TResult parameter contains the content of the referenced file. public async Task ReadContentAsTextAsync() @@ -106,6 +137,7 @@ public async Task ReadContentAsTextAsync() /// /// Opens the referenced file and returns a to access its content. + /// Throws if is . /// /// A to access the referenced file's content. public Stream GetContentStream() @@ -115,6 +147,10 @@ public Stream GetContentStream() private IZipFileEntry GetContentFileEntry() { + if (ContentLocation == EpubContentLocation.REMOTE) + { + throw new InvalidOperationException("Content cannot be retrieved for remote content items."); + } if (replacementContentFileEntry != null) { return replacementContentFileEntry; diff --git a/Source/VersOne.Epub/RefEntities/EpubContentRef.cs b/Source/VersOne.Epub/RefEntities/EpubContentRef.cs index e6f9134..6308a0c 100644 --- a/Source/VersOne.Epub/RefEntities/EpubContentRef.cs +++ b/Source/VersOne.Epub/RefEntities/EpubContentRef.cs @@ -18,27 +18,27 @@ public class EpubContentRef public EpubTextContentFileRef NavigationHtmlFile { get; internal set; } /// - /// Gets all HTML/XHTML content file references of the EPUB book keyed by their relative file paths. + /// Gets all HTML/XHTML content file references of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Html { get; internal set; } /// - /// Gets all CSS file references of the EPUB book keyed by their relative file paths. + /// Gets all CSS file references of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Css { get; internal set; } /// - /// Gets all image file references of the EPUB book keyed by their relative file paths. + /// Gets all image file references of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Images { get; internal set; } /// - /// Gets all embedded font file references of the EPUB book keyed by their relative file paths. + /// Gets all embedded font file references of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary Fonts { get; internal set; } /// - /// Gets all content file references of the EPUB book keyed by their relative file paths. + /// Gets all content file references of the EPUB book keyed by their relative file paths (for local content) or absolute URIs (for remote content). /// public Dictionary AllFiles { get; internal set; } } diff --git a/Source/VersOne.Epub/RefEntities/EpubTextContentFileRef.cs b/Source/VersOne.Epub/RefEntities/EpubTextContentFileRef.cs index 31c0a04..e0069c4 100644 --- a/Source/VersOne.Epub/RefEntities/EpubTextContentFileRef.cs +++ b/Source/VersOne.Epub/RefEntities/EpubTextContentFileRef.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using VersOne.Epub.Options; namespace VersOne.Epub @@ -14,17 +15,20 @@ public class EpubTextContentFileRef : EpubContentFileRef /// and a MIME type of the file's content. /// /// EPUB book reference object which contains this content file reference. - /// Relative file path of the content file (as it is specified in the EPUB manifest). + /// Relative file path or absolute URI of the content item (as it is specified in the EPUB manifest). + /// Location of the content item (local or remote). /// The type of the content of the file. /// The MIME type of the content of the file. /// Optional content reader options determining how to handle missing content files. - public EpubTextContentFileRef(EpubBookRef epubBookRef, string fileName, EpubContentType contentType, string contentMimeType, ContentReaderOptions contentReaderOptions = null) - : base(epubBookRef, fileName, contentType, contentMimeType, contentReaderOptions) + public EpubTextContentFileRef(EpubBookRef epubBookRef, string href, EpubContentLocation contentLocation, EpubContentType contentType, string contentMimeType, + ContentReaderOptions contentReaderOptions = null) + : base(epubBookRef, href, contentLocation, contentType, contentMimeType, contentReaderOptions) { } /// /// Reads the whole content of the referenced file and returns it as a string. + /// Throws if is . /// /// Content of the referenced file. public string ReadContent() @@ -34,6 +38,7 @@ public string ReadContent() /// /// Asynchronously reads the whole content of the referenced file and returns it as a string. + /// Throws if is . /// /// A task that represents the asynchronous read operation. The value of the TResult parameter contains the content of the referenced file. public Task ReadContentAsync() diff --git a/Source/VersOne.Epub/Utils/TaskExtensionMethods.cs b/Source/VersOne.Epub/Utils/TaskExtensionMethods.cs new file mode 100644 index 0000000..5b402f6 --- /dev/null +++ b/Source/VersOne.Epub/Utils/TaskExtensionMethods.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace VersOne.Epub.Utils +{ + internal static class TaskExtensionMethods + { + public static T ExecuteAndUnwrapAggregateException(this Task task) + { + try + { + return task.Result; + } + catch (AggregateException aggregateException) + { + throw aggregateException.InnerException; + } + } + } +}