diff --git a/aio/package.json b/aio/package.json
index 0d58b16fa6..4015a08465 100644
--- a/aio/package.json
+++ b/aio/package.json
@@ -82,6 +82,7 @@
"lighthouse": "^1.6.3",
"lodash": "^4.17.4",
"protractor": "~5.1.0",
+ "rehype": "^4.0.0",
"remark": "^7.0.0",
"remark-autolink-headings": "^4.0.0",
"remark-html": "^6.0.0",
diff --git a/aio/tools/transforms/angular-base-package/index.js b/aio/tools/transforms/angular-base-package/index.js
index 6cd6b4b7fd..0ee75eb0ee 100644
--- a/aio/tools/transforms/angular-base-package/index.js
+++ b/aio/tools/transforms/angular-base-package/index.js
@@ -14,11 +14,12 @@ const linksPackage = require('../links-package');
const examplesPackage = require('../examples-package');
const targetPackage = require('../target-package');
const remarkPackage = require('../remark-package');
+const postProcessPackage = require('../post-process-package');
const { PROJECT_ROOT, DOCS_OUTPUT_PATH, TEMPLATES_PATH, requireFolder } = require('../config');
module.exports = new Package('angular-base', [
- jsdocPackage, nunjucksPackage, linksPackage, examplesPackage, targetPackage, remarkPackage
+ jsdocPackage, nunjucksPackage, linksPackage, examplesPackage, targetPackage, remarkPackage, postProcessPackage
])
// Register the processors
diff --git a/aio/tools/transforms/post-process-package/index.js b/aio/tools/transforms/post-process-package/index.js
new file mode 100644
index 0000000000..559bc57d55
--- /dev/null
+++ b/aio/tools/transforms/post-process-package/index.js
@@ -0,0 +1,5 @@
+var Package = require('dgeni').Package;
+var base = require('dgeni-packages/base');
+
+module.exports = new Package('post-process-package', [base])
+ .processor(require('./processors/post-process-html'));
diff --git a/aio/tools/transforms/post-process-package/processors/post-process-html.js b/aio/tools/transforms/post-process-package/processors/post-process-html.js
new file mode 100644
index 0000000000..ddd2387205
--- /dev/null
+++ b/aio/tools/transforms/post-process-package/processors/post-process-html.js
@@ -0,0 +1,37 @@
+const rehype = require('rehype');
+
+/**
+ * @dgProcessor postProcessHtml
+ *
+ * @description
+ * Use the rehype processing engine to manipulate the
+ * `renderedContent` HTML via rehype "plugins" that work with HTML ASTs (HASTs).
+ * See https://github.com/wooorm/rehype
+ *
+ * Each plugin is a factory function that will be called with the "rehype" engine as `this`.
+ * The factory should return a function that takes a HAST and returns a `boolean` or `undefined`.
+ * The HAST can be mutated by the this function.
+ * If `false` is returned then the processing stops with that plugin.
+ *
+ * @property docTypes {string[]} the `docTypes` of docs that should be post-processed
+ * @property plugins {Function[]} the rehype plugins that will modify the HAST.
+ *
+ */
+module.exports = function postProcessHtml() {
+ return {
+ $runAfter: ['docs-rendered'],
+ $runBefore: ['writing-files'],
+ docTypes: [],
+ plugins: [],
+ $process(docs) {
+ const engine = rehype()
+ .data('settings', { fragment: true });
+ this.plugins.forEach(plugin => engine.use(plugin));
+
+ docs
+ .filter(doc => this.docTypes.indexOf(doc.docType) !== -1)
+ .forEach(doc =>
+ doc.renderedContent = engine.processSync(doc.renderedContent).contents);
+ }
+ };
+};
diff --git a/aio/tools/transforms/post-process-package/processors/post-process-html.spec.js b/aio/tools/transforms/post-process-package/processors/post-process-html.spec.js
new file mode 100644
index 0000000000..4ec2854198
--- /dev/null
+++ b/aio/tools/transforms/post-process-package/processors/post-process-html.spec.js
@@ -0,0 +1,62 @@
+const testPackage = require('../../helpers/test-package');
+const Dgeni = require('dgeni');
+
+describe('postProcessHtml', function() {
+ let dgeni, injector, processor;
+
+ beforeEach(function() {
+ dgeni = new Dgeni([testPackage('post-process-package', true)]);
+ injector = dgeni.configureInjector();
+ processor = injector.get('postProcessHtml');
+ processor.docTypes = ['a', 'b'];
+ });
+
+ it('should be available from the injector', () => {
+ expect(processor).toBeDefined();
+ });
+
+ it('should only process docs that match the specified docTypes', () => {
+ const elements = [];
+ const captureFirstElement = ast => {
+ elements.push(ast.children[0].tagName);
+ };
+ processor.plugins = [() => captureFirstElement];
+
+ const docs = [
+ { docType: 'a', renderedContent: '' },
+ { docType: 'b', renderedContent: '' },
+ { docType: 'c', renderedContent: '' },
+ { docType: 'd', renderedContent: '' },
+ ];
+ processor.$process(docs);
+ expect(elements).toEqual(['a', 'b']);
+ });
+
+ it('should run all the plugins on each doc', () => {
+ const capitalizeFirstElement = ast => {
+ ast.children[0].tagName = ast.children[0].tagName.toUpperCase();
+ };
+ const addOneToFirstElement = ast => {
+ ast.children[0].tagName = ast.children[0].tagName + '1';
+ };
+ const elements = [];
+ const captureFirstElement = ast => {
+ elements.push(ast.children[0].tagName);
+ };
+
+ const docs = [
+ { docType: 'a', renderedContent: '' },
+ { docType: 'b', renderedContent: '' },
+ { docType: 'c', renderedContent: '' },
+ { docType: 'd', renderedContent: '' },
+ ];
+
+ processor.plugins = [
+ () => capitalizeFirstElement,
+ () => addOneToFirstElement,
+ () => captureFirstElement
+ ];
+ processor.$process(docs);
+ expect(elements).toEqual(['A1', 'B1']);
+ });
+});
diff --git a/aio/yarn.lock b/aio/yarn.lock
index 4f6eac49fd..02e08830e9 100644
--- a/aio/yarn.lock
+++ b/aio/yarn.lock
@@ -1219,7 +1219,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
-comma-separated-tokens@^1.0.1:
+comma-separated-tokens@^1.0.0, comma-separated-tokens@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.2.tgz#4b64717a2ee363af6dd39878336bd95e42d063e7"
dependencies:
@@ -3014,10 +3014,24 @@ hash.js@^1.0.0:
dependencies:
inherits "^2.0.1"
+hast-util-from-parse5@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-1.1.0.tgz#359cc339dc8ccf1dfaca41915ad63fd546130acd"
+ dependencies:
+ camelcase "^3.0.0"
+ has "^1.0.1"
+ hastscript "^3.0.0"
+ property-information "^3.1.0"
+ vfile-location "^2.0.0"
+
hast-util-is-element@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.0.0.tgz#3f7216978b2ae14d98749878782675f33be3ce00"
+hast-util-parse-selector@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.1.0.tgz#b55c0f4bb7bb2040c889c325ef87ab29c38102b4"
+
hast-util-sanitize@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-1.1.0.tgz#9b4bc3731043fe92e1253a9a4ca7bcc4148d06f2"
@@ -3046,6 +3060,16 @@ hast-util-whitespace@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-1.0.0.tgz#bd096919625d2936e1ff17bc4df7fd727f17ece9"
+hastscript@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-3.0.1.tgz#9edfab8839e6d67bc6835297a0bf9ba6ad7a00a9"
+ dependencies:
+ camelcase "^3.0.0"
+ comma-separated-tokens "^1.0.0"
+ hast-util-parse-selector "^2.0.0"
+ property-information "^3.0.0"
+ space-separated-tokens "^1.0.0"
+
hawk@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
@@ -4902,6 +4926,10 @@ parse5@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94"
+parse5@^2.1.5:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-2.2.3.tgz#0c4fc41c1000c5e6b93d48b03f8083837834e9f6"
+
parse5@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.2.tgz#05eff57f0ef4577fb144a79f8b9a967a6cc44510"
@@ -5324,7 +5352,7 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
-property-information@^3.1.0:
+property-information@^3.0.0, property-information@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/property-information/-/property-information-3.1.0.tgz#1581bf8a445dfbfef759775a86700e8dda18b4a1"
@@ -5623,6 +5651,29 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"
+rehype-parse@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-3.1.0.tgz#7f5227a597a3f39fc4b938646161539c444ee728"
+ dependencies:
+ hast-util-from-parse5 "^1.0.0"
+ parse5 "^2.1.5"
+ xtend "^4.0.1"
+
+rehype-stringify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/rehype-stringify/-/rehype-stringify-3.0.0.tgz#9fef0868213c2dce2f780b76f3d0488c85e819eb"
+ dependencies:
+ hast-util-to-html "^3.0.0"
+ xtend "^4.0.1"
+
+rehype@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/rehype/-/rehype-4.0.0.tgz#2ed92dd269bfa549f7108fd2c4f6f626d27c7be4"
+ dependencies:
+ rehype-parse "^3.0.0"
+ rehype-stringify "^3.0.0"
+ unified "^6.0.0"
+
relateurl@0.2.x:
version "0.2.7"
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"