Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Remove amp-fit-text block setting #5729

Merged
merged 7 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions assets/css/src/amp-block-editor.css
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
10 changes: 0 additions & 10 deletions assets/css/src/amp-default.css
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
308 changes: 84 additions & 224 deletions assets/src/block-editor/helpers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 ) {
Expand All @@ -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 <amp-fit-text { ...fitTextProps } />;
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 <amp-fit-text { ...fitTextProps } />;
},
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\b[^>]*>(.*?)<\/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;
};

/**
Expand Down Expand Up @@ -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'.
Expand Down Expand Up @@ -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 (
<InspectorControls>
<PanelBody
title={ __( 'AMP Settings', 'amp' ) }
className={ ampFitText ? 'is-amp-fit-text' : '' }
>
<ToggleControl
label={ label }
checked={ ampFitText }
onChange={ () => setAttributes( { ampFitText: ! ampFitText } ) }
/>
</PanelBody>
{ ampFitText && (
<>
<TextControl
label={ __( 'Height', 'amp' ) }
value={ height }
min={ 1 }
onChange={ ( nextHeight ) => {
setAttributes( { height: nextHeight } );
} }
/>
{ maxFont > height && (
<Notice
status="error"
isDismissible={ false }
>
{ __( 'The height must be greater than the max font size.', 'amp' ) }
</Notice>
) }
<PanelBody title={ __( 'Minimum font size', 'amp' ) }>
<FontSizePicker
fallbackFontSize={ 14 }
value={ minFont }
fontSizes={ FONT_SIZES }
onChange={ ( nextMinFont ) => {
if ( ! nextMinFont ) {
nextMinFont = MIN_FONT_SIZE; // @todo Supplying fallbackFontSize should be done automatically by the component?
}

if ( parseInt( nextMinFont ) <= maxFont ) {
setAttributes( { minFont: nextMinFont } );
}
} }
/>
</PanelBody>
{ minFont > maxFont && (
<Notice
status="error"
isDismissible={ false }
>
{ __( 'The min font size must less than the max font size.', 'amp' ) }
</Notice>
) }
<PanelBody title={ __( 'Maximum font size', 'amp' ) }>
<FontSizePicker
fallbackFontSize={ 48 }
value={ maxFont }
fontSizes={ FONT_SIZES }
onChange={ ( nextMaxFont ) => {
if ( ! nextMaxFont ) {
nextMaxFont = MAX_FONT_SIZE; // @todo Supplying fallbackFontSize should be done automatically by the component?
}

setAttributes( {
maxFont: nextMaxFont,
height: Math.max( nextMaxFont, height ),
} );
} }
/>
</PanelBody>
</>
) }
</InspectorControls>
);
};

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.
*
Expand Down
Loading