diff --git a/aio/tools/transforms/examples-package/inline-tag-defs/example.js b/aio/tools/transforms/examples-package/inline-tag-defs/example.js index db62cd8ccc..ad0480ca71 100644 --- a/aio/tools/transforms/examples-package/inline-tag-defs/example.js +++ b/aio/tools/transforms/examples-package/inline-tag-defs/example.js @@ -31,9 +31,15 @@ module.exports = function exampleInlineTagDef(parseArgString, createDocMessage, const sourceCode = getExampleRegion(doc, relativePath, regionName); const attributes = []; + if (relativePath) attributes.push(` path="${relativePath}"`); + if (regionName) attributes.push(` region="${regionName}"`); if (header) attributes.push(` header="${header}"`); 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 '\n' + sourceCode + '\n'; } }; diff --git a/aio/tools/transforms/examples-package/inline-tag-defs/example.spec.js b/aio/tools/transforms/examples-package/inline-tag-defs/example.spec.js index 5f688a455e..296d809cc8 100644 --- a/aio/tools/transforms/examples-package/inline-tag-defs/example.spec.js +++ b/aio/tools/transforms/examples-package/inline-tag-defs/example.spec.js @@ -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', () => { - expect(handler({}, 'example', 'test/url')).toEqual('\nwhole file\n'); + expect(handler({}, 'example', 'test/url')).toEqual('\nwhole file\n'); }); it('should contain the region contents from the example file if a region is specified', () => { - expect(handler({}, 'example', 'test/url region-1')).toEqual('\nregion 1 contents\n'); + expect(handler({}, 'example', 'test/url region-1')).toEqual( + '\nregion 1 contents\n'); }); it('should add a header if specified', () => { - expect(handler({}, 'example', 'test/url region-1 \'Some Header\'')).toEqual('\nregion 1 contents\n'); - expect(handler({}, 'example', 'test/url region-1 Some Header')).toEqual('\nregion 1 contents\n'); + expect(handler({}, 'example', 'test/url region-1 \'Some Header\'')).toEqual( + '\nregion 1 contents\n'); + expect(handler({}, 'example', 'test/url region-1 Some Header')).toEqual( + '\nregion 1 contents\n'); }); it('should contain the whole contents from the example file if an empty ("") region is specified', () => { - expect(handler({}, 'example', 'test/url \'\'')).toEqual('\nwhole file\n'); - expect(handler({}, 'example', 'test/url \'\' Some Header')).toEqual('\nwhole file\n'); + expect(handler({}, 'example', 'test/url \'\'')).toEqual( + '\nwhole file\n'); + expect(handler({}, 'example', 'test/url \'\' Some Header')).toEqual( + '\nwhole file\n'); }); it('should add in linenum attribute if specified', () => { - expect(handler({}, 'example', 'test/url --linenums=\'false\'')).toEqual('\nwhole file\n'); - expect(handler({}, 'example', 'test/url --linenums=\'true\'')).toEqual('\nwhole file\n'); - expect(handler({}, 'example', 'test/url --linenums=\'15\'')).toEqual('\nwhole file\n'); + expect(handler({}, 'example', 'test/url --linenums=\'false\'')).toEqual( + '\nwhole file\n'); + expect(handler({}, 'example', 'test/url --linenums=\'true\'')).toEqual( + '\nwhole file\n'); + expect(handler({}, 'example', 'test/url --linenums=\'15\'')).toEqual( + '\nwhole file\n'); + }); + + it('should preserve the title if specified', () => { + expect(handler({}, 'example', 'test/url title="Some Title"')).toEqual( + '\nwhole file\n'); }); }); }); diff --git a/aio/tools/transforms/examples-package/processors/render-examples.js b/aio/tools/transforms/examples-package/processors/render-examples.js index b90d5763f1..509dd560b1 100644 --- a/aio/tools/transforms/examples-package/processors/render-examples.js +++ b/aio/tools/transforms/examples-package/processors/render-examples.js @@ -10,6 +10,8 @@ module.exports = function renderExamples(getExampleRegion, log, createDocMessage $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 @@ -17,6 +19,14 @@ module.exports = function renderExamples(getExampleRegion, log, createDocMessage /<(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) { @@ -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`.'); + } } }; }; diff --git a/aio/tools/transforms/examples-package/processors/render-examples.spec.js b/aio/tools/transforms/examples-package/processors/render-examples.spec.js index 2fdf0bab9b..baab8e3343 100644 --- a/aio/tools/transforms/examples-package/processors/render-examples.spec.js +++ b/aio/tools/transforms/examples-package/processors/render-examples.spec.js @@ -84,10 +84,10 @@ describe('renderExamples processor', () => { it('should cope with spaces and double quotes inside attribute values', () => { const docs = [ - { renderedContent: `<${CODE_TAG} title='a "quoted" value' path="test/url">`} + { renderedContent: `<${CODE_TAG} header='a "quoted" value' path="test/url">`} ]; processor.$process(docs); - expect(docs[0].renderedContent).toEqual(`<${CODE_TAG} title="a "quoted" value" path="test/url">\nwhole file\n`); + expect(docs[0].renderedContent).toEqual(`<${CODE_TAG} header="a "quoted" value" path="test/url">\nwhole file\n`); }); 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' + '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 "> + Example 2: <${CODE_TAG} path="test/url" title="This is a title 2"> + `, + }, + { + name: 'Document B', + renderedContent: ` + Example 3: <${CODE_TAG} path="test/url" title="This is a title 3"> + Example 4: <${CODE_TAG} path="test/url" header="This is a header 4"> + `, + }, + ]; + + 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">` }, + ]; + 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.` }, + ]; + expect(() => processor.$process(docs)).toThrowError( + 'Some code snippets use the `title` attribute instead of `header`.'); + }); }) ); });