build(aio): capture the h1 title and attach it to the document

The HTML post-processing now collects any h1
that is found in the renderedContent and attaches
it to the doc via the `doc.vFile.title` property.
This commit is contained in:
Peter Bacon Darwin 2017-05-30 22:24:20 +03:00 committed by Pete Bacon Darwin
parent 2f35392cd8
commit 4d5fa5c855
6 changed files with 62 additions and 8 deletions

View File

@ -107,6 +107,7 @@
"ts-node": "~2.0.0",
"tslint": "~4.5.0",
"typescript": "2.2.0",
"unist-util-filter": "^0.2.1",
"unist-util-source": "^1.0.1",
"unist-util-visit": "^1.1.1",
"vrsource-tslint-rules": "^4.0.1",

View File

@ -32,7 +32,7 @@ describe('addImageDimensions post-processor', () => {
processor.$process(docs);
expect(getImageDimensionsSpy).toHaveBeenCalledWith('base/path', 'a/b.jpg');
expect(getImageDimensionsSpy).toHaveBeenCalledWith('base/path', 'c/d.png');
expect(docs).toEqual([{
expect(docs).toEqual([jasmine.objectContaining({
docType: 'a',
renderedContent: `
<p>xxx</p>
@ -41,7 +41,7 @@ describe('addImageDimensions post-processor', () => {
<img src="c/d.png" width="30" height="40">
<p>zzz</p>
`
}]);
})]);
});
it('should log a warning for images with no src attribute', () => {
@ -51,10 +51,10 @@ describe('addImageDimensions post-processor', () => {
}];
processor.$process(docs);
expect(getImageDimensionsSpy).not.toHaveBeenCalled();
expect(docs).toEqual([{
expect(docs).toEqual([jasmine.objectContaining({
docType: 'a',
renderedContent: '<img attr="value">'
}]);
})]);
expect(log.warn).toHaveBeenCalled();
});
@ -70,10 +70,10 @@ describe('addImageDimensions post-processor', () => {
}];
processor.$process(docs);
expect(getImageDimensionsSpy).toHaveBeenCalled();
expect(docs).toEqual([{
expect(docs).toEqual([jasmine.objectContaining({
docType: 'a',
renderedContent: '<img src="missing">'
}]);
})]);
expect(log.warn).toHaveBeenCalled();
});
@ -88,14 +88,14 @@ describe('addImageDimensions post-processor', () => {
}];
processor.$process(docs);
expect(getImageDimensionsSpy).not.toHaveBeenCalled();
expect(docs).toEqual([{
expect(docs).toEqual([jasmine.objectContaining({
docType: 'a',
renderedContent: `
<img src="a/b.jpg" width="10">
<img src="c/d.jpg" height="10">
<img src="e/f.jpg" width="10" height="10">
`
}]);
})]);
});
function mockGetImageDimensions() {

View File

@ -1,6 +1,8 @@
const visit = require('unist-util-visit');
const is = require('hast-util-is-element');
const source = require('unist-util-source');
const toString = require('hast-util-to-string');
const filter = require('unist-util-filter');
module.exports = function h1CheckerPostProcessor() {
return (ast, file) => {
@ -8,11 +10,23 @@ module.exports = function h1CheckerPostProcessor() {
visit(ast, node => {
if (is(node, 'h1')) {
h1s.push(node);
file.title = getText(node);
}
});
if (h1s.length > 1) {
const h1Src = h1s.map(node => source(node, file)).join(', ');
file.fail(`More than one h1 found [${h1Src}]`);
}
};
};
function getText(h1) {
// Remove the aria-hidden anchor from the h1 node
const cleaned = filter(h1, node => !(
is(node, 'a') && node.properties &&
(node.properties.ariaHidden === 'true' || node.properties['aria-hidden'] === 'true')
));
return toString(cleaned);
}

View File

@ -46,4 +46,27 @@ describe('h1Checker postprocessor', () => {
};
expect(() => processor.$process([doc])).not.toThrow();
});
it('should attach the h1 text to the vFile', () => {
const doc = {
docType: 'a',
renderedContent: '<h1>Heading 1</h1>'
};
processor.$process([doc]);
expect(doc.vFile.title).toEqual('Heading 1');
});
it('should clean aria-hidden anchors from h1 text added to the vFile', () => {
const doc = {
docType: 'a',
renderedContent:
'<h1 class="no-toc" id="what-is-angular">' +
'<a title="Link to this heading" class="header-link" aria-hidden="true" href="docs#what-is-angular">' +
'<i class="material-icons">link</i>' +
'</a>What is Angular?' +
'</h1>'
};
processor.$process([doc]);
expect(doc.vFile.title).toEqual('What is Angular?');
});
});

View File

@ -39,6 +39,7 @@ module.exports = function postProcessHtml(log, createDocMessage) {
vFile.messages.forEach(m => {
log.warn(createDocMessage(m.message, doc));
});
doc.vFile = vFile;
} catch(e) {
throw new Error(createDocMessage(e.message, doc));
}

View File

@ -2705,6 +2705,10 @@ flat-cache@^1.2.1:
graceful-fs "^4.1.2"
write "^0.2.1"
flatmap@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/flatmap/-/flatmap-0.0.3.tgz#1f18a4d938152d495965f9c958d923ab2dd669b4"
flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
@ -7256,10 +7260,21 @@ unist-builder@^1.0.1:
dependencies:
object-assign "^4.1.0"
unist-util-filter@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/unist-util-filter/-/unist-util-filter-0.2.1.tgz#e2f7876828903a6a9308e362051f86b14f35b545"
dependencies:
flatmap "0.0.3"
unist-util-is "^1.0.0"
unist-util-generated@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.0.tgz#8c95657ff12b32eaffe0731fbb37da6995fae01b"
unist-util-is@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-1.0.0.tgz#4c7b3c5c0f6aa963640056fe4af7b5fcfdbb8ef0"
unist-util-is@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-2.0.0.tgz#e536472c4f78739e164d0859fc3201b97cf46e7c"