Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table of Contents / Outline: Treat Cover Images as H2-level headings #4616

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion editor/components/document-outline/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,31 @@ exports[`DocumentOutline header blocks present should match snapshot 1`] = `
</div>
`;

exports[`DocumentOutline header blocks present should treat cover images as H2-level headings 1`] = `
<div
className="document-outline"
>
<ul>
<TableOfContentsItem
isValid={true}
key="0"
level="H1"
onClick={[Function]}
>
Heading 1
</TableOfContentsItem>
<TableOfContentsItem
isValid={true}
key="1"
level="H2"
onClick={[Function]}
>
Cover image
</TableOfContentsItem>
</ul>
</div>
`;

exports[`DocumentOutline header blocks present should render warnings for multiple h1 headings 1`] = `
<div
className="document-outline"
Expand Down
11 changes: 11 additions & 0 deletions editor/components/document-outline/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ describe( 'DocumentOutline', () => {
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', () => {
Expand Down Expand Up @@ -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( <DocumentOutline blocks={ blocks } /> );

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( <DocumentOutline blocks={ blocks } /> );
Expand Down
3 changes: 2 additions & 1 deletion editor/components/table-of-contents/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down