Code reformat and UI tweaks

This commit is contained in:
Paddy Xu
2018-07-24 22:06:06 +03:00
parent c1733a39fd
commit e7aee219b3
59 changed files with 1490 additions and 703 deletions

View File

@@ -1,6 +1,22 @@
using System;
// Copyright © 2018 Marco Gavelli and Paddy Xu
//
// This file is part of QuickLook program.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
@@ -11,93 +27,82 @@ namespace VersOne.Epub.Internal
{
internal static class NavigationReader
{
public static async Task<EpubNavigation> ReadNavigationAsync(ZipArchive epubArchive, string contentDirectoryPath, EpubPackage package)
public static async Task<EpubNavigation> ReadNavigationAsync(ZipArchive epubArchive,
string contentDirectoryPath, EpubPackage package)
{
EpubNavigation result = new EpubNavigation();
string tocId = package.Spine.Toc;
if (String.IsNullOrEmpty(tocId))
{
throw new Exception("EPUB parsing error: TOC ID is empty.");
}
EpubManifestItem tocManifestItem = package.Manifest.FirstOrDefault(item => String.Compare(item.Id, tocId, StringComparison.OrdinalIgnoreCase) == 0);
var result = new EpubNavigation();
var tocId = package.Spine.Toc;
if (string.IsNullOrEmpty(tocId)) throw new Exception("EPUB parsing error: TOC ID is empty.");
var tocManifestItem = package.Manifest.FirstOrDefault(item =>
string.Compare(item.Id, tocId, StringComparison.OrdinalIgnoreCase) == 0);
if (tocManifestItem == null)
{
throw new Exception(String.Format("EPUB parsing error: TOC item {0} not found in EPUB manifest.", tocId));
}
string tocFileEntryPath = ZipPathUtils.Combine(contentDirectoryPath, tocManifestItem.Href);
ZipArchiveEntry tocFileEntry = epubArchive.GetEntry(tocFileEntryPath);
throw new Exception(
string.Format("EPUB parsing error: TOC item {0} not found in EPUB manifest.", tocId));
var tocFileEntryPath = ZipPathUtils.Combine(contentDirectoryPath, tocManifestItem.Href);
var tocFileEntry = epubArchive.GetEntry(tocFileEntryPath);
if (tocFileEntry == null)
{
throw new Exception(String.Format("EPUB parsing error: TOC file {0} not found in archive.", tocFileEntryPath));
}
if (tocFileEntry.Length > Int32.MaxValue)
{
throw new Exception(String.Format("EPUB parsing error: TOC file {0} is larger than 2 Gb.", tocFileEntryPath));
}
throw new Exception(string.Format("EPUB parsing error: TOC file {0} not found in archive.",
tocFileEntryPath));
if (tocFileEntry.Length > int.MaxValue)
throw new Exception(string.Format("EPUB parsing error: TOC file {0} is larger than 2 Gb.",
tocFileEntryPath));
XDocument containerDocument;
using (Stream containerStream = tocFileEntry.Open())
using (var containerStream = tocFileEntry.Open())
{
containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false);
}
XNamespace ncxNamespace = "http://www.daisy.org/z3986/2005/ncx/";
XElement ncxNode = containerDocument.Element(ncxNamespace + "ncx");
if (ncxNode == null)
{
throw new Exception("EPUB parsing error: TOC file does not contain ncx element.");
}
XElement headNode = ncxNode.Element(ncxNamespace + "head");
if (headNode == null)
{
throw new Exception("EPUB parsing error: TOC file does not contain head element.");
}
EpubNavigationHead navigationHead = ReadNavigationHead(headNode);
var ncxNode = containerDocument.Element(ncxNamespace + "ncx");
if (ncxNode == null) throw new Exception("EPUB parsing error: TOC file does not contain ncx element.");
var headNode = ncxNode.Element(ncxNamespace + "head");
if (headNode == null) throw new Exception("EPUB parsing error: TOC file does not contain head element.");
var navigationHead = ReadNavigationHead(headNode);
result.Head = navigationHead;
XElement docTitleNode = ncxNode.Element(ncxNamespace + "docTitle");
var docTitleNode = ncxNode.Element(ncxNamespace + "docTitle");
if (docTitleNode == null)
{
throw new Exception("EPUB parsing error: TOC file does not contain docTitle element.");
}
EpubNavigationDocTitle navigationDocTitle = ReadNavigationDocTitle(docTitleNode);
var navigationDocTitle = ReadNavigationDocTitle(docTitleNode);
result.DocTitle = navigationDocTitle;
result.DocAuthors = new List<EpubNavigationDocAuthor>();
foreach (XElement docAuthorNode in ncxNode.Elements(ncxNamespace + "docAuthor"))
foreach (var docAuthorNode in ncxNode.Elements(ncxNamespace + "docAuthor"))
{
EpubNavigationDocAuthor navigationDocAuthor = ReadNavigationDocAuthor(docAuthorNode);
var navigationDocAuthor = ReadNavigationDocAuthor(docAuthorNode);
result.DocAuthors.Add(navigationDocAuthor);
}
XElement navMapNode = ncxNode.Element(ncxNamespace + "navMap");
var navMapNode = ncxNode.Element(ncxNamespace + "navMap");
if (navMapNode == null)
{
throw new Exception("EPUB parsing error: TOC file does not contain navMap element.");
}
EpubNavigationMap navMap = ReadNavigationMap(navMapNode);
var navMap = ReadNavigationMap(navMapNode);
result.NavMap = navMap;
XElement pageListNode = ncxNode.Element(ncxNamespace + "pageList");
var pageListNode = ncxNode.Element(ncxNamespace + "pageList");
if (pageListNode != null)
{
EpubNavigationPageList pageList = ReadNavigationPageList(pageListNode);
var pageList = ReadNavigationPageList(pageListNode);
result.PageList = pageList;
}
result.NavLists = new List<EpubNavigationList>();
foreach (XElement navigationListNode in ncxNode.Elements(ncxNamespace + "navList"))
foreach (var navigationListNode in ncxNode.Elements(ncxNamespace + "navList"))
{
EpubNavigationList navigationList = ReadNavigationList(navigationListNode);
var navigationList = ReadNavigationList(navigationListNode);
result.NavLists.Add(navigationList);
}
return result;
}
private static EpubNavigationHead ReadNavigationHead(XElement headNode)
{
EpubNavigationHead result = new EpubNavigationHead();
foreach (XElement metaNode in headNode.Elements())
{
if (String.Compare(metaNode.Name.LocalName, "meta", StringComparison.OrdinalIgnoreCase) == 0)
var result = new EpubNavigationHead();
foreach (var metaNode in headNode.Elements())
if (string.Compare(metaNode.Name.LocalName, "meta", StringComparison.OrdinalIgnoreCase) == 0)
{
EpubNavigationHeadMeta meta = new EpubNavigationHeadMeta();
foreach (XAttribute metaNodeAttribute in metaNode.Attributes())
var meta = new EpubNavigationHeadMeta();
foreach (var metaNodeAttribute in metaNode.Attributes())
{
string attributeValue = metaNodeAttribute.Value;
var attributeValue = metaNodeAttribute.Value;
switch (metaNodeAttribute.Name.LocalName.ToLowerInvariant())
{
case "name":
@@ -111,66 +116,55 @@ namespace VersOne.Epub.Internal
break;
}
}
if (String.IsNullOrWhiteSpace(meta.Name))
{
if (string.IsNullOrWhiteSpace(meta.Name))
throw new Exception("Incorrect EPUB navigation meta: meta name is missing.");
}
if (meta.Content == null)
{
throw new Exception("Incorrect EPUB navigation meta: meta content is missing.");
}
result.Add(meta);
}
}
return result;
}
private static EpubNavigationDocTitle ReadNavigationDocTitle(XElement docTitleNode)
{
EpubNavigationDocTitle result = new EpubNavigationDocTitle();
foreach (XElement textNode in docTitleNode.Elements())
{
if (String.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
{
var result = new EpubNavigationDocTitle();
foreach (var textNode in docTitleNode.Elements())
if (string.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
result.Add(textNode.Value);
}
}
return result;
}
private static EpubNavigationDocAuthor ReadNavigationDocAuthor(XElement docAuthorNode)
{
EpubNavigationDocAuthor result = new EpubNavigationDocAuthor();
foreach (XElement textNode in docAuthorNode.Elements())
{
if (String.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
{
var result = new EpubNavigationDocAuthor();
foreach (var textNode in docAuthorNode.Elements())
if (string.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
result.Add(textNode.Value);
}
}
return result;
}
private static EpubNavigationMap ReadNavigationMap(XElement navigationMapNode)
{
EpubNavigationMap result = new EpubNavigationMap();
foreach (XElement navigationPointNode in navigationMapNode.Elements())
{
if (String.Compare(navigationPointNode.Name.LocalName, "navPoint", StringComparison.OrdinalIgnoreCase) == 0)
var result = new EpubNavigationMap();
foreach (var navigationPointNode in navigationMapNode.Elements())
if (string.Compare(navigationPointNode.Name.LocalName, "navPoint",
StringComparison.OrdinalIgnoreCase) == 0)
{
EpubNavigationPoint navigationPoint = ReadNavigationPoint(navigationPointNode);
var navigationPoint = ReadNavigationPoint(navigationPointNode);
result.Add(navigationPoint);
}
}
return result;
}
private static EpubNavigationPoint ReadNavigationPoint(XElement navigationPointNode)
{
EpubNavigationPoint result = new EpubNavigationPoint();
foreach (XAttribute navigationPointNodeAttribute in navigationPointNode.Attributes())
var result = new EpubNavigationPoint();
foreach (var navigationPointNodeAttribute in navigationPointNode.Attributes())
{
string attributeValue = navigationPointNodeAttribute.Value;
var attributeValue = navigationPointNodeAttribute.Value;
switch (navigationPointNodeAttribute.Name.LocalName.ToLowerInvariant())
{
case "id":
@@ -184,59 +178,53 @@ namespace VersOne.Epub.Internal
break;
}
}
if (String.IsNullOrWhiteSpace(result.Id))
{
if (string.IsNullOrWhiteSpace(result.Id))
throw new Exception("Incorrect EPUB navigation point: point ID is missing.");
}
result.NavigationLabels = new List<EpubNavigationLabel>();
result.ChildNavigationPoints = new List<EpubNavigationPoint>();
foreach (XElement navigationPointChildNode in navigationPointNode.Elements())
{
foreach (var navigationPointChildNode in navigationPointNode.Elements())
switch (navigationPointChildNode.Name.LocalName.ToLowerInvariant())
{
case "navlabel":
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationPointChildNode);
var navigationLabel = ReadNavigationLabel(navigationPointChildNode);
result.NavigationLabels.Add(navigationLabel);
break;
case "content":
EpubNavigationContent content = ReadNavigationContent(navigationPointChildNode);
var content = ReadNavigationContent(navigationPointChildNode);
result.Content = content;
break;
case "navpoint":
EpubNavigationPoint childNavigationPoint = ReadNavigationPoint(navigationPointChildNode);
var childNavigationPoint = ReadNavigationPoint(navigationPointChildNode);
result.ChildNavigationPoints.Add(childNavigationPoint);
break;
}
}
if (!result.NavigationLabels.Any())
{
throw new Exception(String.Format("EPUB parsing error: navigation point {0} should contain at least one navigation label.", result.Id));
}
throw new Exception(string.Format(
"EPUB parsing error: navigation point {0} should contain at least one navigation label.",
result.Id));
if (result.Content == null)
{
throw new Exception(String.Format("EPUB parsing error: navigation point {0} should contain content.", result.Id));
}
throw new Exception(string.Format("EPUB parsing error: navigation point {0} should contain content.",
result.Id));
return result;
}
private static EpubNavigationLabel ReadNavigationLabel(XElement navigationLabelNode)
{
EpubNavigationLabel result = new EpubNavigationLabel();
XElement navigationLabelTextNode = navigationLabelNode.Element(navigationLabelNode.Name.Namespace + "text");
var result = new EpubNavigationLabel();
var navigationLabelTextNode = navigationLabelNode.Element(navigationLabelNode.Name.Namespace + "text");
if (navigationLabelTextNode == null)
{
throw new Exception("Incorrect EPUB navigation label: label text element is missing.");
}
result.Text = navigationLabelTextNode.Value;
return result;
}
private static EpubNavigationContent ReadNavigationContent(XElement navigationContentNode)
{
EpubNavigationContent result = new EpubNavigationContent();
foreach (XAttribute navigationContentNodeAttribute in navigationContentNode.Attributes())
var result = new EpubNavigationContent();
foreach (var navigationContentNodeAttribute in navigationContentNode.Attributes())
{
string attributeValue = navigationContentNodeAttribute.Value;
var attributeValue = navigationContentNodeAttribute.Value;
switch (navigationContentNodeAttribute.Name.LocalName.ToLowerInvariant())
{
case "id":
@@ -247,33 +235,32 @@ namespace VersOne.Epub.Internal
break;
}
}
if (String.IsNullOrWhiteSpace(result.Source))
{
if (string.IsNullOrWhiteSpace(result.Source))
throw new Exception("Incorrect EPUB navigation content: content source is missing.");
}
return result;
}
private static EpubNavigationPageList ReadNavigationPageList(XElement navigationPageListNode)
{
EpubNavigationPageList result = new EpubNavigationPageList();
foreach (XElement pageTargetNode in navigationPageListNode.Elements())
{
if (String.Compare(pageTargetNode.Name.LocalName, "pageTarget", StringComparison.OrdinalIgnoreCase) == 0)
var result = new EpubNavigationPageList();
foreach (var pageTargetNode in navigationPageListNode.Elements())
if (string.Compare(pageTargetNode.Name.LocalName, "pageTarget", StringComparison.OrdinalIgnoreCase) ==
0)
{
EpubNavigationPageTarget pageTarget = ReadNavigationPageTarget(pageTargetNode);
var pageTarget = ReadNavigationPageTarget(pageTargetNode);
result.Add(pageTarget);
}
}
return result;
}
private static EpubNavigationPageTarget ReadNavigationPageTarget(XElement navigationPageTargetNode)
{
EpubNavigationPageTarget result = new EpubNavigationPageTarget();
foreach (XAttribute navigationPageTargetNodeAttribute in navigationPageTargetNode.Attributes())
var result = new EpubNavigationPageTarget();
foreach (var navigationPageTargetNodeAttribute in navigationPageTargetNode.Attributes())
{
string attributeValue = navigationPageTargetNodeAttribute.Value;
var attributeValue = navigationPageTargetNodeAttribute.Value;
switch (navigationPageTargetNodeAttribute.Name.LocalName.ToLowerInvariant())
{
case "id":
@@ -285,9 +272,9 @@ namespace VersOne.Epub.Internal
case "type":
EpubNavigationPageTargetType type;
if (!Enum.TryParse(attributeValue, out type))
{
throw new Exception(String.Format("Incorrect EPUB navigation page target: {0} is incorrect value for page target type.", attributeValue));
}
throw new Exception(string.Format(
"Incorrect EPUB navigation page target: {0} is incorrect value for page target type.",
attributeValue));
result.Type = type;
break;
case "class":
@@ -298,35 +285,33 @@ namespace VersOne.Epub.Internal
break;
}
}
if (result.Type == default(EpubNavigationPageTargetType))
{
throw new Exception("Incorrect EPUB navigation page target: page target type is missing.");
}
foreach (XElement navigationPageTargetChildNode in navigationPageTargetNode.Elements())
foreach (var navigationPageTargetChildNode in navigationPageTargetNode.Elements())
switch (navigationPageTargetChildNode.Name.LocalName.ToLowerInvariant())
{
case "navlabel":
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationPageTargetChildNode);
var navigationLabel = ReadNavigationLabel(navigationPageTargetChildNode);
result.NavigationLabels.Add(navigationLabel);
break;
case "content":
EpubNavigationContent content = ReadNavigationContent(navigationPageTargetChildNode);
var content = ReadNavigationContent(navigationPageTargetChildNode);
result.Content = content;
break;
}
if (!result.NavigationLabels.Any())
{
throw new Exception("Incorrect EPUB navigation page target: at least one navLabel element is required.");
}
throw new Exception(
"Incorrect EPUB navigation page target: at least one navLabel element is required.");
return result;
}
private static EpubNavigationList ReadNavigationList(XElement navigationListNode)
{
EpubNavigationList result = new EpubNavigationList();
foreach (XAttribute navigationListNodeAttribute in navigationListNode.Attributes())
var result = new EpubNavigationList();
foreach (var navigationListNodeAttribute in navigationListNode.Attributes())
{
string attributeValue = navigationListNodeAttribute.Value;
var attributeValue = navigationListNodeAttribute.Value;
switch (navigationListNodeAttribute.Name.LocalName.ToLowerInvariant())
{
case "id":
@@ -337,33 +322,31 @@ namespace VersOne.Epub.Internal
break;
}
}
foreach (XElement navigationListChildNode in navigationListNode.Elements())
{
foreach (var navigationListChildNode in navigationListNode.Elements())
switch (navigationListChildNode.Name.LocalName.ToLowerInvariant())
{
case "navlabel":
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationListChildNode);
var navigationLabel = ReadNavigationLabel(navigationListChildNode);
result.NavigationLabels.Add(navigationLabel);
break;
case "navTarget":
EpubNavigationTarget navigationTarget = ReadNavigationTarget(navigationListChildNode);
var navigationTarget = ReadNavigationTarget(navigationListChildNode);
result.NavigationTargets.Add(navigationTarget);
break;
}
}
if (!result.NavigationLabels.Any())
{
throw new Exception("Incorrect EPUB navigation page target: at least one navLabel element is required.");
}
throw new Exception(
"Incorrect EPUB navigation page target: at least one navLabel element is required.");
return result;
}
private static EpubNavigationTarget ReadNavigationTarget(XElement navigationTargetNode)
{
EpubNavigationTarget result = new EpubNavigationTarget();
foreach (XAttribute navigationPageTargetNodeAttribute in navigationTargetNode.Attributes())
var result = new EpubNavigationTarget();
foreach (var navigationPageTargetNodeAttribute in navigationTargetNode.Attributes())
{
string attributeValue = navigationPageTargetNodeAttribute.Value;
var attributeValue = navigationPageTargetNodeAttribute.Value;
switch (navigationPageTargetNodeAttribute.Name.LocalName.ToLowerInvariant())
{
case "id":
@@ -380,29 +363,24 @@ namespace VersOne.Epub.Internal
break;
}
}
if (String.IsNullOrWhiteSpace(result.Id))
{
if (string.IsNullOrWhiteSpace(result.Id))
throw new Exception("Incorrect EPUB navigation target: navigation target ID is missing.");
}
foreach (XElement navigationTargetChildNode in navigationTargetNode.Elements())
{
foreach (var navigationTargetChildNode in navigationTargetNode.Elements())
switch (navigationTargetChildNode.Name.LocalName.ToLowerInvariant())
{
case "navlabel":
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationTargetChildNode);
var navigationLabel = ReadNavigationLabel(navigationTargetChildNode);
result.NavigationLabels.Add(navigationLabel);
break;
case "content":
EpubNavigationContent content = ReadNavigationContent(navigationTargetChildNode);
var content = ReadNavigationContent(navigationTargetChildNode);
result.Content = content;
break;
}
}
if (!result.NavigationLabels.Any())
{
throw new Exception("Incorrect EPUB navigation target: at least one navLabel element is required.");
}
return result;
}
}
}
}