diff --git a/editor/components/document-outline/index.js b/editor/components/document-outline/index.js index d74cea7037e51..5ec8cc529835d 100644 --- a/editor/components/document-outline/index.js +++ b/editor/components/document-outline/index.js @@ -59,8 +59,33 @@ const getHeadingLevel = heading => { const isEmptyHeading = heading => ! heading.attributes.content || heading.attributes.content.length === 0; +/** + * Returns a block whose attributes look enough like a heading's attributes. + * + * This is only meant to support heading and cover image blocks, making + * assumptions about cover image blocks so that DocumentOutline can operate on + * them, i.e. making sure attributes `nodeName` and `content` are present. It + * does not attempt to remove or add other attribues. + * + * @param {Object} block A heading or cover image block. + * @returns {Object} A block with heading-like attributes. + */ +const castHeading = ( block ) => + block.name !== 'core/cover-image' ? + block : + { + ...block, + attributes: { + ...block.attributes, + nodeName: 'H2', + content: block.attributes.title, + }, + }; + export const DocumentOutline = ( { blocks = [], title, onSelect } ) => { - const headings = filter( blocks, ( block ) => block.name === 'core/heading' ); + const headings = filter( blocks, ( { name } ) => + name === 'core/heading' || name === 'core/cover-image' + ).map( castHeading ); if ( headings.length < 1 ) { return null; diff --git a/editor/components/document-outline/test/__snapshots__/index.js.snap b/editor/components/document-outline/test/__snapshots__/index.js.snap index 7bf777f695044..649ea4fd689c3 100644 --- a/editor/components/document-outline/test/__snapshots__/index.js.snap +++ b/editor/components/document-outline/test/__snapshots__/index.js.snap @@ -25,6 +25,31 @@ exports[`DocumentOutline header blocks present should match snapshot 1`] = ` `; +exports[`DocumentOutline header blocks present should treat cover images as H2-level headings 1`] = ` +
+ +
+`; + exports[`DocumentOutline header blocks present should render warnings for multiple h1 headings 1`] = `
{ content: 'Heading child', nodeName: 'H3', } ); + const coverImage = createBlock( 'core/cover-image', { + title: 'Cover image', + } ); describe( 'no header blocks present', () => { it( 'should not render when no blocks provided', () => { @@ -65,6 +68,14 @@ describe( 'DocumentOutline', () => { expect( wrapper.find( 'TableOfContentsItem' ) ).toHaveLength( 2 ); } ); + it( 'should treat cover images as H2-level headings', () => { + const blocks = [ headingH1, paragraph, coverImage, paragraph ]; + const wrapper = shallow( ); + + expect( wrapper.find( 'TableOfContentsItem' ) ).toHaveLength( 2 ); + expect( wrapper ).toMatchSnapshot(); + } ); + it( 'should render warnings for multiple h1 headings', () => { const blocks = [ headingH1, paragraph, headingH1, paragraph ]; const wrapper = shallow( ); diff --git a/editor/components/table-of-contents/index.js b/editor/components/table-of-contents/index.js index 75930f6300e9d..d36fa46e705df 100644 --- a/editor/components/table-of-contents/index.js +++ b/editor/components/table-of-contents/index.js @@ -20,7 +20,8 @@ import { getBlocks } from '../../store/selectors'; import { selectBlock } from '../../store/actions'; function TableOfContents( { blocks } ) { - const headings = filter( blocks, ( block ) => block.name === 'core/heading' ); + const headings = filter( blocks, ( block ) => block.name === 'core/heading' || + block.name === 'core/cover-image' ); const paragraphs = filter( blocks, ( block ) => block.name === 'core/paragraph' ); return (