Skip to content

Commit

Permalink
feat: check that non-linear content is reachable
Browse files Browse the repository at this point in the history
EPUB 3.3 says:
> EPUB creators MUST provide a means of accessing all non-linear content
> (e.g., hyperlinks in the content or from the EPUB navigation document).

This commit adds a check for the above statement.
- new error `OPF-096` is reported when no hyperlink was found to
  non-linear content in an EPUB with no script
- new usage `OPF-096b` is reported when no hyperlink was found to
  non-linear content in a scripted EPUB (a link may be added via
  scripting, so we cannot report this as an error)

Fix #1451
  • Loading branch information
rdeltour committed Dec 15, 2022
1 parent 0175818 commit f20993e
Show file tree
Hide file tree
Showing 54 changed files with 402 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ private void initialize()
severities.put(MessageId.OPF_093, Severity.ERROR);
severities.put(MessageId.OPF_094, Severity.ERROR);
severities.put(MessageId.OPF_095, Severity.ERROR);
severities.put(MessageId.OPF_096, Severity.ERROR);
severities.put(MessageId.OPF_096b, Severity.USAGE);

// PKG
severities.put(MessageId.PKG_001, Severity.WARNING);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/adobe/epubcheck/messages/MessageId.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ public enum MessageId implements Comparable<MessageId>
OPF_093("OPF-093"),
OPF_094("OPF-094"),
OPF_095("OPF-095"),
OPF_096("OPF-096"),
OPF_096b("OPF-096b"),

// Messages relating to the entire package
PKG_001("PKG-001"),
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/com/adobe/epubcheck/opf/OPFChecker30.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import java.util.Set;

import org.w3c.epubcheck.core.references.Reference;
import org.w3c.epubcheck.util.url.URLFragment;

import com.adobe.epubcheck.api.EPUBLocation;
Expand Down Expand Up @@ -183,6 +184,26 @@ else if (!overlayTextChecker.isCorrectOverlay(docURL, mo))
}
}
}

// check that non-linear content documents are reachable
if (item.isInSpine() && !item.isLinear() && context.referenceRegistry.isPresent()
// search the reference registry for any hyperlink pointing to this item
&& !context.referenceRegistry.get().asList().stream()
.anyMatch(ref -> ref.type == Reference.Type.HYPERLINK
&& ref.targetResource.equals(item.getURL())))
{
// if content is scripted, references can be added by scripting
// se we only report a usage
if (context.featureReport.hasFeature(FeatureEnum.HAS_SCRIPTS))
{
report.message(MessageId.OPF_096b, item.getLocation(), item.getPath());
}
// else, report an error if no hyperlink were found
else
{
report.message(MessageId.OPF_096, item.getLocation(), item.getPath());
}
}
}

@Override
Expand All @@ -194,14 +215,15 @@ protected void checkSpineItem(OPFItem item, OPFHandler opfHandler)
return;
}

String mimeType = item.getMimeType();

// check properties
if (item.getProperties()
.contains(PackageVocabs.ITEM_VOCAB.get(PackageVocabs.ITEM_PROPERTIES.DATA_NAV)))
{
report.message(MessageId.OPF_077, item.getLocation());
}

// check that spine items have content document fallback
String mimeType = item.getMimeType();
if (!isBlessedItemType(mimeType, version))
{
if (!item.hasFallback())
Expand All @@ -213,7 +235,6 @@ else if (!item.hasContentDocumentFallback())
report.message(MessageId.OPF_044, item.getLocation(), mimeType);
}
}

}

private void checkCollections()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ OPF_091=The item href URL must not have a fragment identifier.
OPF_092=Language tag "%1$s" is not well-formed: %2$s
OPF_093=The "media-type" attribute is required for linked resources located in the EPUB container
OPF_094=The "media-type" attribute is required for "%1$s" links.
OPF_095=The "media-type" attribute of "voicing" links must be an audio MIME type, but found "%1$s".
OPF_095=The "media-type" attribute of "voicing" links must be an audio MIME type, but found "%1$s".
OPF_096=Non-linear content must be reachable, but found no hyperlink to "%1$s".
OPF_096b=No hyperlink was found to non-linear document "%1$s", please check that it can be reached from scripted content.

#Package
PKG_001=Validating the EPUB against version %1$s but detected version %2$s.
Expand Down
2 changes: 1 addition & 1 deletion src/test/resources/epub-edupub/edupub-publication.feature
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Feature: EPUB for Education ▸ Full Publication Checks

## 4.2 Sectioning

Scenario: Verify an non-linear content does not have to follow the sectioning rules
Scenario: Verify that non-linear content does not have to follow the sectioning rules
When checking EPUB 'edupub-non-linear-valid'
Then no errors or warnings are reported

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
<li><a href="nonlinear.xhtml">non-linear</a></li>
</ol>
</nav>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="non" href="nonlinear.xhtml" media-type="application/xhtml+xml" />
<item id="nonlinear" href="nonlinear.xhtml" media-type="application/xhtml+xml" />
</manifest>
<spine>
<itemref idref="content_001" />
<itemref idref="non" linear="no" />
<itemref idref="nonlinear" linear="no" />
</spine>
</package>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
<li><a href="data-nav.xhtml">data nav</a></li>
</ol>
</nav>
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<!-- <itemref idref="content_001" />-->
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="content_001" linear=" no "/>
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="content_002" href="content_002.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="content_001" />
<itemref idref="content_002" linear="no"/>
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8" />
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
<a href="content_002.xhtml">link</a>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="content_002" href="content_002.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="content_001" />
<itemref idref="content_002" linear="no"/>
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal Nav</title>
</head>
<body>
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
<li><a href="content_002.xhtml">content 002</a></li>
</ol>
</nav>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="content_002" href="content_002.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="content_001" />
<itemref idref="content_002" linear="no"/>
</spine>
</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
application/epub+zip
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8" />
<title>Minimal EPUB</title>
<script>
window.addEventListener("load", function(){
var link = document.createElement('a');
link.setAttribute('href', 'content_002.xhtml');
link.innerHTML = "link";
document.body.appendChild(link);
});
</script>
</head>
<body id="body">
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns:epub="http://www.idpf.org/2007/ops" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en" lang="en">
<head>
<meta charset="utf-8"/>
<title>Minimal Nav</title>
</head>
<body>
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
</ol>
</nav>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="q">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="q">NOID</dc:identifier>
<meta property="dcterms:modified">2017-06-14T00:00:01Z</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml" properties="scripted"/>
<item id="content_002" href="content_002.xhtml" media-type="application/xhtml+xml"/>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
</manifest>
<spine>
<itemref idref="content_001" />
<itemref idref="content_002" linear="no"/>
</spine>
</package>
Loading

0 comments on commit f20993e

Please sign in to comment.