-
Notifications
You must be signed in to change notification settings - Fork 383
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
[Gutenberg] Add amp-fit-text support to text blocks #1151
Changes from 1 commit
40e9982
bba71a9
92eeca2
4f814c3
91448b0
d1c2065
ed79521
78ff7aa
8e0f249
d76a23e
5a45e80
c3d9915
937035f
03ebbf1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"boss": true, | ||
"curly": true, | ||
"eqeqeq": true, | ||
"eqnull": true, | ||
"es3": true, | ||
"esversion": 6, | ||
"expr": true, | ||
"immed": true, | ||
"noarg": true, | ||
"nonbsp": true, | ||
"onevar": true, | ||
"quotmark": "single", | ||
"trailing": true, | ||
"undef": true, | ||
"unused": true, | ||
|
||
"browser": true, | ||
|
||
"globals": { | ||
"_": false, | ||
"Backbone": false, | ||
"jQuery": false, | ||
"JSON": false, | ||
"wp": false | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* exported ampEditorBlocks */ | ||
/* eslint no-magic-numbers: [ "error", { "ignore": [ 1, -1, 0 ] } ] */ | ||
|
||
var ampEditorBlocks = ( function() { | ||
var component = { | ||
|
||
/** | ||
* Holds data. | ||
*/ | ||
data: { | ||
textBlocks: [ | ||
'core/paragraph', | ||
'core/heading', | ||
'core/code', | ||
'core/quote', | ||
'core/subhead' | ||
] | ||
} | ||
}; | ||
|
||
/** | ||
* Set data, add filters. | ||
* | ||
* @param {Array} data Data. | ||
*/ | ||
component.boot = function boot( data ) { | ||
_.extend( component.data, data ); | ||
|
||
wp.hooks.addFilter( 'blocks.registerBlockType', 'ampEditorBlocks/addAttributes', component.addAMPAttributes ); | ||
wp.hooks.addFilter( 'blocks.BlockEdit', 'ampEditorBlocks/filterEdit', component.filterBlocksEdit ); | ||
wp.hooks.addFilter( 'blocks.getSaveElement', 'ampEditorBlocks/filterSave', component.filterBlocksSave ); | ||
}; | ||
|
||
/** | ||
* Add AMP attributes to every core block. | ||
* | ||
* @param {Object} settings Settings. | ||
* @param {string} name Block name. | ||
* @return {*} Settings. | ||
*/ | ||
component.addAMPAttributes = function addAMPAttributes( settings, name ) { | ||
// Fit-text for text blocks. | ||
if ( -1 !== component.data.textBlocks.indexOf( name ) ) { | ||
if ( ! settings.attributes ) { | ||
settings.attributes = {}; | ||
} | ||
settings.attributes.ampFitText = { | ||
type: 'boolean', | ||
default: false | ||
}; | ||
settings.attributes.minFont = { | ||
type: 'number' | ||
}; | ||
settings.attributes.maxFont = { | ||
type: 'number' | ||
}; | ||
settings.attributes.height = { | ||
type: 'number', | ||
default: 50 | ||
}; | ||
} | ||
return settings; | ||
}; | ||
|
||
/** | ||
* Filters blocks edit function of all blocks. | ||
* | ||
* @param {Function} BlockEdit Edit function. | ||
* @return {Function} Edit function. | ||
*/ | ||
component.filterBlocksEdit = function filterBlocksEdit( BlockEdit ) { | ||
var el = wp.element.createElement; | ||
|
||
return function( props ) { | ||
var name = props.name, | ||
inspectorControls; | ||
|
||
if ( -1 !== component.data.textBlocks.indexOf( name ) ) { | ||
inspectorControls = component.setUpTextBlocksInspectorControls( props ); | ||
} | ||
|
||
// Return original. | ||
return [ | ||
inspectorControls, | ||
el( BlockEdit, _.assign( { | ||
key: 'original' | ||
}, props ) ) | ||
]; | ||
}; | ||
}; | ||
|
||
/** | ||
* Setup inspector controls for text blocks. | ||
* | ||
* @param {Object} props Props. | ||
* @return {Object|Element|*|{$$typeof, type, key, ref, props, _owner}} Inspector Controls. | ||
*/ | ||
component.setUpTextBlocksInspectorControls = function setUpInspectorControls( props ) { | ||
var ampFitText = props.attributes.ampFitText, | ||
minFont = props.attributes.minFont, | ||
maxFont = props.attributes.maxFont, | ||
height = props.attributes.height, | ||
isSelected = props.isSelected, | ||
el = wp.element.createElement, | ||
InspectorControls = wp.blocks.InspectorControls, | ||
TextControl = wp.components.TextControl, | ||
ToggleControl = wp.components.ToggleControl, | ||
PanelBody = wp.components.PanelBody, | ||
label = 'Use AMP Fit Text'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs translation |
||
|
||
if ( ampFitText ) { | ||
return isSelected && ( | ||
el( InspectorControls, { key: 'inspector' }, | ||
el( PanelBody, { title: 'AMP Settings' }, | ||
el( ToggleControl, { | ||
label: label, | ||
checked: ampFitText, | ||
onChange: function() { | ||
props.setAttributes( { ampFitText: ! ampFitText } ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Most of the core blocks seem to use negating the current value for toggle controls (as far as I've seen), thought of staying consistent with the core blocks when using that. Thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this also result in the |
||
} | ||
} ), | ||
el( TextControl, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can the |
||
label: 'Height (px)', | ||
value: height, | ||
onChange: function( nextHeight ) { | ||
props.setAttributes( { height: nextHeight } ); | ||
} | ||
} ), | ||
el( TextControl, { | ||
label: 'Min font (px)', | ||
value: minFont, | ||
onChange: function( nextMinFont ) { | ||
props.setAttributes( { minFont: nextMinFont } ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Abort if |
||
} | ||
} ), | ||
el( TextControl, { | ||
label: 'Max font (px)', | ||
value: maxFont, | ||
onChange: function( nextMaxFont ) { | ||
props.setAttributes( { maxFont: nextMaxFont } ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make sure the |
||
} | ||
} ) | ||
) | ||
) | ||
); | ||
} | ||
|
||
return isSelected && ( | ||
el( InspectorControls, { key: 'inspector' }, | ||
el( PanelBody, { title: 'AMP Settings' }, | ||
el( ToggleControl, { | ||
label: label, | ||
checked: ampFitText, | ||
onChange: function() { | ||
props.setAttributes( { ampFitText: ! ampFitText } ); | ||
} | ||
} ) | ||
) | ||
) | ||
); | ||
}; | ||
|
||
/** | ||
* Filters blocks save function for core blocks except for dynamic blocks. | ||
* | ||
* @param {Object} element Element. | ||
* @param {Object} blockType Block type. | ||
* @param {Object} attributes Attributes. | ||
* @return {Object} Element. | ||
*/ | ||
component.filterBlocksSave = function filterBlocksSave( element, blockType, attributes ) { | ||
var fitTextProps = { | ||
layout: 'fixed-height', | ||
children: element | ||
}; | ||
// If the blockType is a dynamic block or if AMP layout isn't return original method. | ||
if ( -1 === component.data.textBlocks.indexOf( blockType.name ) || ! attributes.ampFitText ) { | ||
return element; | ||
} | ||
|
||
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; | ||
} | ||
return wp.element.createElement( 'amp-fit-text', fitTextProps ); | ||
}; | ||
|
||
return component; | ||
}() ); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php | ||
/** | ||
* AMP Editor Blocks extending. | ||
* | ||
* @package AMP | ||
* @since 1.0 | ||
*/ | ||
|
||
/** | ||
* Class AMP_Editor_Blocks | ||
*/ | ||
class AMP_Editor_Blocks { | ||
|
||
/** | ||
* Init. | ||
*/ | ||
public function init() { | ||
if ( function_exists( 'gutenberg_init' ) ) { | ||
add_action( 'admin_enqueue_scripts', array( $this, 'add_editor_filters' ) ); | ||
add_filter( 'wp_kses_allowed_html', array( $this, 'whitelist_layout_in_wp_kses_allowed_html' ), 10 ); | ||
} | ||
} | ||
|
||
/** | ||
* Whitelist used data-amp-* attributes. | ||
* | ||
* @param array $context Array of contexts. | ||
* @return mixed Modified array. | ||
*/ | ||
public function whitelist_layout_in_wp_kses_allowed_html( $context ) { | ||
foreach ( $context as $tag ) { | ||
$tag['data-amp-fit-text'] = true; | ||
} | ||
return $context; | ||
} | ||
|
||
/** | ||
* Enqueue filters for extending core blocks attributes. | ||
* Has to be loaded before registering the blocks in registerCoreBlocks. | ||
*/ | ||
public function add_editor_filters() { | ||
wp_enqueue_script( | ||
'amp-editor-blocks', | ||
amp_get_asset_url( 'js/amp-editor-blocks.js' ), | ||
array( 'amp-runtime', 'underscore', 'wp-hooks' ), | ||
AMP__VERSION, | ||
true | ||
); | ||
|
||
$dynamic_blocks = array(); | ||
$block_type_registry = WP_Block_Type_Registry::get_instance(); | ||
$block_types = $block_type_registry->get_all_registered(); | ||
|
||
foreach ( $block_types as $block_type ) { | ||
if ( $block_type->is_dynamic() ) { | ||
$dynamic_blocks[] = $block_type->name; | ||
} | ||
} | ||
|
||
wp_add_inline_script( 'amp-editor-blocks', sprintf( 'ampEditorBlocks.boot( %s );', | ||
wp_json_encode( array( | ||
'dynamicBlocks' => $dynamic_blocks, | ||
) ) | ||
) ); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return is
{Object}
, no?