diff --git a/assets/css/src/amp-block-editor.css b/assets/css/src/amp-block-editor.css index db36813bb0c..7a3a704efb5 100644 --- a/assets/css/src/amp-block-editor.css +++ b/assets/css/src/amp-block-editor.css @@ -1,8 +1,3 @@ -.is-amp-fit-text + .blocks-font-size > .components-font-size-picker__buttons, -.is-amp-fit-text + .blocks-font-size > .components-font-size-picker__custom-input { - display: none; -} - /* AMP preview button wrapper */ .wp-core-ui .amp-wrapper-post-preview { margin-left: -6px; diff --git a/assets/css/src/amp-default.css b/assets/css/src/amp-default.css index 43cc0027008..28dc272106a 100644 --- a/assets/css/src/amp-default.css +++ b/assets/css/src/amp-default.css @@ -11,16 +11,6 @@ amp-anim.amp-wp-enforced-sizes[layout="intrinsic"] > img { object-fit: contain; } -amp-fit-text blockquote, -amp-fit-text h1, -amp-fit-text h2, -amp-fit-text h3, -amp-fit-text h4, -amp-fit-text h5, -amp-fit-text h6 { - font-size: inherit; -} - /** * Override a style rule in Twenty Sixteen and Twenty Seventeen. * It set display:none for audio elements. diff --git a/assets/src/block-editor/helpers/index.js b/assets/src/block-editor/helpers/index.js index 1a051f8f5e0..e23fa30b84c 100644 --- a/assets/src/block-editor/helpers/index.js +++ b/assets/src/block-editor/helpers/index.js @@ -7,11 +7,11 @@ import { ReactElement } from 'react'; /** * WordPress dependencies */ -import { __, _x, sprintf } from '@wordpress/i18n'; -import { cloneElement } from '@wordpress/element'; -import { TextControl, SelectControl, ToggleControl, Notice, PanelBody, FontSizePicker } from '@wordpress/components'; +import { __, sprintf } from '@wordpress/i18n'; +import { SelectControl, ToggleControl, Notice, PanelBody } from '@wordpress/components'; import { InspectorControls } from '@wordpress/block-editor'; import { select } from '@wordpress/data'; +import { cloneElement } from '@wordpress/element'; /** * Internal dependencies @@ -115,38 +115,6 @@ export const addAMPAttributes = ( settings, name ) => { }; } - const isTextBlock = TEXT_BLOCKS.includes( name ); - - // Fit-text for text blocks. - if ( isTextBlock ) { - if ( ! settings.attributes ) { - settings.attributes = {}; - } - settings.attributes.ampFitText = { - type: 'boolean', - default: false, - }; - settings.attributes.minFont = { - default: MIN_FONT_SIZE, - source: 'attribute', - selector: 'amp-fit-text', - attribute: 'min-font-size', - }; - settings.attributes.maxFont = { - default: MAX_FONT_SIZE, - source: 'attribute', - selector: 'amp-fit-text', - attribute: 'max-font-size', - }; - settings.attributes.height = { - // Needs to be higher than the maximum font size, which defaults to MAX_FONT_SIZE - default: 'core/image' === name ? 200 : Math.ceil( MAX_FONT_SIZE / 10 ) * 10, - source: 'attribute', - selector: 'amp-fit-text', - attribute: 'height', - }; - } - // Layout settings for embeds and media blocks. if ( 0 === name.indexOf( 'core-embed' ) || MEDIA_BLOCKS.includes( name ) ) { if ( ! settings.attributes ) { @@ -163,68 +131,102 @@ export const addAMPAttributes = ( settings, name ) => { }; /** - * Filters blocks' save function. + * Removes `amp-fit-text` related attributes on blocks via block deprecation. * - * @param {Object} element Element to be saved. - * @param {string} blockType Block type. - * @param {string} blockType.name Block type name. - * @param {Object} attributes Attributes. + * @param {Object} settings Block settings. + * @param {string} name Block name. * - * @return {Object} Output element. + * @return {Object} Modified block settings. */ -export const filterBlocksSave = ( element, blockType, attributes ) => { // eslint-disable-line complexity - const fitTextProps = { - layout: 'fixed-height', - }; - - if ( 'core/paragraph' === blockType.name && ! attributes.ampFitText ) { - const content = getAmpFitTextContent( attributes.content ); - if ( content !== attributes.content ) { - return cloneElement( - element, - { - key: 'new', - value: content, - }, - ); - } - } else if ( TEXT_BLOCKS.includes( blockType.name ) && attributes.ampFitText ) { - if ( attributes.minFont ) { - fitTextProps[ 'min-font-size' ] = attributes.minFont; - } - if ( attributes.maxFont ) { - fitTextProps[ 'max-font-size' ] = attributes.maxFont; - } - if ( attributes.height ) { - fitTextProps.height = attributes.height; +export const removeAmpFitTextFromBlocks = ( settings, name ) => { + if ( TEXT_BLOCKS.includes( name ) ) { + if ( ! settings.deprecated ) { + settings.deprecated = []; } - fitTextProps.children = element; - - return ; + settings.deprecated.unshift( { + supports: settings.supports, + attributes: { + ...( settings.attributes || {} ), + ampFitText: { + type: 'boolean', + default: false, + }, + minFont: { + default: MIN_FONT_SIZE, + source: 'attribute', + selector: 'amp-fit-text', + attribute: 'min-font-size', + }, + maxFont: { + default: MAX_FONT_SIZE, + source: 'attribute', + selector: 'amp-fit-text', + attribute: 'max-font-size', + }, + height: { + // Needs to be higher than the maximum font size, which defaults to MAX_FONT_SIZE + default: 'core/image' === name ? 200 : Math.ceil( MAX_FONT_SIZE / 10 ) * 10, + source: 'attribute', + selector: 'amp-fit-text', + attribute: 'height', + }, + }, + save( props ) { + /* eslint-disable react/prop-types */ + const { attributes } = props; + const fitTextProps = { layout: 'fixed-height' }; + + if ( attributes.minFont ) { + fitTextProps[ 'min-font-size' ] = attributes.minFont; + } + if ( attributes.maxFont ) { + fitTextProps[ 'max-font-size' ] = attributes.maxFont; + } + if ( attributes.height ) { + fitTextProps.height = attributes.height; + } + /* eslint-enable react/prop-types */ + + fitTextProps.children = settings.save( props ); + + return ; + }, + isEligible( { ampFitText } ) { + return undefined !== ampFitText; + }, + migrate( attributes ) { + const deprecatedAttrs = [ 'ampFitText', 'minFont', 'maxFont', 'height' ]; + deprecatedAttrs.forEach( ( attr ) => delete attributes[ attr ] ); + return attributes; + }, + } ); } - return element; + return settings; }; /** - * Returns the inner content of an AMP Fit Text tag. + * Remove the `class` attribute from `amp-fit-text` elements so that it can be deprecated successfully. + * + * The `class` attribute is added by the `core/generated-class-name/save-props` block editor filter; it is unwanted and + * interferes with successful deprecation of the block. By filtering the saved element the `class` attribute can be + * removed and the deprecation of the block and proceed without error. + * + * @see removeAmpFitTextFromBlocks * - * @param {string} content Original content. + * @param {ReactElement} element Block save result. * - * @return {string} Modified content. + * @return {ReactElement} Modified block if it is of `amp-fit-text` type, otherwise the original element is returned. */ -export const getAmpFitTextContent = ( content ) => { - const contentRegex = /]*>(.*?)<\/amp-fit-text>/; - const match = contentRegex.exec( content ); - - let newContent = content; - - if ( match && match[ 1 ] ) { - newContent = match[ 1 ]; +export const removeClassFromAmpFitTextBlocks = ( element ) => { + if ( 'amp-fit-text' === element.type && undefined !== element.props.className ) { + const { className, ...props } = element.props; + props.className = null; + element = cloneElement( element, props ); } - return newContent; + return element; }; /** @@ -275,8 +277,6 @@ export const filterBlocksEdit = ( BlockEdit ) => { inspectorControls = setUpImageInspectorControls( props ); } else if ( MEDIA_BLOCKS.includes( name ) || 0 === name.indexOf( 'core-embed/' ) ) { inspectorControls = setUpInspectorControls( props ); - } else if ( TEXT_BLOCKS.includes( name ) ) { - inspectorControls = setUpTextBlocksInspectorControls( props ); } // Return just inspector controls in case of 'nodisplay'. @@ -478,146 +478,6 @@ AmpNoloadingToggle.propTypes = { setAttributes: PropTypes.func.isRequired, }; -/** - * Setup inspector controls for text blocks. - * - * @todo Consider wrapping the render function to delete the original font size in text settings when ampFitText. - * - * @param {Object} props Props. - * @param {Function} props.setAttributes Callback to set attributes. - * @param {Object} props.attributes Attributes. - * @param {boolean} props.isSelected Is selected. - * - * @return {ReactElement} Inspector Controls. - */ -const setUpTextBlocksInspectorControls = ( props ) => { - const { isSelected, attributes, setAttributes } = props; - const { ampFitText } = attributes; - let { minFont, maxFont, height } = attributes; - - const FONT_SIZES = [ - { - name: 'small', - shortName: _x( 'S', 'font size', 'amp' ), - size: 14, - }, - { - name: 'regular', - shortName: _x( 'M', 'font size', 'amp' ), - size: 16, - }, - { - name: 'large', - shortName: _x( 'L', 'font size', 'amp' ), - size: 36, - }, - { - name: 'larger', - shortName: _x( 'XL', 'font size', 'amp' ), - size: 48, - }, - ]; - - if ( ! isSelected ) { - return null; - } - - const label = __( 'Automatically fit text to container', 'amp' ); - - if ( ampFitText ) { - maxFont = parseInt( maxFont ); - height = parseInt( height ); - minFont = parseInt( minFont ); - } - - return ( - - - setAttributes( { ampFitText: ! ampFitText } ) } - /> - - { ampFitText && ( - <> - { - setAttributes( { height: nextHeight } ); - } } - /> - { maxFont > height && ( - - { __( 'The height must be greater than the max font size.', 'amp' ) } - - ) } - - { - if ( ! nextMinFont ) { - nextMinFont = MIN_FONT_SIZE; // @todo Supplying fallbackFontSize should be done automatically by the component? - } - - if ( parseInt( nextMinFont ) <= maxFont ) { - setAttributes( { minFont: nextMinFont } ); - } - } } - /> - - { minFont > maxFont && ( - - { __( 'The min font size must less than the max font size.', 'amp' ) } - - ) } - - { - if ( ! nextMaxFont ) { - nextMaxFont = MAX_FONT_SIZE; // @todo Supplying fallbackFontSize should be done automatically by the component? - } - - setAttributes( { - maxFont: nextMaxFont, - height: Math.max( nextMaxFont, height ), - } ); - } } - /> - - - ) } - - ); -}; - -setUpTextBlocksInspectorControls.propTypes = { - isSelected: PropTypes.bool, - attributes: PropTypes.shape( { - ampFitText: PropTypes.bool, - minFont: PropTypes.number, - maxFont: PropTypes.number, - height: PropTypes.number, - } ), - setAttributes: PropTypes.func.isRequired, -}; - /** * Get AMP Lightbox toggle control. * diff --git a/assets/src/block-editor/helpers/test/getAmpFitTextContent.js b/assets/src/block-editor/helpers/test/getAmpFitTextContent.js deleted file mode 100644 index d70e903c45b..00000000000 --- a/assets/src/block-editor/helpers/test/getAmpFitTextContent.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Internal dependencies - */ -import { getAmpFitTextContent } from '../'; - -describe( 'getAmpFitTextContent', () => { - it( 'should extract the element\'s content', () => { - const result = getAmpFitTextContent( 'Hello World' ); - expect( result ).toBe( 'Hello World' ); - } ); - - it( 'should extract the element\'s content even when there are some attributes', () => { - const result = getAmpFitTextContent( 'Hello World' ); - expect( result ).toBe( 'Hello World' ); - } ); -} ); diff --git a/assets/src/block-editor/index.js b/assets/src/block-editor/index.js index 5300f00990a..dc238acd3c0 100644 --- a/assets/src/block-editor/index.js +++ b/assets/src/block-editor/index.js @@ -12,7 +12,7 @@ import { select } from '@wordpress/data'; import { withFeaturedImageNotice } from '../common/components'; import { getMinimumFeaturedImageDimensions } from '../common/helpers'; import { withMediaLibraryNotice } from './components'; -import { addAMPAttributes, filterBlocksEdit, filterBlocksSave } from './helpers'; +import { addAMPAttributes, filterBlocksEdit, removeAmpFitTextFromBlocks, removeClassFromAmpFitTextBlocks } from './helpers'; import './store'; const { @@ -28,7 +28,8 @@ plugins.keys().forEach( ( modulePath ) => { } ); addFilter( 'blocks.registerBlockType', 'ampEditorBlocks/addAttributes', addAMPAttributes ); -addFilter( 'blocks.getSaveElement', 'ampEditorBlocks/filterSave', filterBlocksSave ); +addFilter( 'blocks.registerBlockType', 'ampEditorBlocks/deprecateAmpFitText', removeAmpFitTextFromBlocks ); +addFilter( 'blocks.getSaveElement', 'ampEditorBlocks/deprecateAmpFitText/removeMiscAttrs', removeClassFromAmpFitTextBlocks ); addFilter( 'editor.BlockEdit', 'ampEditorBlocks/filterEdit', filterBlocksEdit, 20 ); addFilter( 'editor.PostFeaturedImage', 'ampEditorBlocks/withFeaturedImageNotice', withFeaturedImageNotice ); addFilter( 'editor.MediaUpload', 'ampEditorBlocks/withMediaLibraryNotice', ( InitialMediaUpload ) => withMediaLibraryNotice( InitialMediaUpload, getMinimumFeaturedImageDimensions() ) ); diff --git a/includes/admin/class-amp-editor-blocks.php b/includes/admin/class-amp-editor-blocks.php index 543667740ea..dc420037b78 100644 --- a/includes/admin/class-amp-editor-blocks.php +++ b/includes/admin/class-amp-editor-blocks.php @@ -35,7 +35,6 @@ class AMP_Editor_Blocks { 'amp-jwplayer', 'amp-brid-player', 'amp-ima-video', - 'amp-fit-text', ]; /**