build(aio): automatically link code blocks to API docs

This commit is contained in:
Peter Bacon Darwin 2017-05-10 18:34:19 +01:00 committed by Pete Bacon Darwin
parent ecc356ecea
commit a9d9aa18a0
6 changed files with 86 additions and 2 deletions

View File

@ -73,6 +73,7 @@
"fs-extra": "^2.1.2",
"globby": "^6.1.0",
"hast-util-is-element": "^1.0.0",
"hast-util-to-string": "^1.0.0",
"html": "^1.0.0",
"http-server": "^0.9.0",
"image-size": "^0.5.1",

View File

@ -235,3 +235,8 @@ code-tabs md-tab-group *.mat-ripple-element, code-tabs md-tab-group *.mat-tab-bo
[role="tabpanel"] {
transition: none;
}
.sidenav-content code a {
color: inherit;
font-size: inherit;
}

View File

@ -114,10 +114,11 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage])
})
.config(function(convertToJsonProcessor, postProcessHtml, EXPORT_DOC_TYPES) {
.config(function(convertToJsonProcessor, postProcessHtml, EXPORT_DOC_TYPES, autoLinkCode) {
const DOCS_TO_CONVERT = EXPORT_DOC_TYPES.concat([
'decorator', 'directive', 'pipe', 'module'
]);
convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT);
postProcessHtml.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT);
autoLinkCode.docTypes = DOCS_TO_CONVERT;
});

View File

@ -37,6 +37,7 @@ module.exports = new Package('angular-base', [
.factory(require('./services/getImageDimensions'))
.factory(require('./post-processors/add-image-dimensions'))
.factory(require('./post-processors/auto-link-code'))
.config(function(checkAnchorLinksProcessor) {
// This is disabled here to prevent false negatives for the `docs-watch` task.
@ -123,12 +124,13 @@ module.exports = new Package('angular-base', [
})
.config(function(postProcessHtml, addImageDimensions) {
.config(function(postProcessHtml, addImageDimensions, autoLinkCode) {
addImageDimensions.basePath = path.resolve(AIO_PATH, 'src');
postProcessHtml.plugins = [
require('./post-processors/autolink-headings'),
addImageDimensions,
require('./post-processors/h1-checker'),
autoLinkCode,
];
})

View File

@ -0,0 +1,36 @@
const visit = require('unist-util-visit');
const is = require('hast-util-is-element');
const textContent = require('hast-util-to-string');
/**
* Automatically add in a link to the relevant document for simple
* code blocks, e.g. `<code>MyClass</code>` becomes
* `<code><a href="path/to/myclass">MyClass</a></code>`
*
* @property docTypes an array of strings. Only docs that have one of these docTypes
* will be linked to.
* Usually set to the API exported docTypes, e.g. "class", "function", "directive", etc.
*/
module.exports = function autoLinkCode(getDocFromAlias) {
autoLinkCodeImpl.docTypes = [];
return autoLinkCodeImpl;
function autoLinkCodeImpl() {
return (ast) => {
visit(ast, node => {
if (is(node, 'code')) {
const docs = getDocFromAlias(textContent(node));
if (docs.length === 1 && autoLinkCodeImpl.docTypes.indexOf(docs[0].docType) !== -1) {
const link = {
type: 'element',
tagName: 'a',
properties: { href: docs[0].path },
children: node.children
};
node.children = [link];
}
}
});
};
}
};

View File

@ -0,0 +1,39 @@
var createTestPackage = require('../../helpers/test-package');
var Dgeni = require('dgeni');
describe('autoLinkCode post-processor', () => {
let processor, autoLinkCode, aliasMap;
beforeEach(() => {
const testPackage = createTestPackage('angular-base-package');
const dgeni = new Dgeni([testPackage]);
const injector = dgeni.configureInjector();
autoLinkCode = injector.get('autoLinkCode');
autoLinkCode.docTypes = ['class', 'pipe'];
aliasMap = injector.get('aliasMap');
processor = injector.get('postProcessHtml');
processor.docTypes = ['test-doc'];
processor.plugins = [autoLinkCode];
});
it('should insert an anchor into every code item that matches the id of an API doc', () => {
aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });
const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code><a href="a/b/myclass">MyClass</a></code>');
});
it('should insert an anchor into every code item that matches an alias of an API doc', () => {
aliasMap.addDoc({ docType: 'class', id: 'MyClass', aliases: ['MyClass', 'foo.MyClass'], path: 'a/b/myclass' });
const doc = { docType: 'test-doc', renderedContent: '<code>foo.MyClass</code>' };
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code><a href="a/b/myclass">foo.MyClass</a></code>');
});
it('should ignore code items that do not match a link to an API doc', () => {
aliasMap.addDoc({ docType: 'guide', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' });
const doc = { docType: 'test-doc', renderedContent: '<code>MyClass</code>' };
processor.$process([doc]);
expect(doc.renderedContent).toEqual('<code>MyClass</code>');
});
});