Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check prev/next links in Content Documents (issue #975) #1037

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ private void initialize()
severities.put(MessageId.NAV_009, Severity.ERROR);
severities.put(MessageId.NAV_010, Severity.ERROR);
severities.put(MessageId.NAV_011, Severity.ERROR);
severities.put(MessageId.NAV_012, Severity.ERROR);

// NCX
severities.put(MessageId.NCX_001, Severity.ERROR);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/adobe/epubcheck/messages/MessageId.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public enum MessageId implements Comparable<MessageId>
NAV_009("NAV-009"),
NAV_010("NAV-010"),
NAV_011("NAV-011"),
NAV_012("NAV-012"),

// Epub2 based table of content messages
NCX_001("NCX-001"),
Expand Down
41 changes: 37 additions & 4 deletions src/main/java/com/adobe/epubcheck/opf/XRefChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public static enum Type
NAV_TOC_LINK,
NAV_PAGELIST_LINK,
PICTURE_SOURCE,
PICTURE_SOURCE_FOREIGN;
PICTURE_SOURCE_FOREIGN,
NAV_LINK;
}

private static class Reference
Expand All @@ -82,9 +83,16 @@ private static class Reference
public final String refResource;
public final String fragment;
public final Type type;
public final String direction;


public Reference(String srcResource, int srcLineNumber, int srcColumnNumber, String value,
String refResource, String fragment, Type type){
this(srcResource, srcLineNumber, srcColumnNumber, value, refResource, fragment, type, null);
}

public Reference(String srcResource, int srcLineNumber, int srcColumnNumber, String value,
String refResource, String fragment, Type type)
String refResource, String fragment, Type type, String direction)
{
this.source = srcResource;
this.lineNumber = srcLineNumber;
Expand All @@ -93,6 +101,7 @@ public Reference(String srcResource, int srcLineNumber, int srcColumnNumber, Str
this.refResource = refResource;
this.fragment = fragment;
this.type = type;
this.direction = direction;
}

}
Expand Down Expand Up @@ -259,7 +268,12 @@ public void registerAnchor(String path, int lineNumber, int columnNumber, String
}

public void registerReference(String srcResource, int srcLineNumber, int srcColumnNumber,
String ref, Type type)
String ref, Type type){
registerReference(srcResource, srcLineNumber, srcColumnNumber, ref, type, null);
}

public void registerReference(String srcResource, int srcLineNumber, int srcColumnNumber,
String ref, Type type, String linkDirection)
{
if (ref.startsWith("data:"))
{
Expand All @@ -277,7 +291,7 @@ public void registerReference(String srcResource, int srcLineNumber, int srcColu
String refFragment = PathUtil.getFragment(ref);
report.info(srcResource, FeatureEnum.RESOURCE, refResource);
references.add(new Reference(srcResource, srcLineNumber, srcColumnNumber, ref, refResource,
refFragment, type));
refFragment, type, linkDirection));

}

Expand Down Expand Up @@ -451,6 +465,24 @@ else if (ref.type == Type.IMAGE && !res.hasValidImageFallback) {
return;
}
break;
case NAV_LINK:
int curSpinePosition = host.item.getSpinePosition();
int targetSpinePosition = res.item.getSpinePosition();
if (ref.direction!=null){
switch (ref.direction.toLowerCase()){
case "prev":
if (targetSpinePosition!= curSpinePosition-1){
report.message(MessageId.NAV_012,EPUBLocation.create(ref.source, ref.lineNumber, ref.columnNumber, ref.refResource),host.item.getPath(), res.item.getPath(), ref.direction, host.item.getPath());
}
break;
case "next":
if (targetSpinePosition != curSpinePosition+1){
report.message(MessageId.NAV_012,EPUBLocation.create(ref.source, ref.lineNumber, ref.columnNumber, ref.refResource),res.item.getPath(), host.item.getPath(), ref.direction, host.item.getPath());
}
break;
}
}
break;
default:
break;
}
Expand Down Expand Up @@ -575,4 +607,5 @@ private void checkReadingOrder(Queue<Reference> references, int lastSpinePositio
}
checkReadingOrder(references, lastSpinePosition, lastAnchorPosition);
}

}
29 changes: 18 additions & 11 deletions src/main/java/com/adobe/epubcheck/ops/OPSHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,30 +141,37 @@ protected void checkLink(XMLElement e, String attrNS, String attr)
{
String href = e.getAttributeNS(attrNS, attr);
String rel = e.getAttributeNS(attrNS, "rel");
if (xrefChecker.isPresent() && href != null && rel != null
&& rel.toLowerCase(Locale.ROOT).contains("stylesheet"))
{
href = PathUtil.resolveRelativeReference(base, href);
xrefChecker.get().registerReference(path, parser.getLineNumber(), parser.getColumnNumber(),
href, XRefChecker.Type.STYLESHEET);

String linkDirection = null;
if (!xrefChecker.isPresent() || href == null || rel == null) {
return;
}
XRefChecker.Type refType = null;
href = PathUtil.resolveRelativeReference(base, href);
rel = rel.toLowerCase(Locale.ROOT);
if (rel.contains("stylesheet")){
refType = XRefChecker.Type.STYLESHEET;
// Check the mimetype to record possible non-standard stylesheets
// with no fallback
String mimetype = xrefChecker.get().getMimeType(href);
if (mimetype != null)
{
if (OPFChecker.isBlessedStyleType(mimetype)
|| OPFChecker.isDeprecatedBlessedStyleType(mimetype))
if (OPFChecker.isBlessedStyleType(mimetype) || OPFChecker.isDeprecatedBlessedStyleType(mimetype))
{
hasCss = true;
}
else
{
nonStandardStylesheetLink = Optional.of(
EPUBLocation.create(path, parser.getLineNumber(), parser.getColumnNumber(), href));
nonStandardStylesheetLink = Optional.of(EPUBLocation.create(path, parser.getLineNumber(), parser.getColumnNumber(), href));
}
}
}
if (rel.contains("prev")){ refType = XRefChecker.Type.NAV_LINK; linkDirection = "prev";}
if (rel.contains("next")){ refType = XRefChecker.Type.NAV_LINK; linkDirection = "next";}

if (refType!=null){
xrefChecker.get().registerReference(path, parser.getLineNumber(), parser.getColumnNumber(), href, refType, linkDirection);
}

}

protected void checkStylesheetFallback()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ NAV_010='%1$s' nav must not link to remote resources; found link to '%2$s'.
NAV_011='%1$s' nav must be in reading order; link target '%2$s' is before the previous link's target in %3$s order.
NAV_011_SUG.spine=spine
NAV_011_SUG.document=document
NAV_012=Related nav links do not match spine sequence; '%1$s' comes before '%2$s' in the spine. Review the '%3$s' link element in '%4$s'.

#NCX EPUB v2 Table of Contents
NCX_001=NCX identifier ('%1$s') does not match OPF identifier ('%2$s').
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1468,4 +1468,11 @@ public void testEncryption_DuplicateIDs()
Collections.addAll(expectedErrors, MessageId.RSC_005, MessageId.RSC_005);
testValidateDocument("invalid/encryption-duplicate-ids");
}

@Test
public void testRelativeLinks(){
Collections.addAll(expectedErrors, MessageId.RSC_007, MessageId.RSC_006, MessageId.NAV_012);
testValidateDocument("invalid/rel-link-checks");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-model href="http://www.daisy.org/pipeline/modules/nordic/nordic-html5.rng"?>
<?xml-model href="http://www.daisy.org/pipeline/modules/nordic/nordic2015-1.sch"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en" lang="en" epub:prefix="z3998: http://www.daisy.org/z3998/2012/vocab/structure/#"
xmlns:nordic="http://www.mtm.se/epub/">
<head>
<meta charset="UTF-8" />
<title>Valentin Haüy - the father of the education for the blind</title>
<meta content="C00000" name="dc:identifier" />
<meta name="viewport" content="width=device-width" />
<style type="text/css" xml:space="preserve">
.initialism{
-epub-speak-as:spell-out;
}
.list-style-type-none{
list-style-type:none;
}
table[class ^= "table-rules-"],
table[class *= " table-rules-"]{
border-width:thin;
border-style:hidden;
}
table[class ^= "table-rules-"]:not(.table-rules-none),
table[class *= " table-rules-"]:not(.table-rules-none){
border-collapse:collapse;
}
table[class ^= "table-rules-"] td,
table[class *= " table-rules-"] td{
border-width:thin;
border-style:none;
}
table[class ^= "table-rules-"] th,
table[class *= " table-rules-"] th{
border-width:thin;
border-style:none;
}
table.table-rules-none td,
table.table-rules-none th{
border-width:thin;
border-style:hidden;
}
table.table-rules-all td,
table.table-rules-all th{
border-width:thin;
border-style:solid;
}
table.table-rules-cols td,
table.table-rules-cols th{
border-left-width:thin;
border-right-width:thin;
border-left-style:solid;
border-right-style:solid;
}
table.table-rules-rows tr{
border-top-width:thin;
border-bottom-width:thin;
border-top-style:solid;
border-bottom-style:solid;
}
table.table-rules-groups colgroup{
border-left-width:thin;
border-right-width:thin;
border-left-style:solid;
border-right-style:solid;
}
table.table-rules-groups tfoot,
table.table-rules-groups thead,
table.table-rules-groups tbody{
border-top-width:thin;
border-bottom-width:thin;
border-top-style:solid;
border-bottom-style:solid;
}
table[class ^= "table-frame-"],
table[class *= " table-frame-"]{
border:thin hidden;
}
table.table-frame-void{
border-style:hidden;
}
table.table-frame-above{
border-style:outset hidden hidden hidden;
}
table.table-frame-below{
border-style:hidden hidden outset hidden;
}
table.table-frame-lhs{
border-style:hidden hidden hidden outset;
}
table.table-frame-rhs{
border-style:hidden outset hidden hidden;
}
table.table-frame-hsides{
border-style:outset hidden;
}
table.table-frame-vsides{
border-style:hidden outset;
}
table.table-frame-box{
border-style:outset;
}
table.table-frame-border{
border-style:outset;
}</style>
<link rel="stylesheet" type="text/css" href="css/accessibility.css" />
<link rel="next" href="C00000-2-toc.xhtml" />
</head>
<body id="level1_1" epub:type="cover">
<section id="prodnote_1" class="render-optional rearcover">
<p>Gro försöker att få Runa på gott humör igen.</p>
<p>– Vi har det bara så långtråkigt. Du har tur. Du får gå ut och in i tornet. Alvilda och jag måste sitta här dag ut och dag in. Bara om natten får vi komma till kvinnosalen. Om det bara
snart ville kommma någon som kan slå ihjäl ormen.</p>
<p>Gro suckar djupt. Liksom Alvilda är hon trött på att vara inspärrad.</p>
<p>Alvilda tittar ner på sina bröder igen.</p>
<p>– Jag vill hellre lära mig att slåss, mumlar hon. Då skulle jag själv kunna slå ihjäl odjuret.</p>
<p>– Jag hörde nog vad du sa. Runa ruskar på huvudet. Du vet inte vad som är bäst för dig. Tänk på allt det besvär din pappa och mamma har haft. Först byggde de det här tornet av koppar.
Sedan har de skaffat en orm, som kan vakta din dygd. Många unga män har mist sina liv för din skull.</p>
<aside id="nested-prodnote-in-rearcover" epub:type="z3998:production" class="prodnote"><p>Prodnote inside rearcover</p></aside>
</section>
</body>
</html>
Loading