From 77309e2ea4040038c3eca9c0ae46842c5f7bd647 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Fri, 18 May 2018 15:07:11 +0100 Subject: [PATCH] build(aio): map H3 headings into H4 headings for certain templates (#24000) The sections such as methods and decorator options are already headed by a H3 heading so we need to map the H3 headings in the API doc source down to H4 headings. This commit includes general heading mapping functionality accessible via the `marked` Nunjucks filter. PR Close #24000 --- aio/tools/transforms/remark-package/index.js | 2 +- .../services/markedNunjucksFilter.js | 12 +++++++ .../services/plugins/mapHeadings.js | 31 ++++++++++++++++++ .../remark-package/services/renderMarkdown.js | 26 ++++++++------- .../services/renderMarkdown.spec.js | 32 +++++++++++++++++++ .../templates/api/lib/memberHelpers.html | 20 +++++++++--- 6 files changed, 107 insertions(+), 16 deletions(-) create mode 100644 aio/tools/transforms/remark-package/services/markedNunjucksFilter.js create mode 100644 aio/tools/transforms/remark-package/services/plugins/mapHeadings.js diff --git a/aio/tools/transforms/remark-package/index.js b/aio/tools/transforms/remark-package/index.js index 67b7acc318..1ef0fe2746 100644 --- a/aio/tools/transforms/remark-package/index.js +++ b/aio/tools/transforms/remark-package/index.js @@ -5,5 +5,5 @@ var Package = require('dgeni').Package; * @description Overrides the renderMarkdown service with an implementation based on remark */ module.exports = new Package('remark', ['nunjucks']) - + .factory(require('./services/markedNunjucksFilter')) .factory(require('./services/renderMarkdown')); diff --git a/aio/tools/transforms/remark-package/services/markedNunjucksFilter.js b/aio/tools/transforms/remark-package/services/markedNunjucksFilter.js new file mode 100644 index 0000000000..11dae32016 --- /dev/null +++ b/aio/tools/transforms/remark-package/services/markedNunjucksFilter.js @@ -0,0 +1,12 @@ +/** + * Convert the value, as markdown, into HTML + * @param headingMappings A map of headings to convert (e.g. from h3 to h4). + */ +module.exports = function markedNunjucksFilter(renderMarkdown) { + return { + name: 'marked', + process: function(str, headingMappings) { + return str && renderMarkdown(str, headingMappings); + } + }; +}; \ No newline at end of file diff --git a/aio/tools/transforms/remark-package/services/plugins/mapHeadings.js b/aio/tools/transforms/remark-package/services/plugins/mapHeadings.js new file mode 100644 index 0000000000..e00ee7c775 --- /dev/null +++ b/aio/tools/transforms/remark-package/services/plugins/mapHeadings.js @@ -0,0 +1,31 @@ +const visit = require('unist-util-visit'); + +function headingToLevel(heading) { + const match = /^h(\d+)/.exec(heading); + return match ? match[1] : '0'; +} + +function parseMappings(mappings) { + const mapping = {}; + Object.keys(mappings).forEach(key => mapping[headingToLevel(key)] = headingToLevel(mappings[key])); + return mapping; +} + +module.exports = function mapHeadings(mappings) { + const headings = parseMappings(mappings || {}); + return () => ast => { + const nodesToFix = []; + Object.keys(headings).forEach(heading => { + visit(ast, 'heading', node => { + if (node.depth === Number(heading)) { + nodesToFix.push(node); + } + }); + }); + + // Update the depth of the matched nodes + nodesToFix.forEach(node => node.depth = headings[node.depth]); + + return ast; + }; +}; diff --git a/aio/tools/transforms/remark-package/services/renderMarkdown.js b/aio/tools/transforms/remark-package/services/renderMarkdown.js index c68701e119..4bdaf90021 100644 --- a/aio/tools/transforms/remark-package/services/renderMarkdown.js +++ b/aio/tools/transforms/remark-package/services/renderMarkdown.js @@ -1,25 +1,29 @@ const remark = require('remark'); const html = require('remark-html'); const code = require('./handlers/code'); +const mapHeadings = require('./plugins/mapHeadings'); /** * @dgService renderMarkdown * @description * Render the markdown in the given string as HTML. + * @param headingMap A map of headings to convert. + * E.g. `{h3: 'h4'} will map heading 3 level into heading 4. */ module.exports = function renderMarkdown() { - const handlers = { code }; - const renderer = remark() - .use(inlineTagDefs) - .use(noIndentedCodeBlocks) - .use(plainHTMLBlocks) - // USEFUL DEBUGGING CODE - // .use(() => tree => { - // console.log(require('util').inspect(tree, { colors: true, depth: 4 })); - // }) - .use(html, { handlers }); + return function renderMarkdownImpl(content, headingMap) { + + const renderer = remark() + .use(inlineTagDefs) + .use(noIndentedCodeBlocks) + .use(plainHTMLBlocks) + // USEFUL DEBUGGING CODE + // .use(() => tree => { + // console.log(require('util').inspect(tree, { colors: true, depth: 4 })); + // }) + .use(mapHeadings(headingMap)) + .use(html, { handlers: { code } }); - return function renderMarkdownImpl(content) { return renderer.processSync(content).toString(); }; diff --git a/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js b/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js index d9afc6c762..973a9c8008 100644 --- a/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js +++ b/aio/tools/transforms/remark-package/services/renderMarkdown.spec.js @@ -95,4 +95,36 @@ describe('remark: renderMarkdown service', () => { '\n' ); }); + + it('should map heading levels as specified', () => { + const content = + '# heading 1\n' + + '\n' + + 'some paragraph\n' + + '\n' + + '## heading 2a\n' + + '\n' + + 'some paragraph\n' + + '\n' + + '### heading 3\n' + + '\n' + + 'some paragraph\n' + + '\n' + + '## heading 2b\n' + + '\n' + + 'some paragraph\n' + + '\n'; + const headingMappings = { h2: 'h3', h3: 'h5' }; + const output = renderMarkdown(content, headingMappings); + expect(output).toEqual( + '

heading 1

\n' + + '

some paragraph

\n' + + '

heading 2a

\n' + + '

some paragraph

\n' + + '
heading 3
\n' + + '

some paragraph

\n' + + '

heading 2b

\n' + + '

some paragraph

\n' + ); + }); }); diff --git a/aio/tools/transforms/templates/api/lib/memberHelpers.html b/aio/tools/transforms/templates/api/lib/memberHelpers.html index 2fdfb3b6e4..15146f8755 100644 --- a/aio/tools/transforms/templates/api/lib/memberHelpers.html +++ b/aio/tools/transforms/templates/api/lib/memberHelpers.html @@ -113,12 +113,24 @@ {% endif %} - {% if method.description %} + + {% if method.description -%} + - {$ method.description | marked $} + {$ method.description | marked({ h3: 'h4' }) $} - {% endif %} - + + {%- endif %} + + {% if method.usageNotes -%} + + +

Usage Notes

+ {$ method.usageNotes | marked({ h3: 'h4' }) $} + + + {%- endif %} + {% endmacro -%}