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
This commit is contained in:
parent
e371b226fa
commit
77309e2ea4
|
@ -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'));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -95,4 +95,36 @@ describe('remark: renderMarkdown service', () => {
|
|||
'</code-example>\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(
|
||||
'<h1>heading 1</h1>\n' +
|
||||
'<p>some paragraph</p>\n' +
|
||||
'<h3>heading 2a</h3>\n' +
|
||||
'<p>some paragraph</p>\n' +
|
||||
'<h5>heading 3</h5>\n' +
|
||||
'<p>some paragraph</p>\n' +
|
||||
'<h3>heading 2b</h3>\n' +
|
||||
'<p>some paragraph</p>\n'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -113,12 +113,24 @@
|
|||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if method.description %}<tr>
|
||||
|
||||
{% if method.description -%}
|
||||
<tr>
|
||||
<td class="description">
|
||||
{$ method.description | marked $}
|
||||
{$ method.description | marked({ h3: 'h4' }) $}
|
||||
</td>
|
||||
</tr>{% endif %}
|
||||
</tbody>
|
||||
</tr>
|
||||
{%- endif %}
|
||||
|
||||
{% if method.usageNotes -%}
|
||||
<tr>
|
||||
<td class="usage-notes">
|
||||
<h3>Usage Notes</h3>
|
||||
{$ method.usageNotes | marked({ h3: 'h4' }) $}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endmacro -%}
|
||||
|
||||
|
|
Loading…
Reference in New Issue