Skip to content

Commit

Permalink
Implemented EpubChapter.Previous / Next.
Browse files Browse the repository at this point in the history
  • Loading branch information
asido committed May 6, 2018
1 parent 5c8091e commit ebf7118
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 92 deletions.
34 changes: 34 additions & 0 deletions EpubSharp.Tests/EpubReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ public void ReadIOSHackersHandbookTest()
{
var book = EpubReader.Read(Cwd.Combine(@"Samples/epub-assorted/iOS Hackers Handbook.epub"));
book.TableOfContents.Should().HaveCount(14);
book.TableOfContents.SelectMany(e => e.SubChapters).Concat(book.TableOfContents).Should().HaveCount(78);
book.TableOfContents[0].AbsolutePath.Should().Be("/OEBPS/9781118240755cover.xhtml");
book.TableOfContents[1].AbsolutePath.Should().Be("/OEBPS/9781118240755c01.xhtml");
book.TableOfContents[1].SubChapters.Should().HaveCount(6);
Expand All @@ -320,5 +321,38 @@ public void SetsChapterParents()
chapter.SubChapters.All(e => e.Parent == chapter).Should().BeTrue();
}
}

[Fact]
public void SetsChapterPreviousNext()
{
var book = EpubReader.Read(Cwd.Combine(@"Samples/epub-assorted/iOS Hackers Handbook.epub"));

EpubChapter previousChapter = null;
var currentChapter = book.TableOfContents[0];
currentChapter.Previous.Should().Be(previousChapter);

for (var i = 1; i <= 77; ++i)
{
previousChapter = currentChapter;
currentChapter = currentChapter.Next;

previousChapter.Next.Should().Be(currentChapter);
currentChapter.Previous.Should().Be(previousChapter);
}

EpubChapter nextChapter = null;
currentChapter.Next.Should().Be(nextChapter);

for (var i = 1; i <= 77; ++i)
{
nextChapter = currentChapter;
currentChapter = currentChapter.Previous;

currentChapter.Next.Should().Be(nextChapter);
nextChapter.Previous.Should().Be(currentChapter);
}

currentChapter.Previous.Should().BeNull();
}
}
}
2 changes: 1 addition & 1 deletion EpubSharp.Tests/EpubTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ private void AssertContentFile(EpubFile expected, EpubFile actual)

private void AssertChapter(EpubChapter expected, EpubChapter actual)
{
Assert.Equal(expected.FileName, actual.FileName);
Assert.Equal(expected.RelativePath, actual.RelativePath);
Assert.Equal(expected.HashLocation, actual.HashLocation);
Assert.Equal(expected.Title, actual.Title);

Expand Down
2 changes: 1 addition & 1 deletion EpubSharp.Tests/EpubWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void CanAddChapterTest()
for (var i = 0; i < chapters.Length; ++i)
{
Assert.Equal(chapters[i].Title, epub.TableOfContents[i].Title);
Assert.Equal(chapters[i].FileName, epub.TableOfContents[i].FileName);
Assert.Equal(chapters[i].RelativePath, epub.TableOfContents[i].RelativePath);
Assert.Equal(chapters[i].HashLocation, epub.TableOfContents[i].HashLocation);
Assert.Equal(0, chapters[i].SubChapters.Count);
Assert.Equal(0, epub.TableOfContents[i].SubChapters.Count);
Expand Down
5 changes: 4 additions & 1 deletion EpubSharp/EpubBook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,13 @@ public class EpubChapter
{
public string Id { get; set; }
public string AbsolutePath { get; set; }
public string FileName { get; set; }
public string RelativePath { get; set; }
public string HashLocation { get; set; }
public string Title { get; set; }

public EpubChapter Parent { get; set; }
public EpubChapter Previous { get; set; }
public EpubChapter Next { get; set; }
public IList<EpubChapter> SubChapters { get; set; } = new List<EpubChapter>();

public override string ToString()
Expand Down
176 changes: 97 additions & 79 deletions EpubSharp/EpubReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace EpubSharp
public static class EpubReader
{
public static EpubBook Read(string filePath, Encoding encoding = null)
{
{
if (filePath == null) throw new ArgumentNullException(nameof(filePath));
if (encoding == null) encoding = Constants.DefaultEncoding;

Expand All @@ -35,7 +35,7 @@ public static EpubBook Read(Stream stream, bool leaveOpen, Encoding encoding = n
{
if (stream == null) throw new ArgumentNullException(nameof(stream));
if (encoding == null) encoding = Constants.DefaultEncoding;

using (var archive = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen, encoding))
{
var format = new EpubFormat { Ocf = OcfReader.Read(archive.LoadXml(Constants.OcfPath)) };
Expand All @@ -47,23 +47,23 @@ public static EpubBook Read(Stream stream, bool leaveOpen, Encoding encoding = n
{
throw new EpubParseException("Epub OCF doesn't specify a root file.");
}

format.Opf = OpfReader.Read(archive.LoadXml(format.Paths.OpfAbsolutePath));

var navPath = format.Opf.FindNavPath();
if (navPath != null)
{
format.Paths.NavAbsolutePath = navPath.ToAbsolutePath(format.Paths.OpfAbsolutePath);
format.Nav = NavReader.Read(archive.LoadHtml(format.Paths.NavAbsolutePath));
}

var ncxPath = format.Opf.FindNcxPath();
if (ncxPath != null)
{
format.Paths.NcxAbsolutePath = ncxPath.ToAbsolutePath(format.Paths.OpfAbsolutePath);
format.Ncx = NcxReader.Read(archive.LoadXml(format.Paths.NcxAbsolutePath));
}

var book = new EpubBook { Format = format };
book.Resources = LoadResources(archive, book);
book.SpecialResources = LoadSpecialResources(archive, book);
Expand All @@ -72,7 +72,7 @@ public static EpubBook Read(Stream stream, bool leaveOpen, Encoding encoding = n
return book;
}
}

private static byte[] LoadCoverImage(EpubBook book)
{
if (book == null) throw new ArgumentNullException(nameof(book));
Expand Down Expand Up @@ -103,7 +103,7 @@ private static List<EpubChapter> LoadChapters(EpubBook book)
{
return LoadChaptersFromNcx(book.Format.Paths.NcxAbsolutePath, book.Format.Ncx.NavMap.NavPoints);
}

return new List<EpubChapter>();
}

Expand All @@ -113,20 +113,23 @@ private static List<EpubChapter> LoadChaptersFromNav(string navAbsolutePath, XEl
var ns = element.Name.Namespace;

var result = new List<EpubChapter>();
var previous = parentChapter;

var ol = element.Element(ns + NavElements.Ol);
if (ol == null)
{
return result;
}

foreach (var li in ol.Elements(ns + NavElements.Li))
{
var chapter = new EpubChapter
{
Parent = parentChapter
Parent = parentChapter,
Previous = previous
};

if (previous != null)
previous.Next = chapter;

var link = li.Element(ns + NavElements.A);
if (link != null)
{
Expand All @@ -140,9 +143,9 @@ private static List<EpubChapter> LoadChaptersFromNav(string navAbsolutePath, XEl
if (url != null)
{
var href = new Href(url);
chapter.FileName = href.Filename;
chapter.RelativePath = href.Path;
chapter.HashLocation = href.HashLocation;
chapter.AbsolutePath = chapter.FileName.ToAbsolutePath(navAbsolutePath);
chapter.AbsolutePath = chapter.RelativePath.ToAbsolutePath(navAbsolutePath);
}

var titleTextElement = li.Descendants().FirstOrDefault(e => !string.IsNullOrWhiteSpace(e.Value));
Expand All @@ -156,6 +159,8 @@ private static List<EpubChapter> LoadChaptersFromNav(string navAbsolutePath, XEl
chapter.SubChapters = LoadChaptersFromNav(navAbsolutePath, li, chapter);
}
result.Add(chapter);

previous = chapter.SubChapters.Any() ? chapter.SubChapters.Last() : chapter;
}
}

Expand All @@ -165,15 +170,28 @@ private static List<EpubChapter> LoadChaptersFromNav(string navAbsolutePath, XEl
private static List<EpubChapter> LoadChaptersFromNcx(string ncxAbsolutePath, IEnumerable<NcxNavPoint> navigationPoints, EpubChapter parentChapter = null)
{
var result = new List<EpubChapter>();
var previous = parentChapter;

foreach (var navigationPoint in navigationPoints)
{
var chapter = new EpubChapter { Title = navigationPoint.NavLabelText, Parent = parentChapter };
var chapter = new EpubChapter
{
Title = navigationPoint.NavLabelText,
Parent = parentChapter,
Previous = previous
};

if (previous != null)
previous.Next = chapter;

var href = new Href(navigationPoint.ContentSrc);
chapter.FileName = href.Filename;
chapter.AbsolutePath = href.Filename.ToAbsolutePath(ncxAbsolutePath);
chapter.RelativePath = href.Path;
chapter.AbsolutePath = href.Path.ToAbsolutePath(ncxAbsolutePath);
chapter.HashLocation = href.HashLocation;
chapter.SubChapters = LoadChaptersFromNcx(ncxAbsolutePath, navigationPoint.NavPoints, chapter);
result.Add(chapter);

previous = chapter.SubChapters.Any() ? chapter.SubChapters.Last() : chapter;
}
return result;
}
Expand Down Expand Up @@ -213,80 +231,80 @@ private static EpubResources LoadResources(ZipArchive epubArchive, EpubBook book
case EpubContentType.Xml:
case EpubContentType.Dtbook:
case EpubContentType.DtbookNcx:
{
var file = new EpubTextFile
{
AbsolutePath = path,
Href = href,
MimeType = mimeType,
ContentType = contentType
};

resources.All.Add(file);

using (var stream = entry.Open())
{
file.Content = stream.ReadToEnd();
}
var file = new EpubTextFile
{
AbsolutePath = path,
Href = href,
MimeType = mimeType,
ContentType = contentType
};

switch (contentType)
{
case EpubContentType.Xhtml11:
resources.Html.Add(file);
break;
case EpubContentType.Css:
resources.Css.Add(file);
break;
default:
resources.Other.Add(file);
break;
resources.All.Add(file);

using (var stream = entry.Open())
{
file.Content = stream.ReadToEnd();
}
break;
}

switch (contentType)
{
case EpubContentType.Xhtml11:
resources.Html.Add(file);
break;
case EpubContentType.Css:
resources.Css.Add(file);
break;
default:
resources.Other.Add(file);
break;
}
break;
}
default:
{
var file = new EpubByteFile
{
AbsolutePath = path,
Href = href,
MimeType = mimeType,
ContentType = contentType
};

resources.All.Add(file);

using (var stream = entry.Open())
{
if (stream == null)
var file = new EpubByteFile
{
throw new EpubException($"Incorrect EPUB file: content file \"{href}\" specified in manifest is not found");
}
AbsolutePath = path,
Href = href,
MimeType = mimeType,
ContentType = contentType
};

resources.All.Add(file);

using (var memoryStream = new MemoryStream((int) entry.Length))
using (var stream = entry.Open())
{
stream.CopyTo(memoryStream);
file.Content = memoryStream.ToArray();
if (stream == null)
{
throw new EpubException($"Incorrect EPUB file: content file \"{href}\" specified in manifest is not found");
}

using (var memoryStream = new MemoryStream((int)entry.Length))
{
stream.CopyTo(memoryStream);
file.Content = memoryStream.ToArray();
}
}
}

switch (contentType)
{
case EpubContentType.ImageGif:
case EpubContentType.ImageJpeg:
case EpubContentType.ImagePng:
case EpubContentType.ImageSvg:
resources.Images.Add(file);
break;
case EpubContentType.FontTruetype:
case EpubContentType.FontOpentype:
resources.Fonts.Add(file);
break;
default:
resources.Other.Add(file);
break;
switch (contentType)
{
case EpubContentType.ImageGif:
case EpubContentType.ImageJpeg:
case EpubContentType.ImagePng:
case EpubContentType.ImageSvg:
resources.Images.Add(file);
break;
case EpubContentType.FontTruetype:
case EpubContentType.FontOpentype:
resources.Fonts.Add(file);
break;
default:
resources.Other.Add(file);
break;
}
break;
}
break;
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions EpubSharp/EpubSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
<Authors>Arvydas Sidorenko</Authors>
<PackageTags>epub epubs book books 2.0 3.0 3.1</PackageTags>
<PackageId>EpubSharp.dll</PackageId>
<Version>1.1.5.11</Version>
<Version>1.1.5.13</Version>
<Description>A library for reading and writing EPUB files.</Description>
<PackageIconUrl>https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/EPUB_silk_icon.svg/2000px-EPUB_silk_icon.svg.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/Asido/EpubSharp/</PackageProjectUrl>
<Copyright>Copyright 2018</Copyright>
<AssemblyVersion>1.1.5.11</AssemblyVersion>
<FileVersion>1.1.5.11</FileVersion>
<AssemblyVersion>1.1.5.13</AssemblyVersion>
<FileVersion>1.1.5.13</FileVersion>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net451'">
Expand Down
Loading

0 comments on commit ebf7118

Please sign in to comment.