diff --git a/blocks/api/raw-handling/special-comment-converter.js b/blocks/api/raw-handling/special-comment-converter.js index 2da2e32c803f41..8146d671ce6395 100644 --- a/blocks/api/raw-handling/special-comment-converter.js +++ b/blocks/api/raw-handling/special-comment-converter.js @@ -9,9 +9,9 @@ import { remove, replace } from '@wordpress/utils'; const { COMMENT_NODE } = window.Node; /** - * Looks for `` comments, as well as the `` - * variant and its `` companion, and replaces them with a custom - * element representing a future block. + * Looks for `` and `` comments, as well as the + * `` variant and its `` companion, + * and replaces them with a custom element representing a future block. * * The custom element is a way to bypass the rest of the `raw-handling` * transforms, which would eliminate other kinds of node with which to carry @@ -24,43 +24,39 @@ const { COMMENT_NODE } = window.Node; * @return {void} */ export default function( node ) { - if ( - node.nodeType !== COMMENT_NODE || - node.nodeValue.indexOf( 'more' ) !== 0 - ) { - // We don't specificially look for `noteaser`, meaning that if one is - // found on its own (and not adjacent to `more`), it will be lost. + if ( node.nodeType !== COMMENT_NODE ) { return; } - // Grab any custom text in the comment - const customText = node.nodeValue.slice( 4 ).trim(); - - // When a `` comment is found, we need to look for any - // `` sibling, but it may not be a direct sibling - // (whitespace typically lies in between) - let sibling = node; - let noTeaser = false; - while ( ( sibling = sibling.nextSibling ) ) { - if ( - sibling.nodeType === COMMENT_NODE && - sibling.nodeValue === 'noteaser' - ) { - noTeaser = true; - remove( sibling ); - break; - } + if ( node.nodeValue === 'nextpage' ) { + replace( node, createNextpage() ); + return; } - // Conjure up a custom More element - const more = createMore( customText, noTeaser ); + if ( node.nodeValue.indexOf( 'more' ) === 0 ) { + // Grab any custom text in the comment. + const customText = node.nodeValue.slice( 4 ).trim(); + + /* + * When a `` comment is found, we need to look for any + * `` sibling, but it may not be a direct sibling + * (whitespace typically lies in between) + */ + let sibling = node; + let noTeaser = false; + while ( ( sibling = sibling.nextSibling ) ) { + if ( + sibling.nodeType === COMMENT_NODE && + sibling.nodeValue === 'noteaser' + ) { + noTeaser = true; + remove( sibling ); + break; + } + } - // Append it to the top level for later conversion to blocks - let parent = node.parentNode; - while ( parent.nodeName !== 'BODY' ) { - parent = parent.parentNode; + replace( node, createMore( customText, noTeaser ) ); } - replace( node, more ); } function createMore( customText, noTeaser ) { @@ -75,3 +71,10 @@ function createMore( customText, noTeaser ) { } return node; } + +function createNextpage() { + const node = document.createElement( 'wp-block' ); + node.dataset.block = 'core/nextpage'; + + return node; +} diff --git a/blocks/api/raw-handling/test/special-comment-converter.js b/blocks/api/raw-handling/test/special-comment-converter.js index 422f61b30de9ee..602fd4611ef1aa 100644 --- a/blocks/api/raw-handling/test/special-comment-converter.js +++ b/blocks/api/raw-handling/test/special-comment-converter.js @@ -10,7 +10,7 @@ import specialCommentConverter from '../special-comment-converter'; import { deepFilterHTML } from '../utils'; describe( 'specialCommentConverter', () => { - it( 'should convert a single comment into a basic block', () => { + it( 'should convert a single "more" comment into a basic block', () => { equal( deepFilterHTML( '
', @@ -19,6 +19,12 @@ describe( 'specialCommentConverter', () => { 'Third paragraph
` ); } ); + it( 'should not break pagination order', () => { + const output = deepFilterHTML( + `First page.
+ +Second page
+ +Third page
`, + [ specialCommentConverter ] + ); + equal( + output, + `First page.
+Second page
+Third page
` + ); + } ); } ); } ); diff --git a/blocks/library/index.js b/blocks/library/index.js index ce1948234a5021..777e9aa0325a0f 100644 --- a/blocks/library/index.js +++ b/blocks/library/index.js @@ -23,6 +23,7 @@ import * as html from './html'; import * as latestPosts from './latest-posts'; import * as list from './list'; import * as more from './more'; +import * as nextpage from './nextpage'; import * as preformatted from './preformatted'; import * as pullquote from './pullquote'; import * as sharedBlock from './block'; @@ -60,6 +61,7 @@ export const registerCoreBlocks = () => { html, latestPosts, more, + nextpage, preformatted, pullquote, separator, diff --git a/blocks/library/nextpage/editor.scss b/blocks/library/nextpage/editor.scss new file mode 100644 index 00000000000000..cc54fec3ff397a --- /dev/null +++ b/blocks/library/nextpage/editor.scss @@ -0,0 +1,40 @@ +.editor-visual-editor__block[data-type="core/nextpage"] { + max-width: 100%; +} + +.wp-block-nextpage { + display: block; + text-align: center; + overflow: hidden; + white-space: nowrap; +} + +.wp-block-nextpage > span { + position: relative; + display: inline-block; + font-size: 12px; + text-transform: uppercase; + font-weight: 600; + font-family: $default-font; + color: $dark-gray-300; +} + +.wp-block-nextpage > span:before, +.wp-block-nextpage > span:after { + content: ''; + position: absolute; + top: 50%; + width: 100vw; + border-top: 3px dashed $light-gray-700; + margin-top: -2px; +} + +.wp-block-nextpage > span:before { + right: 100%; + margin-right: 20px; +} + +.wp-block-nextpage > span:after { + left: 100%; + margin-left: 20px; +} diff --git a/blocks/library/nextpage/index.js b/blocks/library/nextpage/index.js new file mode 100644 index 00000000000000..e67e276609f8a6 --- /dev/null +++ b/blocks/library/nextpage/index.js @@ -0,0 +1,61 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { RawHTML } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import './editor.scss'; +import { createBlock } from '../../api'; + +export const name = 'core/nextpage'; + +export const settings = { + title: __( 'Page break' ), + + description: __( 'This block allows you to set break points on your post. Visitors of your blog are then presented with content split into multiple pages.' ), + + icon: 'admin-page', + + category: 'layout', + + keywords: [ __( 'next page' ), __( 'pagination' ) ], + + supports: { + customClassName: false, + className: false, + html: false, + }, + + attributes: {}, + + transforms: { + from: [ + { + type: 'raw', + isMatch: ( node ) => node.dataset && node.dataset.block === 'core/nextpage', + transform() { + return createBlock( 'core/nextpage', {} ); + }, + }, + ], + }, + + edit() { + return ( +