diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 38ad3e2e11bd13..b5112f5502b932 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -771,7 +771,7 @@ Give quoted text visual emphasis. "In quoting others, we cite ourselves." — Ju - **Name:** core/quote - **Category:** text - **Supports:** anchor, color (background, gradients, heading, link, text), interactivity (clientNavigation), layout (~~allowEditing~~), spacing (blockGap), typography (fontSize, lineHeight), ~~html~~ -- **Attributes:** align, citation, value +- **Attributes:** citation, textAlign, value ## Read More diff --git a/packages/block-editor/src/components/block-list/block-list-item.native.js b/packages/block-editor/src/components/block-list/block-list-item.native.js index c91bee36a10c4a..769e634b6741c2 100644 --- a/packages/block-editor/src/components/block-list/block-list-item.native.js +++ b/packages/block-editor/src/components/block-list/block-list-item.native.js @@ -98,7 +98,7 @@ function BlockListItemContent( { const name = getBlockName( clientId ); const parentName = getBlockName( rootClientId ); const { align } = getBlockAttributes( clientId ) || {}; - const { align: parentBlockAlign } = + const { textAlign: parentBlockAlign } = getBlockAttributes( rootClientId ) || {}; return { diff --git a/packages/block-library/src/paragraph/test/edit.native.js b/packages/block-library/src/paragraph/test/edit.native.js index 3d09068c24930c..9cbd2344ced7e7 100644 --- a/packages/block-library/src/paragraph/test/edit.native.js +++ b/packages/block-library/src/paragraph/test/edit.native.js @@ -12,6 +12,7 @@ import { initializeEditor, render, setupCoreBlocks, + triggerBlockListLayout, waitFor, within, withFakeTimers, @@ -213,6 +214,41 @@ describe( 'Paragraph block', () => { ` ); } ); + it( 'should inherit parent alignment', async () => { + // Arrange + const screen = await initializeEditor(); + await addBlock( screen, 'Quote' ); + await triggerBlockListLayout( getBlock( screen, 'Quote' ) ); + + // Act + const paragraphBlock = getBlock( screen, 'Paragraph' ); + fireEvent.press( paragraphBlock ); + const paragraphTextInput = + within( paragraphBlock ).getByPlaceholderText( 'Start writing…' ); + typeInRichText( + paragraphTextInput, + 'A quick brown fox jumps over the lazy dog.' + ); + fireEvent.press( screen.getByLabelText( 'Navigate Up' ) ); + fireEvent.press( screen.getByLabelText( 'Align text' ) ); + fireEvent.press( screen.getByLabelText( 'Align text right' ) ); + + // Assert + // This not an ideal assertion, as it relies implementation details of the + // component: prop names. However, the only aspect we can assert is the prop + // passed to Aztec, the native module controlling visual alignment. A less + // brittle alternative might be snapshotting, but RNTL does not yet support + // focused snapshots, which means the snapshot would be huge. + // https://github.com/facebook/react/pull/25329 + expect( + screen.UNSAFE_queryAllByProps( { + value: '

A quick brown fox jumps over the lazy dog.

', + placeholder: 'Start writing…', + textAlign: 'right', + } ).length + ).toBe( 2 ); // One for Aztec mock, one for the TextInput. + } ); + it( 'should preserve alignment when split', async () => { // Arrange const screen = await initializeEditor(); diff --git a/packages/block-library/src/quote/block.json b/packages/block-library/src/quote/block.json index b66e64bce2eead..7ad713a13373a1 100644 --- a/packages/block-library/src/quote/block.json +++ b/packages/block-library/src/quote/block.json @@ -22,7 +22,7 @@ "selector": "cite", "__experimentalRole": "content" }, - "align": { + "textAlign": { "type": "string" } }, diff --git a/packages/block-library/src/quote/deprecated.js b/packages/block-library/src/quote/deprecated.js index 052ac5b5c9c372..fcf6776b762362 100644 --- a/packages/block-library/src/quote/deprecated.js +++ b/packages/block-library/src/quote/deprecated.js @@ -7,7 +7,7 @@ import classnames from 'classnames'; * WordPress dependencies */ import { createBlock, parseWithAttributeSchema } from '@wordpress/blocks'; -import { RichText, useBlockProps } from '@wordpress/block-editor'; +import { InnerBlocks, RichText, useBlockProps } from '@wordpress/block-editor'; export const migrateToQuoteV2 = ( attributes ) => { const { value, ...restAttributes } = attributes; @@ -34,6 +34,102 @@ export const migrateToQuoteV2 = ( attributes ) => { ]; }; +const TEXT_ALIGN_OPTIONS = [ 'left', 'right', 'center' ]; + +// Migrate existing text alignment settings to the renamed attribute. +const migrateTextAlign = ( attributes, innerBlocks ) => { + const { align, ...rest } = attributes; + // Check if there are valid alignments stored in the old attribute + // and assign them to the new attribute name. + const migratedAttributes = TEXT_ALIGN_OPTIONS.includes( align ) + ? { ...rest, textAlign: align } + : attributes; + + return [ migratedAttributes, innerBlocks ]; +}; + +// Migrate the v2 blocks with style === `2`; +const migrateLargeStyle = ( attributes, innerBlocks ) => { + return [ + { + ...attributes, + className: attributes.className + ? attributes.className + ' is-style-large' + : 'is-style-large', + }, + innerBlocks, + ]; +}; + +// Version before the 'align' attribute was replaced with 'textAlign'. +const v4 = { + 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, + html: false, + __experimentalOnEnter: true, + __experimentalOnMerge: true, + typography: { + fontSize: true, + lineHeight: true, + __experimentalFontFamily: true, + __experimentalFontWeight: true, + __experimentalFontStyle: true, + __experimentalTextTransform: true, + __experimentalTextDecoration: true, + __experimentalLetterSpacing: true, + __experimentalDefaultControls: { + fontSize: true, + fontAppearance: true, + }, + }, + color: { + gradients: true, + heading: true, + link: true, + __experimentalDefaultControls: { + background: true, + text: true, + }, + }, + }, + isEligible: ( { align } ) => TEXT_ALIGN_OPTIONS.includes( align ), + save( { attributes } ) { + const { align, citation } = attributes; + const className = classnames( { + [ `has-text-align-${ align }` ]: align, + } ); + return ( +
+ + { ! RichText.isEmpty( citation ) && ( + + ) } +
+ ); + }, + migrate: migrateTextAlign, +}; + const v3 = { attributes: { value: { @@ -87,7 +183,9 @@ const v3 = { ); }, - migrate: migrateToQuoteV2, + migrate( attributes ) { + return migrateTextAlign( ...migrateToQuoteV2( attributes ) ); + }, }; const v2 = { @@ -109,7 +207,9 @@ const v2 = { type: 'string', }, }, - migrate: migrateToQuoteV2, + migrate( attributes ) { + return migrateTextAlign( ...migrateToQuoteV2( attributes ) ); + }, save( { attributes } ) { const { align, value, citation } = attributes; @@ -151,15 +251,12 @@ const v1 = { migrate( attributes ) { if ( attributes.style === 2 ) { const { style, ...restAttributes } = attributes; - return migrateToQuoteV2( { - ...restAttributes, - className: attributes.className - ? attributes.className + ' is-style-large' - : 'is-style-large', - } ); + return migrateTextAlign( + ...migrateLargeStyle( ...migrateToQuoteV2( restAttributes ) ) + ); } - return migrateToQuoteV2( attributes ); + return migrateTextAlign( ...migrateToQuoteV2( attributes ) ); }, save( { attributes } ) { @@ -206,12 +303,10 @@ const v0 = { migrate( attributes ) { if ( ! isNaN( parseInt( attributes.style ) ) ) { const { style, ...restAttributes } = attributes; - return migrateToQuoteV2( { - ...restAttributes, - } ); + return migrateTextAlign( ...migrateToQuoteV2( restAttributes ) ); } - return migrateToQuoteV2( attributes ); + return migrateTextAlign( ...migrateToQuoteV2( attributes ) ); }, save( { attributes } ) { @@ -239,4 +334,4 @@ const v0 = { * * See block-deprecation.md */ -export default [ v3, v2, v1, v0 ]; +export default [ v4, v3, v2, v1, v0 ]; diff --git a/packages/block-library/src/quote/edit.js b/packages/block-library/src/quote/edit.js index 32c99bf7d097db..4689899c6a91e8 100644 --- a/packages/block-library/src/quote/edit.js +++ b/packages/block-library/src/quote/edit.js @@ -74,7 +74,7 @@ export default function QuoteEdit( { className, style, } ) { - const { align, citation } = attributes; + const { textAlign, citation } = attributes; useMigrateOnLoad( attributes, clientId ); @@ -86,7 +86,7 @@ export default function QuoteEdit( { const blockProps = useBlockProps( { className: classNames( className, { - [ `has-text-align-${ align }` ]: align, + [ `has-text-align-${ textAlign }` ]: textAlign, } ), ...( ! isWebPlatform && { style } ), } ); @@ -100,9 +100,9 @@ export default function QuoteEdit( { <> { - setAttributes( { align: nextAlign } ); + setAttributes( { textAlign: nextAlign } ); } } /> @@ -132,7 +132,7 @@ export default function QuoteEdit( { createBlock( getDefaultBlockName() ) ) } - { ...( ! isWebPlatform ? { textAlign: align } : {} ) } + { ...( ! isWebPlatform ? { textAlign } : {} ) } /> ) } diff --git a/packages/block-library/src/quote/save.js b/packages/block-library/src/quote/save.js index 7b6ecab8762eb5..c932c50e5c9551 100644 --- a/packages/block-library/src/quote/save.js +++ b/packages/block-library/src/quote/save.js @@ -9,10 +9,10 @@ import classNames from 'classnames'; import { InnerBlocks, RichText, useBlockProps } from '@wordpress/block-editor'; export default function save( { attributes } ) { - const { align, citation } = attributes; + const { textAlign, citation } = attributes; const className = classNames( { - [ `has-text-align-${ align }` ]: align, + [ `has-text-align-${ textAlign }` ]: textAlign, } ); return ( diff --git a/packages/block-library/src/quote/test/__snapshots__/transforms.native.js.snap b/packages/block-library/src/quote/test/__snapshots__/transforms.native.js.snap index 65d87d5b0d7bd4..edd5c40ae916ba 100644 --- a/packages/block-library/src/quote/test/__snapshots__/transforms.native.js.snap +++ b/packages/block-library/src/quote/test/__snapshots__/transforms.native.js.snap @@ -3,7 +3,7 @@ exports[`Quote block transforms to Columns block 1`] = ` "
-
+

"This will make running your own blog a viable alternative again."

Adrian Zumbrunnen
@@ -14,7 +14,7 @@ exports[`Quote block transforms to Columns block 1`] = ` exports[`Quote block transforms to Group block 1`] = ` " -
+

"This will make running your own blog a viable alternative again."

Adrian Zumbrunnen
diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-2.json b/test/integration/fixtures/blocks/core__quote__deprecated-2.json index 2599674eeec7fe..2af2f38fa9e937 100644 --- a/test/integration/fixtures/blocks/core__quote__deprecated-2.json +++ b/test/integration/fixtures/blocks/core__quote__deprecated-2.json @@ -4,7 +4,7 @@ "isValid": true, "attributes": { "citation": "...with a caption", - "align": "right" + "textAlign": "right" }, "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 024531d165d7e8..3d135fffad4374 100644 --- a/test/integration/fixtures/blocks/core__quote__deprecated-2.serialized.html +++ b/test/integration/fixtures/blocks/core__quote__deprecated-2.serialized.html @@ -1,4 +1,4 @@ - +

Testing deprecated quote block...

...with a caption
diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.html b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.html new file mode 100644 index 00000000000000..218b75debb682d --- /dev/null +++ b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.html @@ -0,0 +1,5 @@ + +
+

Quote with the align attribute. Example: {"align":"right"}

+
+ diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.json b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.json new file mode 100644 index 00000000000000..c5b6d35aa427fc --- /dev/null +++ b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.json @@ -0,0 +1,22 @@ +[ + { + "name": "core/quote", + "isValid": true, + "attributes": { + "value": "", + "citation": "", + "textAlign": "right" + }, + "innerBlocks": [ + { + "name": "core/paragraph", + "isValid": true, + "attributes": { + "content": "Quote with the align attribute. Example: {\"align\":\"right\"}", + "dropCap": false + }, + "innerBlocks": [] + } + ] + } +] diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.parsed.json b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.parsed.json new file mode 100644 index 00000000000000..e7dddc8ecbb604 --- /dev/null +++ b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.parsed.json @@ -0,0 +1,25 @@ +[ + { + "blockName": "core/quote", + "attrs": { + "align": "right" + }, + "innerBlocks": [ + { + "blockName": "core/paragraph", + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n

Quote with the align attribute. Example: {\"align\":\"right\"}

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

Quote with the align attribute. Example: {\"align\":\"right\"}

\n" + ] + } + ], + "innerHTML": "\n
\n", + "innerContent": [ + "\n
", + null, + "
\n" + ] + } +] diff --git a/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.serialized.html b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.serialized.html new file mode 100644 index 00000000000000..dfad3d54b991e4 --- /dev/null +++ b/test/integration/fixtures/blocks/core__quote__deprecated-4-align-attribute.serialized.html @@ -0,0 +1,5 @@ + +
+

Quote with the align attribute. Example: {"align":"right"}

+
+