diff --git a/lib/experimental/block-editor-settings-mobile.php b/lib/experimental/block-editor-settings-mobile.php index bd05e24e4acc9f..d0a0e7add5319b 100644 --- a/lib/experimental/block-editor-settings-mobile.php +++ b/lib/experimental/block-editor-settings-mobile.php @@ -26,9 +26,9 @@ function gutenberg_get_block_editor_settings_mobile( $settings ) { $settings['__experimentalStyles'] = gutenberg_get_global_styles(); } - // To be set to true when the web makes quote v2 (inner blocks) the default. + // To tell mobile that the site uses quote v2 (inner blocks). // See https://github.com/WordPress/gutenberg/pull/25892. - $settings['__experimentalEnableQuoteBlockV2'] = gutenberg_is_quote_v2_enabled(); + $settings['__experimentalEnableQuoteBlockV2'] = true; } return $settings; diff --git a/lib/experimental/blocks.php b/lib/experimental/blocks.php index b9ac0a6c715830..c92358621c5de0 100644 --- a/lib/experimental/blocks.php +++ b/lib/experimental/blocks.php @@ -5,15 +5,6 @@ * @package gutenberg */ -/** - * Returns whether the quote v2 is enabled by the user. - * - * @return boolean - */ -function gutenberg_is_quote_v2_enabled() { - return get_option( 'gutenberg-experiments' ) && array_key_exists( 'gutenberg-quote-v2', get_option( 'gutenberg-experiments' ) ); -} - /** * Sets a global JS variable used to trigger the availability of the experimental blocks. */ @@ -21,10 +12,6 @@ function gutenberg_enable_experimental_blocks() { if ( get_option( 'gutenberg-experiments' ) && array_key_exists( 'gutenberg-list-v2', get_option( 'gutenberg-experiments' ) ) ) { wp_add_inline_script( 'wp-block-library', 'window.__experimentalEnableListBlockV2 = true', 'before' ); } - - if ( gutenberg_is_quote_v2_enabled() ) { - wp_add_inline_script( 'wp-block-library', 'window.__experimentalEnableQuoteBlockV2 = true', 'before' ); - } } add_action( 'admin_init', 'gutenberg_enable_experimental_blocks' ); diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 0c9e8eba38d72d..581b6afebdf216 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -52,17 +52,6 @@ function gutenberg_initialize_experiments_settings() { 'id' => 'gutenberg-list-v2', ) ); - add_settings_field( - 'gutenberg-quote-v2', - __( 'Quote block v2', 'gutenberg' ), - 'gutenberg_display_experiment_field', - 'gutenberg-experiments', - 'gutenberg_experiments_section', - array( - 'label' => __( 'Test a new quote block that allows nested blocks (Warning: The new block is not ready. You may experience content loss, avoid using it on production sites)', 'gutenberg' ), - 'id' => 'gutenberg-quote-v2', - ) - ); register_setting( 'gutenberg-experiments', 'gutenberg-experiments' diff --git a/packages/block-library/src/index.native.js b/packages/block-library/src/index.native.js index 984e5c290135d0..863cd4ef3315d1 100644 --- a/packages/block-library/src/index.native.js +++ b/packages/block-library/src/index.native.js @@ -179,14 +179,6 @@ const devOnly = ( block ) => ( !! __DEV__ ? block : null ); const iOSOnly = ( block ) => Platform.OS === 'ios' ? block : devOnly( block ); -// To be removed once Quote V2 is released on the web editor. -function quoteCheck( quoteBlock, blocksFlags ) { - if ( blocksFlags?.__experimentalEnableQuoteBlockV2 ) { - quoteBlock.settings = quoteBlock?.settingsV2; - } - return quoteBlock; -} - // Hide the Classic block and SocialLink block addFilter( 'blocks.registerBlockType', @@ -238,10 +230,9 @@ addFilter( * * registerCoreBlocks(); * ``` - * @param {Object} [blocksFlags] Experimental flags * */ -export const registerCoreBlocks = ( blocksFlags ) => { +export const registerCoreBlocks = () => { // When adding new blocks to this list please also consider updating /src/block-support/supported-blocks.json in the Gutenberg-Mobile repo [ paragraph, @@ -254,7 +245,7 @@ export const registerCoreBlocks = ( blocksFlags ) => { nextpage, separator, list, - quoteCheck( quote, blocksFlags ), + quote, mediaText, preformatted, gallery, diff --git a/packages/block-library/src/list/transforms.js b/packages/block-library/src/list/transforms.js index 5d67e6cee0c67d..32667a99a735af 100644 --- a/packages/block-library/src/list/transforms.js +++ b/packages/block-library/src/list/transforms.js @@ -65,19 +65,6 @@ const transforms = { } ); }, }, - { - type: 'block', - blocks: [ 'core/quote', 'core/pullquote' ], - transform: ( { value, anchor } ) => { - return createBlock( 'core/list', { - values: toHTMLString( { - value: create( { html: value, multilineTag: 'p' } ), - multilineTag: 'li', - } ), - anchor, - } ); - }, - }, { type: 'raw', selector: 'ol,ul', @@ -174,23 +161,6 @@ const transforms = { } ) ), }, - { - type: 'block', - blocks: [ 'core/quote' ], - transform: ( { values, anchor } ) => { - return createBlock( 'core/quote', { - value: toHTMLString( { - value: create( { - html: values, - multilineTag: 'li', - multilineWrapperTags: [ 'ul', 'ol' ], - } ), - multilineTag: 'p', - } ), - anchor, - } ); - }, - }, { type: 'block', blocks: [ 'core/pullquote' ], diff --git a/packages/block-library/src/quote/deprecated.js b/packages/block-library/src/quote/deprecated.js index cd1443038002b8..f9cd8d581b9626 100644 --- a/packages/block-library/src/quote/deprecated.js +++ b/packages/block-library/src/quote/deprecated.js @@ -1,127 +1,241 @@ /** * External dependencies */ +import classnames from 'classnames'; import { omit } from 'lodash'; /** * WordPress dependencies */ -import { RichText } from '@wordpress/block-editor'; - -const blockAttributes = { - value: { - type: 'string', - source: 'html', - selector: 'blockquote', - multiline: 'p', - default: '', - }, - citation: { - type: 'string', - source: 'html', - selector: 'cite', - default: '', - }, - align: { - type: 'string', - }, +import { createBlock, parseWithAttributeSchema } from '@wordpress/blocks'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; + +export const migrateToQuoteV2 = ( attributes ) => { + const { value } = attributes; + + return [ + { + ...omit( attributes, [ 'value' ] ), + }, + value + ? parseWithAttributeSchema( value, { + type: 'array', + source: 'query', + selector: 'p', + query: { + content: { + type: 'string', + source: 'html', + }, + }, + } ).map( ( { content } ) => + createBlock( 'core/paragraph', { content } ) + ) + : createBlock( 'core/paragraph' ), + ]; }; -const deprecated = [ - { - attributes: blockAttributes, - save( { attributes } ) { - const { align, value, citation } = attributes; - - return ( -
- - { ! RichText.isEmpty( citation ) && ( - - ) } -
- ); +const v3 = { + attributes: { + value: { + type: 'string', + source: 'html', + selector: 'blockquote', + multiline: 'p', + default: '', + __experimentalRole: 'content', + }, + citation: { + type: 'string', + source: 'html', + selector: 'cite', + default: '', + __experimentalRole: 'content', + }, + align: { + type: 'string', }, }, - { - attributes: { - ...blockAttributes, - style: { - type: 'number', - default: 1, + supports: { + anchor: true, + __experimentalSlashInserter: true, + typography: { + fontSize: true, + lineHeight: true, + __experimentalFontStyle: true, + __experimentalFontWeight: true, + __experimentalLetterSpacing: true, + __experimentalTextTransform: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, }, }, + }, + save( { attributes } ) { + const { align, value, citation } = attributes; + + const className = classnames( { + [ `has-text-align-${ align }` ]: align, + } ); - migrate( attributes ) { - if ( attributes.style === 2 ) { - return { - ...omit( attributes, [ 'style' ] ), - className: attributes.className - ? attributes.className + ' is-style-large' - : 'is-style-large', - }; - } + return ( +
+ + { ! RichText.isEmpty( citation ) && ( + + ) } +
+ ); + }, + migrate: migrateToQuoteV2, +}; - return attributes; +const v2 = { + attributes: { + value: { + type: 'string', + source: 'html', + selector: 'blockquote', + multiline: 'p', + default: '', + }, + citation: { + type: 'string', + source: 'html', + selector: 'cite', + default: '', }, + align: { + type: 'string', + }, + }, + migrate: migrateToQuoteV2, + save( { attributes } ) { + const { align, value, citation } = attributes; - save( { attributes } ) { - const { align, value, citation, style } = attributes; + return ( +
+ + { ! RichText.isEmpty( citation ) && ( + + ) } +
+ ); + }, +}; - return ( -
- - { ! RichText.isEmpty( citation ) && ( - - ) } -
- ); +const v1 = { + attributes: { + value: { + type: 'string', + source: 'html', + selector: 'blockquote', + multiline: 'p', + default: '', }, - }, - { - attributes: { - ...blockAttributes, - citation: { - type: 'string', - source: 'html', - selector: 'footer', - default: '', - }, - style: { - type: 'number', - default: 1, - }, + citation: { + type: 'string', + source: 'html', + selector: 'cite', + default: '', }, + align: { + type: 'string', + }, + style: { + type: 'number', + default: 1, + }, + }, - migrate( attributes ) { - if ( ! isNaN( parseInt( attributes.style ) ) ) { - return { - ...omit( attributes, [ 'style' ] ), - }; - } + migrate( attributes ) { + if ( attributes.style === 2 ) { + return migrateToQuoteV2( { + ...omit( attributes, [ 'style' ] ), + className: attributes.className + ? attributes.className + ' is-style-large' + : 'is-style-large', + } ); + } - return attributes; - }, + return migrateToQuoteV2( attributes ); + }, - save( { attributes } ) { - const { align, value, citation, style } = attributes; + save( { attributes } ) { + const { align, value, citation, style } = attributes; - return ( -
- - { ! RichText.isEmpty( citation ) && ( - - ) } -
- ); + return ( +
+ + { ! RichText.isEmpty( citation ) && ( + + ) } +
+ ); + }, +}; + +const v0 = { + attributes: { + value: { + type: 'string', + source: 'html', + selector: 'blockquote', + multiline: 'p', + default: '', + }, + citation: { + type: 'string', + source: 'html', + selector: 'footer', + default: '', + }, + align: { + type: 'string', }, + style: { + type: 'number', + default: 1, + }, + }, + + migrate( attributes ) { + if ( ! isNaN( parseInt( attributes.style ) ) ) { + return migrateToQuoteV2( { + ...omit( attributes, [ 'style' ] ), + } ); + } + + return migrateToQuoteV2( attributes ); + }, + + save( { attributes } ) { + const { align, value, citation, style } = attributes; + + return ( +
+ + { ! RichText.isEmpty( citation ) && ( + + ) } +
+ ); }, -]; +}; -export default deprecated; +/** + * New deprecations need to be placed first + * for them to have higher priority. + * + * Old deprecations may need to be updated as well. + * + * See block-deprecation.md + */ +export default [ v3, v2, v1, v0 ]; diff --git a/packages/block-library/src/quote/edit.js b/packages/block-library/src/quote/edit.js index 8bd50b68ae9788..e6c560078e5010 100644 --- a/packages/block-library/src/quote/edit.js +++ b/packages/block-library/src/quote/edit.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import classnames from 'classnames'; +import classNames from 'classnames'; /** * WordPress dependencies @@ -12,29 +12,87 @@ import { BlockControls, RichText, useBlockProps, + useInnerBlocksProps, + store as blockEditorStore, } from '@wordpress/block-editor'; import { BlockQuotation } from '@wordpress/components'; +import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; -import { Platform } from '@wordpress/element'; +import { Platform, useEffect } from '@wordpress/element'; +import deprecated from '@wordpress/deprecated'; + +/** + * Internal dependencies + */ +import { migrateToQuoteV2 } from './deprecated'; const isWebPlatform = Platform.OS === 'web'; +const TEMPLATE = [ [ 'core/paragraph', {} ] ]; + +/** + * At the moment, deprecations don't handle create blocks from attributes + * (like when using CPT templates). For this reason, this hook is necessary + * to avoid breaking templates using the old quote block format. + * + * @param {Object} attributes Block attributes. + * @param {string} clientId Block client ID. + */ +const useMigrateOnLoad = ( attributes, clientId ) => { + const registry = useRegistry(); + const { updateBlockAttributes, replaceInnerBlocks } = + useDispatch( blockEditorStore ); + useEffect( () => { + // As soon as the block is loaded, migrate it to the new version. + + if ( ! attributes.value ) { + // No need to migrate if it doesn't have the value attribute. + return; + } + + const [ newAttributes, newInnerBlocks ] = + migrateToQuoteV2( attributes ); + + deprecated( 'Value attribute on the quote block', { + since: '6.0', + version: '6.5', + alternative: 'inner blocks', + } ); + + registry.batch( () => { + updateBlockAttributes( clientId, newAttributes ); + replaceInnerBlocks( clientId, newInnerBlocks ); + } ); + }, [ attributes.value ] ); +}; + export default function QuoteEdit( { attributes, setAttributes, - isSelected, - mergeBlocks, - onReplace, - className, insertBlocksAfter, + clientId, + className, style, } ) { - const { align, value, citation } = attributes; + const { align, citation } = attributes; + + useMigrateOnLoad( attributes, clientId ); + + const hasSelection = useSelect( ( select ) => { + const { isBlockSelected, hasSelectedInnerBlock } = + select( blockEditorStore ); + return hasSelectedInnerBlock( clientId ) || isBlockSelected( clientId ); + }, [] ); + const blockProps = useBlockProps( { - className: classnames( className, { + className: classNames( className, { [ `has-text-align-${ align }` ]: align, } ), - style, + ...( ! isWebPlatform && { style } ), + } ); + const innerBlocksProps = useInnerBlocksProps( blockProps, { + template: TEMPLATE, + templateInsertUpdatesSelection: true, } ); return ( @@ -47,66 +105,33 @@ export default function QuoteEdit( { } } /> - - - setAttributes( { - value: nextValue, - } ) - } - onMerge={ mergeBlocks } - onRemove={ ( forward ) => { - const hasEmptyCitation = - ! citation || citation.length === 0; - if ( ! forward && hasEmptyCitation ) { - onReplace( [] ); - } - } } - aria-label={ __( 'Quote text' ) } - placeholder={ - // translators: placeholder text used for the quote - __( 'Add quote' ) - } - onReplace={ onReplace } - onSplit={ ( piece ) => - createBlock( 'core/quote', { - ...attributes, - value: piece, - } ) - } - __unstableOnSplitMiddle={ () => - createBlock( 'core/paragraph' ) - } - textAlign={ align } - __unstableEmbedURLOnPaste - /> - { ( ! RichText.isEmpty( citation ) || isSelected ) && ( + + { innerBlocksProps.children } + { ( ! RichText.isEmpty( citation ) || hasSelection ) && ( + onChange={ ( nextCitation ) => { setAttributes( { citation: nextCitation, - } ) - } + } ); + } } __unstableMobileNoFocusOnMount - aria-label={ __( 'Quote citation text' ) } + aria-label={ __( 'Quote citation' ) } placeholder={ - // translators: placeholder text used for the citation + // translators: placeholder text used for the + // citation __( 'Add citation' ) } className="wp-block-quote__citation" - textAlign={ align } __unstableOnSplitAtEnd={ () => insertBlocksAfter( createBlock( getDefaultBlockName() ) ) } + { ...( ! isWebPlatform ? { textAlign: align } : {} ) } /> ) } diff --git a/packages/block-library/src/quote/index.js b/packages/block-library/src/quote/index.js index 2490462b8a963f..8140ad49f34958 100644 --- a/packages/block-library/src/quote/index.js +++ b/packages/block-library/src/quote/index.js @@ -12,51 +12,28 @@ import edit from './edit'; import metadata from './block.json'; import save from './save'; import transforms from './transforms'; -import settingsV2 from './v2'; const { name } = metadata; -export { metadata, name, settingsV2 }; +export { metadata, name }; -export const settingsV1 = { +export const settings = { icon, example: { attributes: { - value: - '

' + __( 'In quoting others, we cite ourselves.' ) + '

', citation: 'Julio Cortázar', }, + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { + content: __( 'In quoting others, we cite ourselves.' ), + }, + }, + ], }, transforms, edit, save, - merge( attributes, { value, citation } ) { - // Quote citations cannot be merged. Pick the second one unless it's - // empty. - if ( ! citation ) { - citation = attributes.citation; - } - - if ( ! value || value === '

' ) { - return { - ...attributes, - citation, - }; - } - - return { - ...attributes, - value: attributes.value + value, - citation, - }; - }, deprecated, }; - -let settings = settingsV1; -if ( process.env.IS_GUTENBERG_PLUGIN ) { - settings = window?.__experimentalEnableQuoteBlockV2 - ? settingsV2 - : settingsV1; -} -export { settings }; diff --git a/packages/block-library/src/quote/save.js b/packages/block-library/src/quote/save.js index fafbec8df52213..7b6ecab8762eb5 100644 --- a/packages/block-library/src/quote/save.js +++ b/packages/block-library/src/quote/save.js @@ -1,23 +1,23 @@ /** * External dependencies */ -import classnames from 'classnames'; +import classNames from 'classnames'; /** * WordPress dependencies */ -import { RichText, useBlockProps } from '@wordpress/block-editor'; +import { InnerBlocks, RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { align, value, citation } = attributes; + const { align, citation } = attributes; - const className = classnames( { + const className = classNames( { [ `has-text-align-${ align }` ]: align, } ); return (
- + { ! RichText.isEmpty( citation ) && ( ) } diff --git a/packages/block-library/src/quote/v2/test/migrate.js b/packages/block-library/src/quote/test/migrate.js similarity index 89% rename from packages/block-library/src/quote/v2/test/migrate.js rename to packages/block-library/src/quote/test/migrate.js index 475344b51d3be1..d1107473c1b5df 100644 --- a/packages/block-library/src/quote/v2/test/migrate.js +++ b/packages/block-library/src/quote/test/migrate.js @@ -11,9 +11,8 @@ import { * Internal dependencies */ import { migrateToQuoteV2 } from '../deprecated'; -import * as paragraph from '../../../paragraph'; -import * as quote from '../../../quote'; -import * as quoteV2 from '../../../quote/v2'; +import * as paragraph from '../../paragraph'; +import * as quote from '../../quote'; describe( 'Migrate quote block', () => { beforeAll( () => { @@ -21,10 +20,6 @@ describe( 'Migrate quote block', () => { { name: paragraph.name, ...paragraph.metadata }, paragraph.settings ); - registerBlockType( - { name: quote.name, ...quote.metadata }, - quoteV2.settings - ); } ); afterAll( () => { diff --git a/packages/block-library/src/quote/transforms.js b/packages/block-library/src/quote/transforms.js index 134aff4339eda7..18716d3b11308b 100644 --- a/packages/block-library/src/quote/transforms.js +++ b/packages/block-library/src/quote/transforms.js @@ -1,188 +1,158 @@ /** * WordPress dependencies */ -import { createBlock } from '@wordpress/blocks'; -import { create, join, split, toHTMLString } from '@wordpress/rich-text'; +import { + createBlock, + parseWithAttributeSchema, + rawHandler, +} from '@wordpress/blocks'; const transforms = { from: [ { type: 'block', - isMultiBlock: true, - blocks: [ 'core/paragraph' ], - transform: ( attributes ) => { - return createBlock( 'core/quote', { - value: toHTMLString( { - value: join( - attributes.map( ( { content } ) => - create( { html: content } ) - ), - '\u2028' - ), - multilineTag: 'p', - } ), - anchor: attributes.anchor, - } ); + blocks: [ 'core/pullquote' ], + transform: ( { value, citation, anchor, fontSize, style } ) => { + return createBlock( + 'core/quote', + { + citation, + anchor, + fontSize, + style, + }, + parseWithAttributeSchema( value, { + type: 'array', + source: 'query', + selector: 'p', + query: { + content: { + type: 'string', + source: 'html', + }, + }, + } ).map( ( { content } ) => + createBlock( 'core/paragraph', { content } ) + ) + ); }, }, { type: 'block', - blocks: [ 'core/heading' ], - transform: ( { content, anchor } ) => { - return createBlock( 'core/quote', { - value: `

${ content }

`, - anchor, - } ); - }, - }, - { - type: 'block', - blocks: [ 'core/pullquote' ], - transform: ( { value, citation, anchor } ) => - createBlock( 'core/quote', { - value, - citation, - anchor, - } ), + blocks: [ 'core/group' ], + transform: ( { anchor }, innerBlocks ) => + createBlock( 'core/quote', { anchor }, innerBlocks ), }, { type: 'prefix', prefix: '>', - transform: ( content ) => { - return createBlock( 'core/quote', { - value: `

${ content }

`, - } ); - }, + transform: ( content ) => + createBlock( 'core/quote', {}, [ + createBlock( 'core/paragraph', { content } ), + ] ), }, { type: 'raw', - isMatch: ( node ) => { - const isParagraphOrSingleCite = ( () => { - let hasCitation = false; - return ( child ) => { - // Child is a paragraph. - if ( child.nodeName === 'P' ) { - return true; - } - // Child is a cite and no other cite child exists before it. - if ( ! hasCitation && child.nodeName === 'CITE' ) { - hasCitation = true; - return true; - } - }; - } )(); - return ( - node.nodeName === 'BLOCKQUOTE' && - // The quote block can only handle multiline paragraph - // content with an optional cite child. - Array.from( node.childNodes ).every( - isParagraphOrSingleCite - ) - ); - }, - schema: ( { phrasingContentSchema } ) => ( { + schema: () => ( { blockquote: { - children: { - p: { - children: phrasingContentSchema, - }, - cite: { - children: phrasingContentSchema, - }, - }, + children: '*', }, } ), - }, - ], - to: [ - { - type: 'block', - blocks: [ 'core/paragraph' ], - transform: ( { value, citation } ) => { - const paragraphs = []; - if ( value && value !== '

' ) { - paragraphs.push( - ...split( - create( { html: value, multilineTag: 'p' } ), - '\u2028' - ).map( ( piece ) => - createBlock( 'core/paragraph', { - content: toHTMLString( { value: piece } ), - } ) - ) - ); - } - if ( citation && citation !== '

' ) { - paragraphs.push( - createBlock( 'core/paragraph', { - content: citation, - } ) - ); - } - - if ( paragraphs.length === 0 ) { - return createBlock( 'core/paragraph', { - content: '', - } ); - } - return paragraphs; + selector: 'blockquote', + transform: ( node ) => { + return createBlock( + 'core/quote', + // Don't try to parse any `cite` out of this content. + // * There may be more than one cite. + // * There may be more attribution text than just the cite. + // * If the cite is nested in the quoted text, it's wrong to + // remove it. + {}, + rawHandler( { + HTML: node.innerHTML, + mode: 'BLOCKS', + } ) + ); }, }, - { type: 'block', - blocks: [ 'core/heading' ], - transform: ( { value, citation, ...attrs } ) => { - // If there is no quote content, use the citation as the - // content of the resulting heading. A nonexistent citation - // will result in an empty heading. - if ( value === '

' ) { - return createBlock( 'core/heading', { - content: citation, - } ); - } - - const pieces = split( - create( { html: value, multilineTag: 'p' } ), - '\u2028' - ); - - const headingBlock = createBlock( 'core/heading', { - content: toHTMLString( { value: pieces[ 0 ] } ), - } ); - - if ( ! citation && pieces.length === 1 ) { - return headingBlock; - } - - const quotePieces = pieces.slice( 1 ); - - const quoteBlock = createBlock( 'core/quote', { - ...attrs, - citation, - value: toHTMLString( { - value: quotePieces.length - ? join( pieces.slice( 1 ), '\u2028' ) - : create(), - multilineTag: 'p', - } ), - } ); - - return [ headingBlock, quoteBlock ]; + isMultiBlock: true, + blocks: [ '*' ], + isMatch: ( {}, blocks ) => { + return ! blocks.some( ( { name } ) => name === 'core/quote' ); }, + __experimentalConvert: ( blocks ) => + createBlock( + 'core/quote', + {}, + blocks.map( ( block ) => + createBlock( + block.name, + block.attributes, + block.innerBlocks + ) + ) + ), }, - + ], + to: [ { type: 'block', blocks: [ 'core/pullquote' ], - transform: ( { value, citation, anchor } ) => { + isMatch: ( {}, block ) => { + return block.innerBlocks.every( + ( { name } ) => name === 'core/paragraph' + ); + }, + transform: ( + { citation, anchor, fontSize, style }, + innerBlocks + ) => { + const value = innerBlocks + .map( + ( { attributes } ) => `

${ attributes.content }

` + ) + .join( '' ); return createBlock( 'core/pullquote', { value, citation, anchor, + fontSize, + style, } ); }, }, + { + type: 'block', + blocks: [ 'core/group' ], + transform: ( { citation, anchor }, innerBlocks ) => + createBlock( + 'core/group', + { anchor }, + citation + ? [ + ...innerBlocks, + createBlock( 'core/paragraph', { + content: citation, + } ), + ] + : innerBlocks + ), + }, + { + type: 'block', + blocks: [ '*' ], + transform: ( { citation }, innerBlocks ) => + citation + ? [ + ...innerBlocks, + createBlock( 'core/paragraph', { + content: citation, + } ), + ] + : innerBlocks, + }, ], }; diff --git a/packages/block-library/src/quote/v2/deprecated.js b/packages/block-library/src/quote/v2/deprecated.js deleted file mode 100644 index a9950e4a225483..00000000000000 --- a/packages/block-library/src/quote/v2/deprecated.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; -import { omit } from 'lodash'; - -/** - * WordPress dependencies - */ -import { createBlock, parseWithAttributeSchema } from '@wordpress/blocks'; -import { RichText, useBlockProps } from '@wordpress/block-editor'; - -/** - * Internal dependencies - */ -import deprecationsForV1Block from '../deprecated'; - -export const migrateToQuoteV2 = ( attributes ) => { - const { value } = attributes; - - return [ - { - ...omit( attributes, [ 'value' ] ), - }, - value - ? parseWithAttributeSchema( value, { - type: 'array', - source: 'query', - selector: 'p', - query: { - content: { - type: 'string', - source: 'html', - }, - }, - } ).map( ( { content } ) => - createBlock( 'core/paragraph', { content } ) - ) - : createBlock( 'core/paragraph' ), - ]; -}; - -const v3 = { - attributes: { - value: { - type: 'string', - source: 'html', - selector: 'blockquote', - multiline: 'p', - default: '', - __experimentalRole: 'content', - }, - citation: { - type: 'string', - source: 'html', - selector: 'cite', - default: '', - __experimentalRole: 'content', - }, - align: { - type: 'string', - }, - }, - supports: { - anchor: true, - __experimentalSlashInserter: true, - typography: { - fontSize: true, - lineHeight: true, - __experimentalFontStyle: true, - __experimentalFontWeight: true, - __experimentalLetterSpacing: true, - __experimentalTextTransform: true, - __experimentalDefaultControls: { - fontSize: true, - fontAppearance: true, - }, - }, - }, - save( { attributes } ) { - const { align, value, citation } = attributes; - - const className = classnames( { - [ `has-text-align-${ align }` ]: align, - } ); - - return ( -
- - { ! RichText.isEmpty( citation ) && ( - - ) } -
- ); - }, - migrate: migrateToQuoteV2, -}; - -/** - * New deprecations need to be placed first - * for them to have higher priority. - * - * Old deprecations may need to be updated as well. - * - * See block-deprecation.md - */ -export default [ v3, ...deprecationsForV1Block ]; diff --git a/packages/block-library/src/quote/v2/edit.js b/packages/block-library/src/quote/v2/edit.js deleted file mode 100644 index 911d3346e50700..00000000000000 --- a/packages/block-library/src/quote/v2/edit.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * External dependencies - */ -import classNames from 'classnames'; - -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { - AlignmentControl, - BlockControls, - RichText, - useBlockProps, - useInnerBlocksProps, - store as blockEditorStore, -} from '@wordpress/block-editor'; -import { BlockQuotation } from '@wordpress/components'; -import { useDispatch, useSelect, useRegistry } from '@wordpress/data'; -import { createBlock, getDefaultBlockName } from '@wordpress/blocks'; -import { Platform, useEffect } from '@wordpress/element'; -import deprecated from '@wordpress/deprecated'; - -/** - * Internal dependencies - */ -import { migrateToQuoteV2 } from './deprecated'; - -const isWebPlatform = Platform.OS === 'web'; -const TEMPLATE = [ [ 'core/paragraph', {} ] ]; - -/** - * At the moment, deprecations don't handle create blocks from attributes - * (like when using CPT templates). For this reason, this hook is necessary - * to avoid breaking templates using the old quote block format. - * - * @param {Object} attributes Block attributes. - * @param {string} clientId Block client ID. - */ -const useMigrateOnLoad = ( attributes, clientId ) => { - const registry = useRegistry(); - const { updateBlockAttributes, replaceInnerBlocks } = - useDispatch( blockEditorStore ); - useEffect( () => { - // As soon as the block is loaded, migrate it to the new version. - - if ( ! attributes.value ) { - // No need to migrate if it doesn't have the value attribute. - return; - } - - const [ newAttributes, newInnerBlocks ] = - migrateToQuoteV2( attributes ); - - deprecated( 'Value attribute on the quote block', { - since: '6.0', - version: '6.5', - alternative: 'inner blocks', - } ); - - registry.batch( () => { - updateBlockAttributes( clientId, newAttributes ); - replaceInnerBlocks( clientId, newInnerBlocks ); - } ); - }, [ attributes.value ] ); -}; - -export default function QuoteEdit( { - attributes, - setAttributes, - isSelected, - insertBlocksAfter, - clientId, - className, - style, -} ) { - const { citation, align } = attributes; - - useMigrateOnLoad( attributes, clientId ); - - const isAncestorOfSelectedBlock = useSelect( ( select ) => - select( blockEditorStore ).hasSelectedInnerBlock( clientId ) - ); - const hasSelection = isSelected || isAncestorOfSelectedBlock; - - const blockProps = useBlockProps( { - className: classNames( className, { - [ `has-text-align-${ align }` ]: align, - } ), - ...( ! isWebPlatform && { style } ), - } ); - const innerBlocksProps = useInnerBlocksProps( blockProps, { - template: TEMPLATE, - templateInsertUpdatesSelection: true, - } ); - - return ( - <> - - { - setAttributes( { align: nextAlign } ); - } } - /> - - - { innerBlocksProps.children } - { ( ! RichText.isEmpty( citation ) || hasSelection ) && ( - { - setAttributes( { - citation: nextCitation, - } ); - } } - __unstableMobileNoFocusOnMount - aria-label={ __( 'Quote citation' ) } - placeholder={ - // translators: placeholder text used for the - // citation - __( 'Add citation' ) - } - className="wp-block-quote__citation" - __unstableOnSplitAtEnd={ () => - insertBlocksAfter( - createBlock( getDefaultBlockName() ) - ) - } - { ...( ! isWebPlatform ? { textAlign: align } : {} ) } - /> - ) } - - - ); -} diff --git a/packages/block-library/src/quote/v2/index.js b/packages/block-library/src/quote/v2/index.js deleted file mode 100644 index 7019fe59db6464..00000000000000 --- a/packages/block-library/src/quote/v2/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * WordPress dependencies - */ -import { __ } from '@wordpress/i18n'; -import { quote as icon } from '@wordpress/icons'; - -/** - * Internal dependencies - */ -import edit from './edit'; -import save from './save'; -import transforms from './transforms'; -import deprecated from './deprecated'; - -const settings = { - icon, - example: { - attributes: { - citation: 'Julio Cortázar', - }, - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { - content: __( 'In quoting others, we cite ourselves.' ), - }, - }, - ], - }, - transforms, - edit, - save, - deprecated, -}; - -export default settings; diff --git a/packages/block-library/src/quote/v2/save.js b/packages/block-library/src/quote/v2/save.js deleted file mode 100644 index 52db0c5cb5328f..00000000000000 --- a/packages/block-library/src/quote/v2/save.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * External dependencies - */ -import classNames from 'classnames'; - -/** - * WordPress dependencies - */ -import { InnerBlocks, RichText, useBlockProps } from '@wordpress/block-editor'; - -export default function save( { attributes } ) { - const { align, citation } = attributes; - const blockProps = useBlockProps.save( { - className: classNames( { - [ `has-text-align-${ align }` ]: align, - } ), - } ); - return ( -
- - { ! RichText.isEmpty( citation ) && ( - - ) } -
- ); -} diff --git a/packages/block-library/src/quote/v2/transforms.js b/packages/block-library/src/quote/v2/transforms.js deleted file mode 100644 index 0479beecf7d687..00000000000000 --- a/packages/block-library/src/quote/v2/transforms.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * WordPress dependencies - */ -import { - createBlock, - parseWithAttributeSchema, - rawHandler, - serialize, -} from '@wordpress/blocks'; - -const transforms = { - from: [ - { - type: 'block', - blocks: [ 'core/pullquote' ], - transform: ( { value, citation, anchor, fontSize, style } ) => { - return createBlock( - 'core/quote', - { - citation, - anchor, - fontSize, - style, - }, - parseWithAttributeSchema( value, { - type: 'array', - source: 'query', - selector: 'p', - query: { - content: { - type: 'string', - source: 'html', - }, - }, - } ).map( ( { content } ) => - createBlock( 'core/paragraph', { content } ) - ) - ); - }, - }, - { - type: 'block', - blocks: [ 'core/group' ], - transform: ( { anchor }, innerBlocks ) => - createBlock( 'core/quote', { anchor }, innerBlocks ), - }, - { - type: 'prefix', - prefix: '>', - transform: ( content ) => - createBlock( 'core/quote', {}, [ - createBlock( 'core/paragraph', { content } ), - ] ), - }, - { - type: 'raw', - schema: () => ( { - blockquote: { - children: '*', - }, - } ), - selector: 'blockquote', - transform: ( node ) => { - return createBlock( - 'core/quote', - // Don't try to parse any `cite` out of this content. - // * There may be more than one cite. - // * There may be more attribution text than just the cite. - // * If the cite is nested in the quoted text, it's wrong to - // remove it. - {}, - rawHandler( { - HTML: node.innerHTML, - mode: 'BLOCKS', - } ) - ); - }, - }, - { - type: 'block', - isMultiBlock: true, - blocks: [ '*' ], - isMatch: ( {}, blocks ) => { - return ! blocks.some( ( { name } ) => name === 'core/quote' ); - }, - __experimentalConvert: ( blocks ) => - createBlock( - 'core/quote', - {}, - blocks.map( ( block ) => - createBlock( - block.name, - block.attributes, - block.innerBlocks - ) - ) - ), - }, - ], - to: [ - { - type: 'block', - blocks: [ 'core/pullquote' ], - isMatch: ( {}, block ) => { - return block.innerBlocks.every( - ( { name } ) => name === 'core/paragraph' - ); - }, - transform: ( - { citation, anchor, fontSize, style }, - innerBlocks - ) => { - return createBlock( 'core/pullquote', { - value: serialize( innerBlocks ), - citation, - anchor, - fontSize, - style, - } ); - }, - }, - { - type: 'block', - blocks: [ 'core/group' ], - transform: ( { citation, anchor }, innerBlocks ) => - createBlock( - 'core/group', - { anchor }, - citation - ? [ - ...innerBlocks, - createBlock( 'core/paragraph', { - content: citation, - } ), - ] - : innerBlocks - ), - }, - { - type: 'block', - blocks: [ '*' ], - transform: ( { citation }, innerBlocks ) => - citation - ? [ - ...innerBlocks, - createBlock( 'core/paragraph', { - content: citation, - } ), - ] - : innerBlocks, - }, - ], -}; - -export default transforms; diff --git a/packages/e2e-test-utils/src/transform-block-to.js b/packages/e2e-test-utils/src/transform-block-to.js index 4a6968c684904e..1989698c001e4b 100644 --- a/packages/e2e-test-utils/src/transform-block-to.js +++ b/packages/e2e-test-utils/src/transform-block-to.js @@ -30,8 +30,5 @@ export async function transformBlockTo( name ) { await insertButton.evaluate( ( element ) => element.scrollIntoView() ); await insertButton.click(); - // Wait for the transformed block to appear. - const BLOCK_SELECTOR = '.block-editor-block-list__block'; - const BLOCK_NAME_SELECTOR = `[data-title="${ name }"]`; - await page.waitForSelector( `${ BLOCK_SELECTOR }${ BLOCK_NAME_SELECTOR }` ); + await page.evaluate( () => new Promise( requestIdleCallback ) ); } diff --git a/packages/e2e-tests/plugins/cpt-locking.php b/packages/e2e-tests/plugins/cpt-locking.php index f4fbdb99ffb25e..5ac97c9cfae520 100644 --- a/packages/e2e-tests/plugins/cpt-locking.php +++ b/packages/e2e-tests/plugins/cpt-locking.php @@ -19,7 +19,13 @@ function gutenberg_test_cpt_locking() { 'placeholder' => 'Add a description', ), ), - array( 'core/quote' ), + array( + 'core/quote', + array(), + array( + array( 'core/paragraph' ), + ), + ), array( 'core/columns' ), ); register_post_type( @@ -65,7 +71,13 @@ function gutenberg_test_cpt_locking() { 'templateLock' => false, ), array( - array( 'core/quote' ), + array( + 'core/quote', + array(), + array( + array( 'core/paragraph' ), + ), + ), array( 'core/paragraph', array( @@ -91,7 +103,13 @@ function gutenberg_test_cpt_locking() { 'templateLock' => 'all', ), array( - array( 'core/quote' ), + array( + 'core/quote', + array(), + array( + array( 'core/paragraph' ), + ), + ), array( 'core/paragraph', array( @@ -115,7 +133,13 @@ function gutenberg_test_cpt_locking() { 'core/group', array(), array( - array( 'core/quote' ), + array( + 'core/quote', + array(), + array( + array( 'core/paragraph' ), + ), + ), array( 'core/paragraph', array( diff --git a/packages/e2e-tests/specs/editor/blocks/__snapshots__/quote.test.js.snap b/packages/e2e-tests/specs/editor/blocks/__snapshots__/quote.test.js.snap index 57fcc6c61dbdd0..d1121eebc29bda 100644 --- a/packages/e2e-tests/specs/editor/blocks/__snapshots__/quote.test.js.snap +++ b/packages/e2e-tests/specs/editor/blocks/__snapshots__/quote.test.js.snap @@ -34,180 +34,86 @@ exports[`Quote can be converted to paragraphs and renders one paragraph block pe exports[`Quote can be converted to paragraphs and renders only one paragraph for the cite, if the quote is void 1`] = ` " +

+ + +

cite

" `; exports[`Quote can be created by converting a heading 1`] = ` " -

test

+
+

test

+
" `; exports[`Quote can be created by converting a paragraph 1`] = ` " -

test

+
+

test

+
" `; exports[`Quote can be created by converting multiple paragraphs 1`] = ` " -

one

two

+
+

one

+ + + +

two

+
" `; exports[`Quote can be created by typing "/quote" 1`] = ` " -

I’m a quote

+
+

I’m a quote

+
" `; exports[`Quote can be created by typing > in front of text of a paragraph block 1`] = ` " -

test

+
+

test

+
" `; exports[`Quote can be created by using > at the start of a paragraph block 1`] = ` " -

A quote

Another paragraph

-" -`; - -exports[`Quote can be merged into from a paragraph 1`] = ` -" -

test

-" -`; - -exports[`Quote can be split at the end and merged back 1`] = ` -" -

1

- +
+

A quote

+ -

-" -`; - -exports[`Quote can be split at the end and merged back 2`] = ` -" -

1

+

Another paragraph

+
" `; -exports[`Quote can be split at the end and merged back 3`] = ` +exports[`Quote can be split at the end 1`] = ` " -

1

-" -`; - -exports[`Quote can be split in the middle and merged back 1`] = ` -" -

1

c
+
+

1

+

- - - -

2

c
-" -`; - -exports[`Quote can be split in the middle and merged back 2`] = ` -" -

1

c
- - - -

2

c
-" -`; - -exports[`Quote can be split in the middle and merged back 3`] = ` -" -

1

c
- - - -

2

c
-" +" `; -exports[`Quote can be split in the middle and merged back 4`] = ` +exports[`Quote can be split at the end 2`] = ` " -

1

2

c
-" -`; - -exports[`Quote is transformed to a heading and a quote if the quote contains a citation 1`] = ` -" -

one

- - - -

cite
-" -`; - -exports[`Quote is transformed to a heading and a quote if the quote contains multiple paragraphs 1`] = ` -" -

one

- - - -

two

three

+
+

1

+
" `; - -exports[`Quote is transformed to a heading if the quote just contains one paragraph 1`] = ` -" -

one

-" -`; - -exports[`Quote is transformed to an empty heading if the quote is empty 1`] = ` -" -

-" -`; - -exports[`Quote the resuling quote after transforming to a heading can be transformed again 1`] = ` -" -

one

- - - -

two

cite
-" -`; - -exports[`Quote the resuling quote after transforming to a heading can be transformed again 2`] = ` -" -

one

- - - -

two

- - - -

cite
-" -`; - -exports[`Quote the resuling quote after transforming to a heading can be transformed again 3`] = ` -" -

one

- - - -

two

- - - -

cite

-" -`; diff --git a/packages/e2e-tests/specs/editor/blocks/quote.test.js b/packages/e2e-tests/specs/editor/blocks/quote.test.js index da4efefb38de13..7086a09ac3136c 100644 --- a/packages/e2e-tests/specs/editor/blocks/quote.test.js +++ b/packages/e2e-tests/specs/editor/blocks/quote.test.js @@ -77,7 +77,9 @@ describe( 'Quote', () => { await page.keyboard.type( 'one' ); await page.keyboard.press( 'Enter' ); await page.keyboard.type( 'two' ); - await transformBlockTo( 'Paragraph' ); + // Navigate to the citation to select the block. + await page.keyboard.press( 'ArrowRight' ); + await transformBlockTo( 'Unwrap' ); expect( await getEditedPostContent() ).toMatchSnapshot(); } ); @@ -89,7 +91,7 @@ describe( 'Quote', () => { await page.keyboard.type( 'two' ); await page.keyboard.press( 'ArrowRight' ); await page.keyboard.type( 'cite' ); - await transformBlockTo( 'Paragraph' ); + await transformBlockTo( 'Unwrap' ); expect( await getEditedPostContent() ).toMatchSnapshot(); } ); @@ -98,14 +100,15 @@ describe( 'Quote', () => { await insertBlock( 'Quote' ); await page.keyboard.press( 'ArrowRight' ); await page.keyboard.type( 'cite' ); - await transformBlockTo( 'Paragraph' ); + await transformBlockTo( 'Unwrap' ); expect( await getEditedPostContent() ).toMatchSnapshot(); } ); it( 'and renders a void paragraph if both the cite and quote are void', async () => { await insertBlock( 'Quote' ); - await transformBlockTo( 'Paragraph' ); + await page.keyboard.press( 'ArrowRight' ); // Select the quote + await transformBlockTo( 'Unwrap' ); expect( await getEditedPostContent() ).toMatchSnapshot(); } ); @@ -119,56 +122,6 @@ describe( 'Quote', () => { expect( await getEditedPostContent() ).toMatchSnapshot(); } ); - it( 'is transformed to an empty heading if the quote is empty', async () => { - await insertBlock( 'Quote' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'is transformed to a heading if the quote just contains one paragraph', async () => { - await insertBlock( 'Quote' ); - await page.keyboard.type( 'one' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'is transformed to a heading and a quote if the quote contains multiple paragraphs', async () => { - await insertBlock( 'Quote' ); - await page.keyboard.type( 'one' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'two' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'three' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'is transformed to a heading and a quote if the quote contains a citation', async () => { - await insertBlock( 'Quote' ); - await page.keyboard.type( 'one' ); - await page.keyboard.press( 'ArrowRight' ); - await page.keyboard.type( 'cite' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'the resuling quote after transforming to a heading can be transformed again', async () => { - await insertBlock( 'Quote' ); - await page.keyboard.type( 'one' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'two' ); - await page.keyboard.press( 'ArrowRight' ); - await page.keyboard.type( 'cite' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - await page.click( '[data-type="core/quote"]' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - await page.click( '[data-type="core/quote"]' ); - await transformBlockTo( 'Heading' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - it( 'can be converted to a pullquote', async () => { await insertBlock( 'Quote' ); await page.keyboard.type( 'one' ); @@ -180,16 +133,7 @@ describe( 'Quote', () => { expect( await getEditedPostContent() ).toMatchSnapshot(); } ); - it( 'can be merged into from a paragraph', async () => { - await insertBlock( 'Quote' ); - await insertBlock( 'Paragraph' ); - await page.keyboard.type( 'test' ); - await pressKeyTimes( 'ArrowLeft', 'test'.length ); - await page.keyboard.press( 'Backspace' ); - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'can be split at the end and merged back', async () => { + it( 'can be split at the end', async () => { await insertBlock( 'Quote' ); await page.keyboard.type( '1' ); await page.keyboard.press( 'Enter' ); @@ -200,46 +144,7 @@ describe( 'Quote', () => { await page.keyboard.press( 'Backspace' ); - // Expect empty paragraph inside quote block. - expect( await getEditedPostContent() ).toMatchSnapshot(); - - await page.keyboard.press( 'Backspace' ); - - // Expect quote without empty paragraphs. - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - - it( 'can be split in the middle and merged back', async () => { - await insertBlock( 'Quote' ); - await page.keyboard.type( '1' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( '2' ); - await page.keyboard.press( 'ArrowRight' ); - await page.keyboard.type( 'c' ); - await page.keyboard.press( 'ArrowUp' ); - await page.keyboard.press( 'ArrowUp' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.press( 'Enter' ); - - // Expect two quote blocks and empty paragraph in the middle. - expect( await getEditedPostContent() ).toMatchSnapshot(); - - await page.keyboard.press( 'Backspace' ); - - // Expect two quote blocks and empty paragraph in the first quote. - expect( await getEditedPostContent() ).toMatchSnapshot(); - - await page.keyboard.press( 'Backspace' ); - - // Expect two quote blocks. - expect( await getEditedPostContent() ).toMatchSnapshot(); - - await page.keyboard.press( 'ArrowLeft' ); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Backspace' ); - + // Expect the paragraph to be deleted. expect( await getEditedPostContent() ).toMatchSnapshot(); } ); } ); diff --git a/packages/e2e-tests/specs/editor/plugins/__snapshots__/cpt-locking.test.js.snap b/packages/e2e-tests/specs/editor/plugins/__snapshots__/cpt-locking.test.js.snap index a7d34618db0de4..4f502b2fd29b07 100644 --- a/packages/e2e-tests/specs/editor/plugins/__snapshots__/cpt-locking.test.js.snap +++ b/packages/e2e-tests/specs/editor/plugins/__snapshots__/cpt-locking.test.js.snap @@ -10,7 +10,9 @@ exports[`cpt locking template_lock all should insert line breaks when using ente -

+
+

+
@@ -28,7 +30,9 @@ exports[`cpt locking template_lock all should not error when deleting the cotent -

+
+

+
@@ -43,7 +47,9 @@ exports[`cpt locking template_lock all unlocked group should allow blocks to be -

+
+

+
" `; @@ -51,7 +57,9 @@ exports[`cpt locking template_lock all unlocked group should allow blocks to be exports[`cpt locking template_lock all unlocked group should allow blocks to be removed 1`] = ` "
-

+
+

+
" `; @@ -66,7 +74,9 @@ exports[`cpt locking template_lock false should allow blocks to be inserted 1`] -

+
+

+
@@ -88,7 +98,9 @@ exports[`cpt locking template_lock false should allow blocks to be moved 1`] = ` -

+
+

+
@@ -102,7 +114,9 @@ exports[`cpt locking template_lock false should allow blocks to be removed 1`] = -

+
+

+
@@ -120,7 +134,9 @@ exports[`cpt locking template_lock insert should allow blocks to be moved 1`] = -

+
+

+
diff --git a/packages/e2e-tests/specs/editor/plugins/__snapshots__/inner-blocks-render-appender.test.js.snap b/packages/e2e-tests/specs/editor/plugins/__snapshots__/inner-blocks-render-appender.test.js.snap index 231ef215354a85..480121a3ceb8f1 100644 --- a/packages/e2e-tests/specs/editor/plugins/__snapshots__/inner-blocks-render-appender.test.js.snap +++ b/packages/e2e-tests/specs/editor/plugins/__snapshots__/inner-blocks-render-appender.test.js.snap @@ -3,7 +3,9 @@ exports[`RenderAppender prop of InnerBlocks Users can customize the appender and can still insert blocks using exposed components 1`] = ` "
-

+
+

+
" `; @@ -11,7 +13,9 @@ exports[`RenderAppender prop of InnerBlocks Users can customize the appender and exports[`RenderAppender prop of InnerBlocks Users can dynamically customize the appender 1`] = ` "
-

+
+

+
diff --git a/packages/e2e-tests/specs/editor/plugins/__snapshots__/templates.test.js.snap b/packages/e2e-tests/specs/editor/plugins/__snapshots__/templates.test.js.snap index f089390857781a..054e38c501a4fb 100644 --- a/packages/e2e-tests/specs/editor/plugins/__snapshots__/templates.test.js.snap +++ b/packages/e2e-tests/specs/editor/plugins/__snapshots__/templates.test.js.snap @@ -10,7 +10,9 @@ exports[`templates Using a CPT with a predefined template Should add a custom po -

+
+

+
@@ -36,7 +38,9 @@ exports[`templates Using a CPT with a predefined template Should respect user ed -

+
+

+
diff --git a/packages/e2e-tests/specs/editor/plugins/block-variations.test.js b/packages/e2e-tests/specs/editor/plugins/block-variations.test.js index 090e4f2a9214cb..886382a4667b1e 100644 --- a/packages/e2e-tests/specs/editor/plugins/block-variations.test.js +++ b/packages/e2e-tests/specs/editor/plugins/block-variations.test.js @@ -148,6 +148,8 @@ describe( 'Block variations', () => { it( 'should show block information when no matching variation is found', async () => { await insertBlock( 'Large Quote' ); + // Select the quote block. + await page.keyboard.press( 'ArrowDown' ); const breadcrumb = await getActiveBreadcrumb(); expect( breadcrumb ).toEqual( 'Quote' ); const navigationItem = await getFirstNavigationItem(); diff --git a/packages/e2e-tests/specs/editor/plugins/cpt-locking.test.js b/packages/e2e-tests/specs/editor/plugins/cpt-locking.test.js index 6af9aeac8754b3..dbb4b8348f7c76 100644 --- a/packages/e2e-tests/specs/editor/plugins/cpt-locking.test.js +++ b/packages/e2e-tests/specs/editor/plugins/cpt-locking.test.js @@ -49,12 +49,12 @@ describe( 'cpt locking', () => { const shouldAllowBlocksToBeMoved = async () => { await page.click( - '.block-editor-rich-text__editable[data-type="core/paragraph"]' + 'div > .block-editor-rich-text__editable[data-type="core/paragraph"]' ); expect( await page.$( 'button[aria-label="Move up"]' ) ).not.toBeNull(); await page.click( 'button[aria-label="Move up"]' ); await page.type( - '.block-editor-rich-text__editable[data-type="core/paragraph"]', + 'div > .block-editor-rich-text__editable[data-type="core/paragraph"]', 'p1' ); expect( await getEditedPostContent() ).toMatchSnapshot(); @@ -193,7 +193,7 @@ describe( 'cpt locking', () => { it( 'should allow blocks to be removed', async () => { await page.type( - '.block-editor-rich-text__editable[data-type="core/paragraph"]', + 'div > .block-editor-rich-text__editable[data-type="core/paragraph"]', 'p1' ); await clickBlockToolbarButton( 'Options' ); diff --git a/packages/e2e-tests/specs/editor/plugins/inner-blocks-render-appender.test.js b/packages/e2e-tests/specs/editor/plugins/inner-blocks-render-appender.test.js index 3c25fd93541caa..81a7d943331bb4 100644 --- a/packages/e2e-tests/specs/editor/plugins/inner-blocks-render-appender.test.js +++ b/packages/e2e-tests/specs/editor/plugins/inner-blocks-render-appender.test.js @@ -98,6 +98,9 @@ describe( 'RenderAppender prop of InnerBlocks', () => { // Insert a quote block. await quoteButton.click(); + // Select the quote block. + await page.keyboard.press( 'ArrowDown' ); + // Verify if the custom block appender text changed as expected. await page.waitForXPath( `//*[contains(@class, "${ DYNAMIC_APPENDER_SELECTOR }")]/span[contains(@class, "single-blocks-appender")][contains(text(), "Single Blocks Appender")]` diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/multi-block-selection.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/multi-block-selection.test.js.snap index b75df36d20904f..6923de7cc83f3f 100644 --- a/packages/e2e-tests/specs/editor/various/__snapshots__/multi-block-selection.test.js.snap +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/multi-block-selection.test.js.snap @@ -146,22 +146,6 @@ exports[`Multi-block selection should handle Enter across blocks 2`] = ` " `; -exports[`Multi-block selection should merge into quote with correct selection 1`] = ` -" -

1[

- - - -

]2

-" -`; - -exports[`Multi-block selection should merge into quote with correct selection 2`] = ` -" -

1

&2

-" -`; - exports[`Multi-block selection should multi-select from within the list block 1`] = ` "

1

diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/writing-flow.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/writing-flow.test.js.snap index 71943003cf923f..37328170c07e11 100644 --- a/packages/e2e-tests/specs/editor/various/__snapshots__/writing-flow.test.js.snap +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/writing-flow.test.js.snap @@ -207,9 +207,9 @@ exports[`Writing Flow should navigate empty paragraphs 1`] = ` `; exports[`Writing Flow should not create extra line breaks in multiline value 1`] = ` -" -

-" +" +
+" `; exports[`Writing Flow should not delete surrounding space when deleting a selected word 1`] = ` diff --git a/packages/e2e-tests/specs/editor/various/block-switcher.test.js b/packages/e2e-tests/specs/editor/various/block-switcher.test.js index 945cd212528876..7adbac136cd2e1 100644 --- a/packages/e2e-tests/specs/editor/various/block-switcher.test.js +++ b/packages/e2e-tests/specs/editor/various/block-switcher.test.js @@ -28,7 +28,6 @@ describe( 'Block Switcher', () => { expect.arrayContaining( [ 'Group', 'Paragraph', - 'Quote', 'Heading', 'Pullquote', 'Columns', diff --git a/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js b/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js index 5e14d57dcd7596..c9d633a521a4da 100644 --- a/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js +++ b/packages/e2e-tests/specs/editor/various/multi-block-selection.test.js @@ -906,30 +906,6 @@ describe( 'Multi-block selection', () => { expect( await getEditedPostContent() ).toMatchSnapshot(); } ); - it( 'should merge into quote with correct selection', async () => { - await clickBlockAppender(); - await page.keyboard.type( '> 1[' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( ']2' ); - await page.keyboard.press( 'ArrowLeft' ); - // Select everything between []. - await pressKeyWithModifier( 'shift', 'ArrowLeft' ); - await pressKeyWithModifier( 'shift', 'ArrowLeft' ); - await pressKeyWithModifier( 'shift', 'ArrowLeft' ); - - // Test setup. - expect( await getEditedPostContent() ).toMatchSnapshot(); - - await page.keyboard.press( 'Backspace' ); - - // Ensure selection is in the correct place. - await page.keyboard.type( '&' ); - - // Expect two blocks with "&" in between. - expect( await getEditedPostContent() ).toMatchSnapshot(); - } ); - it( 'should select separator (single element block)', async () => { await clickBlockAppender(); await page.keyboard.type( '/hr' ); diff --git a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js index 16f8347b0fea58..9e2dfb5098e455 100644 --- a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js @@ -364,6 +364,8 @@ describe( 'Reusable blocks', () => { '.block-editor-block-list__block[aria-label="Block: Quote"]' ); await quoteBlock.click(); + // Select the quote block. + await page.keyboard.press( 'ArrowDown' ); await openDocumentSettingsSidebar(); await page.waitForXPath( '//*[@role="region"][@aria-label="Editor settings"]//button[.="Styles"]' diff --git a/packages/e2e-tests/specs/editor/various/writing-flow.test.js b/packages/e2e-tests/specs/editor/various/writing-flow.test.js index aa4d8ad8d8f313..b763924aef10d7 100644 --- a/packages/e2e-tests/specs/editor/various/writing-flow.test.js +++ b/packages/e2e-tests/specs/editor/various/writing-flow.test.js @@ -282,7 +282,7 @@ describe( 'Writing Flow', () => { } ); it( 'should not create extra line breaks in multiline value', async () => { - await insertBlock( 'Quote' ); + await insertBlock( 'List' ); await page.keyboard.type( 'a' ); await page.keyboard.press( 'Backspace' ); expect( await getEditedPostContent() ).toMatchSnapshot(); diff --git a/packages/edit-post/src/test/editor.native.js b/packages/edit-post/src/test/editor.native.js index c3e35e92598988..28aac9d3ae4238 100644 --- a/packages/edit-post/src/test/editor.native.js +++ b/packages/edit-post/src/test/editor.native.js @@ -35,9 +35,7 @@ afterAll( () => { } ); describe( 'Editor', () => { - beforeAll( () => { - registerCoreBlocks(); - } ); + beforeAll( registerCoreBlocks ); it( 'detects unsupported block and sends hasUnsupportedBlocks true to native', () => { RNReactNativeGutenbergBridge.editorDidMount = jest.fn(); diff --git a/packages/react-native-editor/src/setup.js b/packages/react-native-editor/src/setup.js index f31538b70f24b2..c9a71ef6c89601 100644 --- a/packages/react-native-editor/src/setup.js +++ b/packages/react-native-editor/src/setup.js @@ -58,12 +58,9 @@ const gutenbergSetup = () => { const setupInitHooks = () => { addAction( 'native.pre-render', 'core/react-native-editor', ( props ) => { - const capabilities = props.capabilities ?? {}; - const blocksFlags = { - __experimentalEnableQuoteBlockV2: props?.quoteBlockV2, - }; + registerBlocks(); - registerBlocks( blocksFlags ); + const capabilities = props.capabilities ?? {}; // Unregister non-supported blocks by capabilities if ( @@ -119,12 +116,12 @@ const setupInitHooks = () => { }; let blocksRegistered = false; -const registerBlocks = ( blocksFlags ) => { +const registerBlocks = () => { if ( blocksRegistered ) { return; } - registerCoreBlocks( blocksFlags ); + registerCoreBlocks(); blocksRegistered = true; }; diff --git a/packages/react-native-editor/src/test/index.test.js b/packages/react-native-editor/src/test/index.test.js index 05412dcfafcdaf..cc7a301421af7b 100644 --- a/packages/react-native-editor/src/test/index.test.js +++ b/packages/react-native-editor/src/test/index.test.js @@ -190,7 +190,8 @@ describe( 'Register Gutenberg', () => { {}, { component: EditorComponent } ); - const blockList = screen.getByTestId( 'block-list-wrapper' ); + // Inner blocks create BlockLists so let's take into account selecting the main one + const blockList = screen.getAllByTestId( 'block-list-wrapper' )[ 0 ]; expect( blockList ).toBeVisible(); expect( console ).toHaveLoggedWith( 'Hermes is: true' ); diff --git a/test/e2e/specs/editor/blocks/list.spec.js b/test/e2e/specs/editor/blocks/list.spec.js index eb5fec4d1d129e..99f60ae49693bc 100644 --- a/test/e2e/specs/editor/blocks/list.spec.js +++ b/test/e2e/specs/editor/blocks/list.spec.js @@ -313,23 +313,6 @@ test.describe( 'List', () => { ); } ); - test( 'can be created by converting a quote', async ( { - editor, - page, - } ) => { - await editor.insertBlock( { name: 'core/quote' } ); - await page.keyboard.type( 'one' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'two' ); - await editor.transformBlockTo( 'core/list' ); - - await expect.poll( editor.getEditedPostContent ).toBe( - ` -
  • one
  • two
-` - ); - } ); - test( 'can be converted to a quote', async ( { editor, page } ) => { await editor.insertBlock( { name: 'core/list' } ); await page.keyboard.type( 'one' ); @@ -339,7 +322,9 @@ test.describe( 'List', () => { await expect.poll( editor.getEditedPostContent ).toBe( ` -

one

two

+
+
  • one
  • two
+
` ); } ); diff --git a/test/e2e/specs/editor/blocks/quote.spec.js b/test/e2e/specs/editor/blocks/quote.spec.js index 843a2b8db67ee1..69d69f0003489f 100644 --- a/test/e2e/specs/editor/blocks/quote.spec.js +++ b/test/e2e/specs/editor/blocks/quote.spec.js @@ -23,7 +23,9 @@ test.describe( 'adding a quote', () => { const content = await editor.getEditedPostContent(); expect( content ).toBe( ` -

Quote content

+
+

Quote content

+
` ); } ); diff --git a/test/e2e/specs/editor/various/style-variation.spec.js b/test/e2e/specs/editor/various/style-variation.spec.js index 3971ab4888ddc9..cc13dd1ad9238e 100644 --- a/test/e2e/specs/editor/various/style-variation.spec.js +++ b/test/e2e/specs/editor/various/style-variation.spec.js @@ -17,6 +17,9 @@ test.describe( 'adding blocks', () => { attributes: { value: '

Quote content

' }, } ); + // Select the quote block. + await page.keyboard.press( 'ArrowDown' ); + await editor.clickBlockToolbarButton( 'Quote' ); await page.click( 'role=menuitem[name="Plain"i]' ); @@ -25,7 +28,9 @@ test.describe( 'adding blocks', () => { const content = await editor.getEditedPostContent(); expect( content ).toBe( ` -

Quote content

+
+

Quote content

+
` ); } ); diff --git a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap index 3bfd162ddddcc8..06f7a8d80716bb 100644 --- a/test/integration/__snapshots__/blocks-raw-handling.test.js.snap +++ b/test/integration/__snapshots__/blocks-raw-handling.test.js.snap @@ -28,6 +28,18 @@ exports[`Blocks raw handling pasteHandler should strip windows data 1`] = ` " `; +exports[`Blocks raw handling should correctly handle quotes with mixed content 1`] = ` +" +
+

chicken

+ + + +

ribs

+
+" +`; + exports[`rawHandler should convert HTML post to blocks with minimal content changes 1`] = ` "

Howdy

@@ -77,12 +89,20 @@ exports[`rawHandler should convert HTML post to blocks with minimal content chan -

Text.

+
+

Text.

+
- -

Heading

Text.

-" + +
+

Heading

+ + + +

Text.

+
+" `; exports[`rawHandler should convert a caption shortcode 1`] = ` diff --git a/test/integration/blocks-raw-handling.test.js b/test/integration/blocks-raw-handling.test.js index 34d6aaae3f6d3a..6e3f0e63aba946 100644 --- a/test/integration/blocks-raw-handling.test.js +++ b/test/integration/blocks-raw-handling.test.js @@ -288,110 +288,15 @@ describe( 'Blocks raw handling', () => { expect( console ).toHaveLogged(); } ); - it( 'should correctly handle quotes with one paragraphs and no citation', () => { - const filtered = pasteHandler( { - HTML: '

chicken

', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( - '

chicken

' - ); - expect( console ).toHaveLogged(); - } ); - it( 'should correctly handle quotes with multiple paragraphs and no citation', () => { - const filtered = pasteHandler( { - HTML: '

chicken

ribs

', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( - '

chicken

ribs

' - ); - expect( console ).toHaveLogged(); - } ); - - it( 'should correctly handle quotes with paragraph and citation at the end', () => { - const filtered = pasteHandler( { - HTML: '

chicken

ribs
', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( - '

chicken

ribs
' - ); - expect( console ).toHaveLogged(); - } ); - - it( 'should handle a citation before the content', () => { - const filtered = pasteHandler( { - HTML: '
ribs

ribs

', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( - '

ribs

ribs
' + it( 'should correctly handle quotes with mixed content', () => { + const filtered = serialize( + pasteHandler( { + HTML: '

chicken

ribs

', + mode: 'AUTO', + } ) ); - expect( console ).toHaveLogged(); - } ); - - it( 'should handle a citation in the middle of the content', () => { - const filtered = pasteHandler( { - HTML: '

chicken

ribs

ribs

', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( - '

chicken

ribs

ribs
' - ); - expect( console ).toHaveLogged(); - } ); - - it( 'should correctly handle quotes with only a citation', () => { - const filtered = pasteHandler( { - HTML: '
ribs
', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( - '

ribs
' - ); - expect( console ).toHaveLogged(); - } ); - - it( 'should convert to paragraph quotes with more than one cite', () => { - const filtered = pasteHandler( { - HTML: '
ribsribs
', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - - expect( filtered ).toBe( '

ribsribs

' ); - expect( console ).toHaveLogged(); - } ); - - it( 'should convert to paragraph quotes with more than one cite and at least one paragraph', () => { - const filtered = pasteHandler( { - HTML: '

chicken

ribsribs
', - mode: 'AUTO', - } ) - .map( getBlockContent ) - .join( '' ); - expect( filtered ).toBe( '

chickenribsribs

' ); + expect( filtered ).toMatchSnapshot(); expect( console ).toHaveLogged(); } ); diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-1.json b/test/integration/fixtures/blocks/core__quote__deprecated-1.json index f7d321059a6227..ea4a9a23196586 100644 --- a/test/integration/fixtures/blocks/core__quote__deprecated-1.json +++ b/test/integration/fixtures/blocks/core__quote__deprecated-1.json @@ -3,9 +3,18 @@ "name": "core/quote", "isValid": true, "attributes": { - "value": "

Testing deprecated quote block...

", "citation": "...with a caption" }, - "innerBlocks": [] + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "Testing deprecated quote block...", + "dropCap": false + }, + "innerBlocks": [] + } + ] } ] diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-1.serialized.html b/test/integration/fixtures/blocks/core__quote__deprecated-1.serialized.html index d865a5f09d9011..9f06d2409dc7a7 100644 --- a/test/integration/fixtures/blocks/core__quote__deprecated-1.serialized.html +++ b/test/integration/fixtures/blocks/core__quote__deprecated-1.serialized.html @@ -1,3 +1,5 @@ -

Testing deprecated quote block...

...with a caption
+
+

Testing deprecated quote block...

+...with a caption
diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-2.json b/test/integration/fixtures/blocks/core__quote__deprecated-2.json index 00631ad17dd7f9..2599674eeec7fe 100644 --- a/test/integration/fixtures/blocks/core__quote__deprecated-2.json +++ b/test/integration/fixtures/blocks/core__quote__deprecated-2.json @@ -3,10 +3,19 @@ "name": "core/quote", "isValid": true, "attributes": { - "value": "

Testing deprecated quote block...

", "citation": "...with a caption", "align": "right" }, - "innerBlocks": [] + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "Testing deprecated quote block...", + "dropCap": false + }, + "innerBlocks": [] + } + ] } ] diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-2.serialized.html b/test/integration/fixtures/blocks/core__quote__deprecated-2.serialized.html index 08271ab418b33b..024531d165d7e8 100644 --- a/test/integration/fixtures/blocks/core__quote__deprecated-2.serialized.html +++ b/test/integration/fixtures/blocks/core__quote__deprecated-2.serialized.html @@ -1,3 +1,5 @@ -

Testing deprecated quote block...

...with a caption
+
+

Testing deprecated quote block...

+...with a caption
diff --git a/test/integration/fixtures/blocks/core__quote__style-1.html b/test/integration/fixtures/blocks/core__quote__style-1.html index 4bfd0ef80e5d49..6a56433a56267d 100644 --- a/test/integration/fixtures/blocks/core__quote__style-1.html +++ b/test/integration/fixtures/blocks/core__quote__style-1.html @@ -1,3 +1,5 @@ - -

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

Matt Mullenweg, 2017
- + +
+

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

+Matt Mullenweg, 2017
+ diff --git a/test/integration/fixtures/blocks/core__quote__style-1.json b/test/integration/fixtures/blocks/core__quote__style-1.json index 90a8c88a23228e..d262a2fefc6f3e 100644 --- a/test/integration/fixtures/blocks/core__quote__style-1.json +++ b/test/integration/fixtures/blocks/core__quote__style-1.json @@ -3,9 +3,19 @@ "name": "core/quote", "isValid": true, "attributes": { - "value": "

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

", + "value": "", "citation": "Matt Mullenweg, 2017" }, - "innerBlocks": [] + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.", + "dropCap": false + }, + "innerBlocks": [] + } + ] } ] diff --git a/test/integration/fixtures/blocks/core__quote__style-1.parsed.json b/test/integration/fixtures/blocks/core__quote__style-1.parsed.json index 5a071b57a7a5c8..2491985cc6d87d 100644 --- a/test/integration/fixtures/blocks/core__quote__style-1.parsed.json +++ b/test/integration/fixtures/blocks/core__quote__style-1.parsed.json @@ -2,10 +2,22 @@ { "blockName": "core/quote", "attrs": {}, - "innerBlocks": [], - "innerHTML": "\n

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

Matt Mullenweg, 2017
\n", + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

\n", + "innerContent": [ + "\n

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

\n" + ] + } + ], + "innerHTML": "\n
Matt Mullenweg, 2017
\n", "innerContent": [ - "\n

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

Matt Mullenweg, 2017
\n" + "\n
", + null, + "Matt Mullenweg, 2017
\n" ] } ] diff --git a/test/integration/fixtures/blocks/core__quote__style-1.serialized.html b/test/integration/fixtures/blocks/core__quote__style-1.serialized.html index 4268c4139854e7..6a56433a56267d 100644 --- a/test/integration/fixtures/blocks/core__quote__style-1.serialized.html +++ b/test/integration/fixtures/blocks/core__quote__style-1.serialized.html @@ -1,3 +1,5 @@ -

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

Matt Mullenweg, 2017
+
+

The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.

+Matt Mullenweg, 2017
diff --git a/test/integration/fixtures/blocks/core__quote__style-2.html b/test/integration/fixtures/blocks/core__quote__style-2.html index d4ecdca350df1b..13c2762059ecfa 100644 --- a/test/integration/fixtures/blocks/core__quote__style-2.html +++ b/test/integration/fixtures/blocks/core__quote__style-2.html @@ -1,3 +1,5 @@ - -

There is no greater agony than bearing an untold story inside you.

Maya Angelou
- + +
+

There is no greater agony than bearing an untold story inside you.

+Maya Angelou
+ diff --git a/test/integration/fixtures/blocks/core__quote__style-2.json b/test/integration/fixtures/blocks/core__quote__style-2.json index bc8901ab9225dc..c7c699e4caf422 100644 --- a/test/integration/fixtures/blocks/core__quote__style-2.json +++ b/test/integration/fixtures/blocks/core__quote__style-2.json @@ -3,10 +3,20 @@ "name": "core/quote", "isValid": true, "attributes": { - "value": "

There is no greater agony than bearing an untold story inside you.

", + "value": "", "citation": "Maya Angelou", "className": "is-style-large" }, - "innerBlocks": [] + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "There is no greater agony than bearing an untold story inside you.", + "dropCap": false + }, + "innerBlocks": [] + } + ] } ] diff --git a/test/integration/fixtures/blocks/core__quote__style-2.parsed.json b/test/integration/fixtures/blocks/core__quote__style-2.parsed.json index fea7f9f380c46e..e6eef0e2ba9ed1 100644 --- a/test/integration/fixtures/blocks/core__quote__style-2.parsed.json +++ b/test/integration/fixtures/blocks/core__quote__style-2.parsed.json @@ -4,10 +4,22 @@ "attrs": { "className": "is-style-large" }, - "innerBlocks": [], - "innerHTML": "\n

There is no greater agony than bearing an untold story inside you.

Maya Angelou
\n", + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n

There is no greater agony than bearing an untold story inside you.

\n", + "innerContent": [ + "\n

There is no greater agony than bearing an untold story inside you.

\n" + ] + } + ], + "innerHTML": "\n
Maya Angelou
\n", "innerContent": [ - "\n

There is no greater agony than bearing an untold story inside you.

Maya Angelou
\n" + "\n
", + null, + "Maya Angelou
\n" ] } ] diff --git a/test/integration/fixtures/blocks/core__quote__style-2.serialized.html b/test/integration/fixtures/blocks/core__quote__style-2.serialized.html index b257de24088e9a..13c2762059ecfa 100644 --- a/test/integration/fixtures/blocks/core__quote__style-2.serialized.html +++ b/test/integration/fixtures/blocks/core__quote__style-2.serialized.html @@ -1,3 +1,5 @@ -

There is no greater agony than bearing an untold story inside you.

Maya Angelou
+
+

There is no greater agony than bearing an untold story inside you.

+Maya Angelou
diff --git a/test/integration/fixtures/documents/markdown-out.html b/test/integration/fixtures/documents/markdown-out.html index 5e4ddca850da3e..104996580b223e 100644 --- a/test/integration/fixtures/documents/markdown-out.html +++ b/test/integration/fixtures/documents/markdown-out.html @@ -39,7 +39,13 @@

Quote

-

First

Second

+
+

First

+ + + +

Second

+