angular-cn/aio/tools/transforms/examples-package/processors/render-examples.js

80 lines
3.4 KiB
JavaScript

const { parseAttributes, renderAttributes } = require('../../helpers/utils');
/**
* Search the renderedContent looking for code examples that have a path (and optionally a region) attribute.
* When they are found replace their content with the appropriate doc-region parsed previously from an example file.
*/
module.exports = function renderExamples(getExampleRegion, log, createDocMessage) {
return {
$runAfter: ['docs-rendered'],
$runBefore: ['writing-files'],
ignoreBrokenExamples: false,
$process: function(docs) {
const titleVsHeaderErrors = [];
docs.forEach(doc => {
if (doc.renderedContent) {
// We match either `code-example` or `code-pane` elements that have a path attribute
doc.renderedContent = doc.renderedContent.replace(
/<(code-example|code-pane)([^>]*)>[^<]*<\/([^>]+)>/g,
(original, openingTag, attributes, closingTag) => {
const attrMap = parseAttributes(attributes);
if (attrMap.hasOwnProperty('title')) {
titleVsHeaderErrors.push(createDocMessage(
`Using the "title" attribute for specifying a ${openingTag} header is no longer supported. ` +
`Use the "header" attribute instead.\n<${openingTag}${attributes}>`, doc));
return;
}
if (attrMap.path) {
try {
if (closingTag !== openingTag) {
// The markdown renderer will wrap what it thinks is a paragraph in `<p>` and `</p>` tags.
// If you do not leave a blank line between a paragraph of text and a `<code-example>` then
// the markdown renderer may add a paragraph marker "in-between" the opening and closing
// tags of the code-example. For example:
//
// ```
// Some paragraph
// <code-example path="...">
//
// </code-example>
// ```
//
// will be rendered as:
//
// ```
// <p>Some paragraph
// <code-example path="...">
// </p>
// </code-example>
// ```
throw new Error(
'Badly formed example: ' + original + ' - closing tag does not match opening tag.\n' +
' - Perhaps you forgot to put a blank line before the example?');
}
// We found a path attribute so look up the example and rebuild the HTML
const exampleContent = getExampleRegion(doc, attrMap.path, attrMap.region);
return `<${openingTag}${renderAttributes(attrMap)}>\n${exampleContent}\n</${openingTag}>`;
} catch(e) {
log.warn(createDocMessage(e.message, doc));
if (!this.ignoreBrokenExamples) {
throw e;
}
}
}
// No path attribute so just ignore this one
return original;
});
}
});
if (titleVsHeaderErrors.length) {
titleVsHeaderErrors.forEach(err => log.error(err));
throw new Error('Some code snippets use the `title` attribute instead of `header`.');
}
}
};
};