Skip to content

Commit

Permalink
feat(data): extract and report link info from the Package Document (#130
Browse files Browse the repository at this point in the history
)

Publication links (defined as `link` elements in the Package Document) are extracted
and copied under a new `links` property of the `earl:testSubject` object.

For instance, the following OPF snippet:

```
<link rel="a11y:certifierReport" href="http://www.example.com/report.html"/>
```

Would be reported as:

```
"earl:testSubject" {
  …
  "links": {
    "a11y:certifierReport": "http://www.example.com/report.html"
  }
}
```

Only publication-level links (i.e. with no `refines` attribute) are extracted.

Fixes #96
  • Loading branch information
rdeltour authored Dec 20, 2017
1 parent fd80592 commit a010744
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 12 deletions.
7 changes: 4 additions & 3 deletions packages/ace-report/src/report-builders.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ function withAssertions(obj, assertions) {
return obj;
}

function withTestSubject(obj, url, title = '', identifier = '', metadata = null) {
function withTestSubject(obj, url, title = '', identifier = '', metadata = null, links = null) {
const testSubject = { url };
if (title.length > 0) testSubject['dct:title'] = title;
if (identifier.length > 0) testSubject['dct:identifier'] = identifier;
if (metadata !== undefined && metadata != null) testSubject.metadata = metadata;
if (links !== undefined && links != null) testSubject.links = links;
obj['earl:testSubject'] = testSubject;
return obj;
}
Expand Down Expand Up @@ -149,8 +150,8 @@ class ReportBuilder {
});
return this;
}
withTestSubject(url, title, identifier, metadata) {
withTestSubject(this._json, url, title, identifier, metadata);
withTestSubject(url, title, identifier, metadata, links) {
withTestSubject(this._json, url, title, identifier, metadata, links);
return this;
}
}
Expand Down
73 changes: 70 additions & 3 deletions packages/ace-report/src/report-builders.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ describe('report builder', () => {
});
});
});
describe('adding assertions', () => {

describe('withAssertions', () => {
let assertions;
test('adding null assertion is ignored', () => {
expect(report.withAssertions(null)).toBeDefined();
Expand Down Expand Up @@ -119,7 +120,8 @@ describe('report builder', () => {
expect(assertions[1]).toEqual({ foo: 'foo' });
});
});
describe('adding data', () => {

describe('withData', () => {
let data;
beforeEach(() => {
data = report.build().data;
Expand Down Expand Up @@ -152,7 +154,8 @@ describe('report builder', () => {
expect(data).toEqual({ foo: ['foo', 'bar'] });
});
});
describe('adding properties', () => {

describe('withProperties', () => {
let properties;
beforeEach(() => {
properties = report.build().properties;
Expand Down Expand Up @@ -189,4 +192,68 @@ describe('report builder', () => {
expect(properties).toEqual({ foo: true });
});
});

describe('withTestSubject', () => {
test('with URL', () => {
expect(report.withTestSubject('https://example.com')).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com'
})
});
test('with title', () => {
expect(report.withTestSubject('https://example.com', 'title')).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com',
'dct:title': 'title',
})
});
test('with identifier', () => {
expect(report.withTestSubject('https://example.com', '', 'uid')).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com',
'dct:identifier': 'uid',
})
});
test('with metadata null', () => {
expect(report.withTestSubject('https://example.com', '', '', null)).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com',
})
});
test('with metadata', () => {
expect(report.withTestSubject('https://example.com', '', '', { foo: 'bar' })).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com',
metadata: { foo: 'bar' }
})
});

test('with link null', () => {
expect(report.withTestSubject('https://example.com', '', '', null, null)).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com',
})
});
test('with links', () => {
expect(report.withTestSubject('https://example.com', '', '', null, { foo: 'bar' })).toBeDefined();
const testSubject = report.build()['earl:testSubject'];
expect(testSubject).toBeDefined();
expect(testSubject).toEqual({
url: 'https://example.com',
links: { foo: 'bar' }
})
});
});
});
8 changes: 2 additions & 6 deletions packages/ace-report/src/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ function aggregateHTMLOutlines(outlines) {
module.exports = class Report {
constructor(epub) {
this._builder = new builders.ReportBuilder()
.withTestSubject(epub.path, '', '', epub.metadata)
.withA11yMeta(a11yMetaChecker.analyze(epub.metadata));
.withTestSubject(epub.path, '', '', epub.metadata, epub.links)
.withA11yMeta(a11yMetaChecker.analyze(epub.metadata))
}

get json() {
Expand All @@ -56,10 +56,6 @@ module.exports = class Report {
addData(data) {
this._builder.withData(data);
}
addOutline(outline) {
this._builder.withHOutline(outline);
return this;
}
addHeadings(headings) {
this._builder.withHeadingsOutline(headingsToOutline(headings));
return this;
Expand Down
19 changes: 19 additions & 0 deletions packages/epub-utils/src/epub-parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,24 @@ function parseMetadata(doc, select) {
return result;
}


function addLink(rel, href, link) {
if (!link[rel]) {
link[rel] = href;
} else if (!(link[rel] instanceof Array)) {
link[rel] = [link[rel], href];
} else {
link[rel].push(href);
}
}
function parseLinks(doc, select) {
const result = {};
select('//opf:link[not(@refines)]', doc).forEach((link) => {
addLink(link.getAttribute('rel'), link.getAttribute('href'), result);
});
return result;
}

// override the default of XHTML
EpubParser.prototype.setContentDocMediaType = function(mediaType) {
this.contentDocMediaType = mediaType;
Expand Down Expand Up @@ -114,6 +132,7 @@ EpubParser.prototype.parseData = function(packageDocPath, epubDir) {
{ opf: 'http://www.idpf.org/2007/opf',
dc: 'http://purl.org/dc/elements/1.1/'});
this.metadata = parseMetadata(doc, select);
this.links = parseLinks(doc, select);

const spineItemIdrefs = select('//opf:itemref/@idref', doc);
spineItemIdrefs.forEach((idref) => {
Expand Down
9 changes: 9 additions & 0 deletions tests/__tests__/report_json.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ describe('check data', () => {
});
});

test('extract links', async () => {
const report = await ace(path.join(__dirname, '../data/feat-links'));
expect(report['earl:testSubject']).toMatchObject({
links: {
"a11y:certifierReport": "http://www.example.com/report.html"
},
});
});

test('extract videos', async () => {
const report = await ace(path.join(__dirname, '../data/feat-video'));
expect(report.data).toMatchObject({
Expand Down
9 changes: 9 additions & 0 deletions tests/data/feat-links/EPUB/content_001.xhtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en">
<head>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
</body>
</html>
12 changes: 12 additions & 0 deletions tests/data/feat-links/EPUB/nav.xhtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en">
<head>
<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>
25 changes: 25 additions & 0 deletions tests/data/feat-links/EPUB/package.opf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="uid"
prefix="a11y: http://www.idpf.org/epub/vocab/package/a11y/#">
<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="uid">NOID</dc:identifier>
<meta property="dcterms:modified">2017-01-01T00:00:01Z</meta>
<meta property="schema:accessibilityFeature">structuralNavigation</meta>
<meta property="schema:accessibilitySummary">everything OK!</meta>
<meta property="schema:accessibilityHazard">noFlashingHazard</meta>
<meta property="schema:accessibilityHazard">noSoundHazard</meta>
<meta property="schema:accessibilityHazard">noMotionSimulationHazard</meta>
<meta property="schema:accessMode">textual</meta>
<meta property="schema:accessModeSufficient">textual</meta>
<link rel="a11y:certifierReport" href="http://www.example.com/report.html"/>
</metadata>
<manifest>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
</manifest>
<spine>
<itemref idref="content_001" />
</spine>
</package>
6 changes: 6 additions & 0 deletions tests/data/feat-links/META-INF/container.xml
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>
1 change: 1 addition & 0 deletions tests/data/feat-links/mimetype
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
application/epub+zip

0 comments on commit a010744

Please sign in to comment.