Skip to content

Commit

Permalink
feat: better check media overlays styling properties
Browse files Browse the repository at this point in the history
- report schema error RSC-005 when the 'media:active-class' or
  'media:playback-active-class' properties are declared more than once.
- report schema error RSC-005 when the 'media:active-class' or
  'media:playback-active-class' properties define more than once class
  names.
- report new usage CSS-029 when a CSS selector is found referring to
  the widely-used '-epub-media-overlay-active' or '-epub-media-overlay-
  playing' class names but no 'media:active-class' or 'media:playback-
  active-class' properties were declared in the package document.
- report new error CSS-030 when the 'media:active-class' or
  'media:playback-active-class' properties are declared but no CSS is
  found in a content document with media overlays.
- added various test scenarios for the checks described above.

Closs #1218.
  • Loading branch information
rdeltour committed Nov 14, 2022
1 parent 01a7758 commit 6a58b8e
Show file tree
Hide file tree
Showing 54 changed files with 581 additions and 5 deletions.
39 changes: 39 additions & 0 deletions src/main/java/com/adobe/epubcheck/css/CSSHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import org.idpf.epubcheck.util.css.CssContentHandler;
import org.idpf.epubcheck.util.css.CssErrorHandler;
import org.idpf.epubcheck.util.css.CssExceptions.CssException;
import org.idpf.epubcheck.util.css.CssGrammar;
import org.idpf.epubcheck.util.css.CssGrammar.CssAtRule;
import org.idpf.epubcheck.util.css.CssGrammar.CssComposedConstruct;
import org.idpf.epubcheck.util.css.CssGrammar.CssConstruct;
import org.idpf.epubcheck.util.css.CssGrammar.CssDeclaration;
import org.idpf.epubcheck.util.css.CssGrammar.CssSelector;
Expand Down Expand Up @@ -201,6 +203,43 @@ public void endAtRule(String name)
@Override
public void selectors(List<CssSelector> selectors)
{
for (CssSelector selector : selectors)
{
if (!context.featureReport.hasFeature(FeatureEnum.MEDIA_OVERLAYS_ACTIVE_CLASS)
&& findClassName(selector, ".-epub-media-overlay-active"))
{
report.message(MessageId.CSS_029,
getCorrectedEPUBLocation(selector.getLocation().getLine(),
selector.getLocation().getColumn(), selector.toCssString()),
"-epub-media-overlay-active", "media:active-class");
}
if (!context.featureReport.hasFeature(FeatureEnum.MEDIA_OVERLAYS_PLAYBACK_ACTIVE_CLASS)
&& findClassName(selector, ".-epub-media-overlay-playing"))
{
report.message(MessageId.CSS_029,
getCorrectedEPUBLocation(selector.getLocation().getLine(),
selector.getLocation().getColumn(), selector.toCssString()),
"-epub-media-overlay-playing", "media:playback-active-class");
}
}
}

private boolean findClassName(CssConstruct construct, String name)
{
if (construct.getType() == CssGrammar.CssConstruct.Type.CLASSNAME
&& name.equals(construct.toCssString()))
{
return true;

}
else if (construct instanceof CssComposedConstruct)
{
for (CssConstruct component : ((CssComposedConstruct) construct).getComponents())
{
if (findClassName(component, name)) return true;
}
}
return false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ private void initialize()
severities.put(MessageId.CSS_024, Severity.SUPPRESSED);
severities.put(MessageId.CSS_025, Severity.SUPPRESSED);
severities.put(MessageId.CSS_028, Severity.USAGE);
severities.put(MessageId.CSS_029, Severity.USAGE);
severities.put(MessageId.CSS_030, Severity.ERROR);

// HTML
severities.put(MessageId.HTM_001, Severity.ERROR);
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 @@ -85,6 +85,8 @@ public enum MessageId implements Comparable<MessageId>
CSS_024("CSS-024"),
CSS_025("CSS-025"),
CSS_028("CSS-028"),
CSS_029("CSS-029"),
CSS_030("CSS-030"),

// Messages relating to xhtml markup
HTM_001("HTM-001"),
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/com/adobe/epubcheck/opf/OPFHandler30.java
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,24 @@ private void processMeta()
{
metadataBuilders.peekFirst().meta(e.getAttribute("id"), prop.get(),
(String) e.getPrivateData(), e.getAttribute("refines"));

// Primary metadata checks
if (metadataBuilders.size() == 1)
{
switch (prop.get().getPrefixedName())
{
case "media:active-class":
context.featureReport.report(FeatureEnum.MEDIA_OVERLAYS_ACTIVE_CLASS, location(),
e.getPrivateData().toString());
break;
case "media:playback-active-class":
context.featureReport.report(FeatureEnum.MEDIA_OVERLAYS_PLAYBACK_ACTIVE_CLASS, location(),
e.getPrivateData().toString());
break;
default:
break;
}
}
}

// just parse the scheme for vocab errors
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/com/adobe/epubcheck/ops/OPSHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class OPSHandler extends XMLHandler
protected boolean hasTh = false;
protected boolean hasThead = false;
protected boolean hasCaption = false;
protected boolean hasCSS = false;
protected boolean epubTypeInUse = false;
protected StringBuilder textNode;
protected Stack<EPUBLocation> elementLocationStack = new Stack<EPUBLocation>();
Expand Down Expand Up @@ -94,10 +95,13 @@ protected void checkLink()
XMLElement e = currentElement();
URL href = checkURL(e.getAttribute("href"));
String rel = e.getAttribute("rel");
if (xrefChecker.isPresent() && href != null && rel != null
if (href != null && rel != null
&& rel.toLowerCase(Locale.ROOT).contains("stylesheet"))
{
xrefChecker.get().registerReference(href, XRefChecker.Type.STYLESHEET, location());
this.hasCSS = true;
if (xrefChecker.isPresent()) {
xrefChecker.get().registerReference(href, XRefChecker.Type.STYLESHEET, location());
}
}
}

Expand Down Expand Up @@ -365,6 +369,7 @@ public void endElement()
String style = textNode.toString();
if (style.length() > 0)
{
this.hasCSS = true;
new CSSChecker(context, style, currentLocation.getLine(), false).check();
}
textNode = null;
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/adobe/epubcheck/ops/OPSHandler30.java
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ public void endElement()
String name = e.getName();
if (openElements == 0 && (name.equals("html") || name.equals("svg")))
{
checkOverlaysStyles();
checkProperties();
}
else if (name.equals("object"))
Expand Down Expand Up @@ -902,6 +903,17 @@ protected void checkFallback(String elementType)
}
}

protected void checkOverlaysStyles()
{
if (context.opfItem.isPresent() && context.opfItem.get().getMediaOverlay() != null
&& (context.featureReport.hasFeature(FeatureEnum.MEDIA_OVERLAYS_ACTIVE_CLASS)
|| context.featureReport.hasFeature(FeatureEnum.MEDIA_OVERLAYS_PLAYBACK_ACTIVE_CLASS))
&& !this.hasCSS)
{
report.message(MessageId.CSS_030, location());
}
}

protected void checkProperties()
{
if (!context.container.isPresent()) // single file validation
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/adobe/epubcheck/util/FeatureEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public enum FeatureEnum
LOI("list of illustrations"),
LOT("list of tables"),
LOV("list of videos"),
MEDIA_OVERLAYS_ACTIVE_CLASS("media:active-class"),
MEDIA_OVERLAYS_PLAYBACK_ACTIVE_CLASS("media:playback-active-class"),
MODIFIED_DATE("modification date"),
NAVIGATION_ORDER("navigation order"),
PAGE_BREAK("epub:page-break"),
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/idpf/epubcheck/util/css/CssGrammar.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public enum Type
/**
* A CssConstruct that is composed by a single token.
*/
static abstract class CssAtomicConstruct extends CssConstruct
public static abstract class CssAtomicConstruct extends CssConstruct
{
final String value;

Expand Down Expand Up @@ -434,7 +434,7 @@ public String toString()
* A CssConstruct that is composed a list of atomic and/or composed CssConstructs,
* and optionally a name.
*/
static abstract class CssComposedConstruct extends CssConstruct
public static abstract class CssComposedConstruct extends CssConstruct
{
final List<CssConstruct> components;
final Optional<String> name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ CSS_024_SUG=Remove unused CSS selectors.
CSS_025=CSS class Selector could not be found.
CSS_025_SUG=Check for typos or define a class selector to document the use of the class.
CSS_028=Use of Font-face declaration.
CSS_029=Found CSS class name "%1$s" but no "%2$s" property was declared in the package document.
CSS_030=The package document declares media overlays styling class names but no CSS was found in the content document.

#HTM - XHTML related messages
HTM_001=Any publication resource that is an XML-based media type must be a valid XML 1.0 document. XML version found: %1$s.
Expand Down
10 changes: 10 additions & 0 deletions src/main/resources/com/adobe/epubcheck/schema/30/package-30.sch
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,24 @@
</pattern>

<pattern id="opf.media.overlay.metadata.active-class">
<rule context="opf:package/opf:metadata">
<assert test="count(opf:meta[normalize-space(@property)='media:active-class']) le 1">The 'active-class' property must not occur more than one time in the package
metadata.</assert>
</rule>
<rule context="opf:meta[normalize-space(@property)='media:active-class']">
<report test="@refines"> @refines must not be used with the media:active-class property</report>
<report test="contains(normalize-space(.),' ')">the 'active-class' property must define a single class name</report>
</rule>
</pattern>

<pattern id="opf.media.overlay.metadata.playback-active-class">
<rule context="opf:package/opf:metadata">
<assert test="count(opf:meta[normalize-space(@property)='media:playback-active-class']) le 1">The 'playback-active-class' property must not occur more than one time in the package
metadata.</assert>
</rule>
<rule context="opf:meta[normalize-space(@property)='media:playback-active-class']">
<report test="@refines"> @refines must not be used with the media:playback-active-class property</report>
<report test="contains(normalize-space(.),' ')">the 'playback-active-class' property must define a single class name</report>
</rule>
</pattern>

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<smil xmlns="http://www.w3.org/ns/SMIL" xmlns:epub="http://www.idpf.org/2007/ops" version="3.0">
<body>
<par id="par1">
<text src="content_001.xhtml#c01"/>
<audio src="content_001.mp3"/>
</par>
</body>
</smil>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8" />
<title>Minimal EPUB</title>
<style>
.-epub-media-overlay-active {
background-color: yellow;
}
.-epub-media-overlay-playing {
color: gray;
}
</style>
</head>
<body>
<h1 id="c01">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,22 @@
<?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>
<meta property="media:duration">2.5s</meta>
<meta property="media:duration" refines="#mo_001">2.5s</meta>
<meta property="media:active-class">-epub-media-overlay-active</meta>
<meta property="media:playback-active-class">-epub-media-overlay-playing</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml" media-overlay="mo_001"/>
<item id="mo_001" href="content_001.smil" media-type="application/smil+xml"/>
<item id="audio_001" href="content_001.mp3" media-type="audio/mpeg"/>
<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,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,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="uid"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata>
<dc:title>Title</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="uid">NOID</dc:identifier>
<meta property="dcterms:modified">2019-01-01T12:00:00Z</meta>
<meta property="media:active-class">class1 class2</meta>
<!-- Media Overlays Duration Properties -->
<meta property="media:duration">10min</meta>
<meta refines="#mo001" property="media:duration">10min</meta>
</metadata>
<manifest>
<item id="t001" href="contents.xhtml" properties="nav" media-type="application/xhtml+xml"/>
<item id="mo001" href="mediaoverlay_001.smil" media-type="application/smil+xml"/>
</manifest>
<spine>
<itemref idref="t001"/>
</spine>
</package>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<smil xmlns="http://www.w3.org/ns/SMIL" xmlns:epub="http://www.idpf.org/2007/ops" version="3.0">
<body>
<par id="par1">
<text src="content_001.xhtml#c01"/>
<audio src="content_001.mp3"/>
</par>
</body>
</smil>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta charset="utf-8" />
<title>Minimal EPUB</title>
</head>
<body>
<h1 id="c01">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,21 @@
<?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>
<meta property="media:duration">2.5s</meta>
<meta property="media:duration" refines="#mo_001">2.5s</meta>
<meta property="media:active-class">-epub-media-overlay-active</meta>
</metadata>
<manifest>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml" media-overlay="mo_001"/>
<item id="mo_001" href="content_001.smil" media-type="application/smil+xml"/>
<item id="audio_001" href="content_001.mp3" media-type="audio/mpeg"/>
<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,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
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<smil xmlns="http://www.w3.org/ns/SMIL" xmlns:epub="http://www.idpf.org/2007/ops" version="3.0">
<body>
<par id="par1">
<text src="content_001.xhtml#c01"/>
<audio src="content_001.mp3"/>
</par>
</body>
</smil>
Loading

0 comments on commit 6a58b8e

Please sign in to comment.