Skip to content

Commit 57a921e

Browse files
authored
Parse <nav> elements nested in other HTML elements in EPUB 3 navigation documents (#113)
1 parent 3e8f2f6 commit 57a921e

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

Source/VersOne.Epub.Test/Unit/Readers/Epub3NavDocumentReaderTests.cs

+19
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,19 @@ public class Epub3NavDocumentReaderTests
159159
</html>
160160
""";
161161

162+
private const string NAV_FILE_WITH_WITH_NON_TOP_LEVEL_NAV_ELEMENT = """
163+
<html xmlns="http://www.w3.org/1999/xhtml">
164+
<body>
165+
<div>
166+
<nav>
167+
<h1>Test header</h1>
168+
<ol />
169+
</nav>
170+
</div>
171+
</body>
172+
</html>
173+
""";
174+
162175
private static EpubPackage MinimalEpubPackageWithNav =>
163176
new
164177
(
@@ -447,6 +460,12 @@ public async Task ReadEpub3NavDocumentAsyncWithEscapedAHrefTest()
447460
await TestSuccessfulReadOperation(NAV_FILE_WITH_ESCAPED_HREF_IN_A_ELEMENT, expectedEpub3NavDocument);
448461
}
449462

463+
[Fact(DisplayName = "Reading a NAV file with non-top-level 'nav' element should succeed")]
464+
public async Task ReadEpub3NavDocumentAsyncWithNonTopLevelNavElementTest()
465+
{
466+
await TestSuccessfulReadOperation(NAV_FILE_WITH_WITH_NON_TOP_LEVEL_NAV_ELEMENT, MinimalEpub3NavDocumentWithHeader);
467+
}
468+
450469
private static async Task TestSuccessfulReadOperation(string navFileContent, Epub3NavDocument expectedEpub3NavDocument, EpubReaderOptions? epubReaderOptions = null)
451470
{
452471
TestZipFile testZipFile = CreateTestZipFileWithNavFile(navFileContent);

Source/VersOne.Epub/Readers/Epub3NavDocumentReader.cs

+16-4
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,24 @@ public Epub3NavDocumentReader(EpubReaderOptions? epubReaderOptions = null)
4949
XElement htmlNode = navDocument.Element(xhtmlNamespace + "html") ?? throw new Epub3NavException("EPUB parsing error: navigation file does not contain html element.");
5050
XElement bodyNode = htmlNode.Element(xhtmlNamespace + "body") ?? throw new Epub3NavException("EPUB parsing error: navigation file does not contain body element.");
5151
List<Epub3Nav> navs = new();
52-
foreach (XElement navNode in bodyNode.Elements(xhtmlNamespace + "nav"))
52+
ReadEpub3NavsWithinContainerElement(bodyNode, navs);
53+
return new(navFileEntryPath, navs);
54+
}
55+
56+
private static void ReadEpub3NavsWithinContainerElement(XElement containerElement, List<Epub3Nav> resultNavs)
57+
{
58+
foreach (XElement childElement in containerElement.Elements())
5359
{
54-
Epub3Nav epub3Nav = ReadEpub3Nav(navNode);
55-
navs.Add(epub3Nav);
60+
if (childElement.GetLowerCaseLocalName() == "nav")
61+
{
62+
Epub3Nav epub3Nav = ReadEpub3Nav(childElement);
63+
resultNavs.Add(epub3Nav);
64+
}
65+
else
66+
{
67+
ReadEpub3NavsWithinContainerElement(childElement, resultNavs);
68+
}
5669
}
57-
return new(navFileEntryPath, navs);
5870
}
5971

6072
private static Epub3Nav ReadEpub3Nav(XElement navNode)

0 commit comments

Comments
 (0)