build(docs-infra): throw error if using `title` on code snippets (#26514)
Since #26396, the `title` property is ignored and `header` should be used instead for specifying a code snippet's header. This commit ensures that we don't accidentally set `title` have it be silently ignored. PR Close #26514
This commit is contained in:
parent
d557f1d9de
commit
0add00a743
|
@ -31,9 +31,15 @@ module.exports = function exampleInlineTagDef(parseArgString, createDocMessage,
|
||||||
const sourceCode = getExampleRegion(doc, relativePath, regionName);
|
const sourceCode = getExampleRegion(doc, relativePath, regionName);
|
||||||
|
|
||||||
const attributes = [];
|
const attributes = [];
|
||||||
|
if (relativePath) attributes.push(` path="${relativePath}"`);
|
||||||
|
if (regionName) attributes.push(` region="${regionName}"`);
|
||||||
if (header) attributes.push(` header="${header}"`);
|
if (header) attributes.push(` header="${header}"`);
|
||||||
if (linenums !== undefined) attributes.push(` linenums="${linenums}"`);
|
if (linenums !== undefined) attributes.push(` linenums="${linenums}"`);
|
||||||
|
|
||||||
|
// Preserve the no-longer-supported `title` attribute,
|
||||||
|
// in order to throw an appropriate error in `renderExamples` later.
|
||||||
|
if (tagArgs.title) attributes.push(` title="${tagArgs.title}"`);
|
||||||
|
|
||||||
return '<code-example' + attributes.join('') + '>\n' + sourceCode + '\n</code-example>';
|
return '<code-example' + attributes.join('') + '>\n' + sourceCode + '\n</code-example>';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,27 +42,40 @@ describe('example inline-tag-def', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the whole contents from the example file if no region is specified', () => {
|
it('should contain the whole contents from the example file if no region is specified', () => {
|
||||||
expect(handler({}, 'example', 'test/url')).toEqual('<code-example>\nwhole file\n</code-example>');
|
expect(handler({}, 'example', 'test/url')).toEqual('<code-example path="test/url">\nwhole file\n</code-example>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the region contents from the example file if a region is specified', () => {
|
it('should contain the region contents from the example file if a region is specified', () => {
|
||||||
expect(handler({}, 'example', 'test/url region-1')).toEqual('<code-example>\nregion 1 contents\n</code-example>');
|
expect(handler({}, 'example', 'test/url region-1')).toEqual(
|
||||||
|
'<code-example path="test/url" region="region-1">\nregion 1 contents\n</code-example>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add a header if specified', () => {
|
it('should add a header if specified', () => {
|
||||||
expect(handler({}, 'example', 'test/url region-1 \'Some Header\'')).toEqual('<code-example header="Some Header">\nregion 1 contents\n</code-example>');
|
expect(handler({}, 'example', 'test/url region-1 \'Some Header\'')).toEqual(
|
||||||
expect(handler({}, 'example', 'test/url region-1 Some Header')).toEqual('<code-example header="Some Header">\nregion 1 contents\n</code-example>');
|
'<code-example path="test/url" region="region-1" header="Some Header">\nregion 1 contents\n</code-example>');
|
||||||
|
expect(handler({}, 'example', 'test/url region-1 Some Header')).toEqual(
|
||||||
|
'<code-example path="test/url" region="region-1" header="Some Header">\nregion 1 contents\n</code-example>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain the whole contents from the example file if an empty ("") region is specified', () => {
|
it('should contain the whole contents from the example file if an empty ("") region is specified', () => {
|
||||||
expect(handler({}, 'example', 'test/url \'\'')).toEqual('<code-example>\nwhole file\n</code-example>');
|
expect(handler({}, 'example', 'test/url \'\'')).toEqual(
|
||||||
expect(handler({}, 'example', 'test/url \'\' Some Header')).toEqual('<code-example header="Some Header">\nwhole file\n</code-example>');
|
'<code-example path="test/url">\nwhole file\n</code-example>');
|
||||||
|
expect(handler({}, 'example', 'test/url \'\' Some Header')).toEqual(
|
||||||
|
'<code-example path="test/url" header="Some Header">\nwhole file\n</code-example>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add in linenum attribute if specified', () => {
|
it('should add in linenum attribute if specified', () => {
|
||||||
expect(handler({}, 'example', 'test/url --linenums=\'false\'')).toEqual('<code-example linenums="false">\nwhole file\n</code-example>');
|
expect(handler({}, 'example', 'test/url --linenums=\'false\'')).toEqual(
|
||||||
expect(handler({}, 'example', 'test/url --linenums=\'true\'')).toEqual('<code-example linenums="true">\nwhole file\n</code-example>');
|
'<code-example path="test/url" linenums="false">\nwhole file\n</code-example>');
|
||||||
expect(handler({}, 'example', 'test/url --linenums=\'15\'')).toEqual('<code-example linenums="15">\nwhole file\n</code-example>');
|
expect(handler({}, 'example', 'test/url --linenums=\'true\'')).toEqual(
|
||||||
|
'<code-example path="test/url" linenums="true">\nwhole file\n</code-example>');
|
||||||
|
expect(handler({}, 'example', 'test/url --linenums=\'15\'')).toEqual(
|
||||||
|
'<code-example path="test/url" linenums="15">\nwhole file\n</code-example>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should preserve the title if specified', () => {
|
||||||
|
expect(handler({}, 'example', 'test/url title="Some Title"')).toEqual(
|
||||||
|
'<code-example path="test/url" title="Some Title">\nwhole file\n</code-example>');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,8 @@ module.exports = function renderExamples(getExampleRegion, log, createDocMessage
|
||||||
$runBefore: ['writing-files'],
|
$runBefore: ['writing-files'],
|
||||||
ignoreBrokenExamples: false,
|
ignoreBrokenExamples: false,
|
||||||
$process: function(docs) {
|
$process: function(docs) {
|
||||||
|
const titleVsHeaderErrors = [];
|
||||||
|
|
||||||
docs.forEach(doc => {
|
docs.forEach(doc => {
|
||||||
if (doc.renderedContent) {
|
if (doc.renderedContent) {
|
||||||
// We match either `code-example` or `code-pane` elements that have a path attribute
|
// We match either `code-example` or `code-pane` elements that have a path attribute
|
||||||
|
@ -17,6 +19,14 @@ module.exports = function renderExamples(getExampleRegion, log, createDocMessage
|
||||||
/<(code-example|code-pane)([^>]*)>[^<]*<\/([^>]+)>/g,
|
/<(code-example|code-pane)([^>]*)>[^<]*<\/([^>]+)>/g,
|
||||||
(original, openingTag, attributes, closingTag) => {
|
(original, openingTag, attributes, closingTag) => {
|
||||||
const attrMap = parseAttributes(attributes);
|
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) {
|
if (attrMap.path) {
|
||||||
try {
|
try {
|
||||||
if (closingTag !== openingTag) {
|
if (closingTag !== openingTag) {
|
||||||
|
@ -59,6 +69,11 @@ module.exports = function renderExamples(getExampleRegion, log, createDocMessage
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (titleVsHeaderErrors.length) {
|
||||||
|
titleVsHeaderErrors.forEach(err => log.error(err));
|
||||||
|
throw new Error('Some code snippets use the `title` attribute instead of `header`.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,10 +84,10 @@ describe('renderExamples processor', () => {
|
||||||
|
|
||||||
it('should cope with spaces and double quotes inside attribute values', () => {
|
it('should cope with spaces and double quotes inside attribute values', () => {
|
||||||
const docs = [
|
const docs = [
|
||||||
{ renderedContent: `<${CODE_TAG} title='a "quoted" value' path="test/url"></${CODE_TAG}>`}
|
{ renderedContent: `<${CODE_TAG} header='a "quoted" value' path="test/url"></${CODE_TAG}>`}
|
||||||
];
|
];
|
||||||
processor.$process(docs);
|
processor.$process(docs);
|
||||||
expect(docs[0].renderedContent).toEqual(`<${CODE_TAG} title="a "quoted" value" path="test/url">\nwhole file\n</${CODE_TAG}>`);
|
expect(docs[0].renderedContent).toEqual(`<${CODE_TAG} header="a "quoted" value" path="test/url">\nwhole file\n</${CODE_TAG}>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an exception if the code-example tag is not closed correctly', () => {
|
it('should throw an exception if the code-example tag is not closed correctly', () => {
|
||||||
|
@ -117,6 +117,55 @@ describe('renderExamples processor', () => {
|
||||||
'Missing example file... relativePath: "missing/url". - doc\n' +
|
'Missing example file... relativePath: "missing/url". - doc\n' +
|
||||||
'Example files can be found in the following relative paths: "examples" - doc');
|
'Example files can be found in the following relative paths: "examples" - doc');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw an exception if any code-example tag has a `title` attribute', () => {
|
||||||
|
const docs = [
|
||||||
|
{
|
||||||
|
name: 'Document A',
|
||||||
|
renderedContent: `
|
||||||
|
Example 1: <${CODE_TAG} path="test/url" header="This is a header "></${CODE_TAG}>
|
||||||
|
Example 2: <${CODE_TAG} path="test/url" title="This is a title 2"></${CODE_TAG}>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Document B',
|
||||||
|
renderedContent: `
|
||||||
|
Example 3: <${CODE_TAG} path="test/url" title="This is a title 3"></${CODE_TAG}>
|
||||||
|
Example 4: <${CODE_TAG} path="test/url" header="This is a header 4"></${CODE_TAG}>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(() => processor.$process(docs)).toThrowError(
|
||||||
|
'Some code snippets use the `title` attribute instead of `header`.');
|
||||||
|
|
||||||
|
expect(log.error).toHaveBeenCalledTimes(2);
|
||||||
|
expect(log.error).toHaveBeenCalledWith(
|
||||||
|
`Using the "title" attribute for specifying a ${CODE_TAG} header is no longer supported. ` +
|
||||||
|
'Use the "header" attribute instead.\n' +
|
||||||
|
`<${CODE_TAG} path="test/url" title="This is a title 2"> - doc "Document A"`);
|
||||||
|
expect(log.error).toHaveBeenCalledWith(
|
||||||
|
`Using the "title" attribute for specifying a ${CODE_TAG} header is no longer supported. ` +
|
||||||
|
'Use the "header" attribute instead.\n' +
|
||||||
|
`<${CODE_TAG} path="test/url" title="This is a title 3"> - doc "Document B"`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception for `title` attribute even if `ignoreBrokenExamples` is set to true', () => {
|
||||||
|
processor.ignoreBrokenExamples = true;
|
||||||
|
const docs = [
|
||||||
|
{ renderedContent: `<${CODE_TAG} path="test/url" title="This is a title"></${CODE_TAG}>` },
|
||||||
|
];
|
||||||
|
expect(() => processor.$process(docs)).toThrowError(
|
||||||
|
'Some code snippets use the `title` attribute instead of `header`.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception for `title` attribute even if there is no `path` attribute', () => {
|
||||||
|
const docs = [
|
||||||
|
{ renderedContent: `<${CODE_TAG} title="This is a title">Hard-coded contents.</${CODE_TAG}>` },
|
||||||
|
];
|
||||||
|
expect(() => processor.$process(docs)).toThrowError(
|
||||||
|
'Some code snippets use the `title` attribute instead of `header`.');
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue