Add iframe raw handling (e.g. Google Maps)#4660
Conversation
blocks/editable/index.js
Outdated
|
|
||
| export default withContext( 'editor' )( | ||
| ( settings ) => ( { | ||
| unfilteredHTML: settings && settings.unfilteredHTML, |
There was a problem hiding this comment.
@iseulde Do you think it would be better to use the withAPIData component and check user.data.capabilities.unfiltered_html? example here
There was a problem hiding this comment.
Good point, didn't think of that. Will try tomorrow.
I tested this in latest Chrome on macOS and it works! :-)
I think you mean author, right? If so, this is working correctly. Editors can post unfiltered HTML. |
Yes, sorry. Didn't realise editors have the cap as well. I updated the PR, but since the |
|
If someone could review, that'd be great! :) |
|
|
||
| let wrapper = node; | ||
|
|
||
| while ( wrapper.nodeName !== 'P' ) { |
There was a problem hiding this comment.
I think you might need while( wrapper && wrapper.nodeName ) here, because the final iteration might be a node with parentElement = null.
There was a problem hiding this comment.
Thanks! I changed it from while ( wrapper.nodeName !== 'P' && ( wrapper = wrapper.parentElement ) ) {} and forgot to add the check. 🙈 Nice catch.
e901e18 to
43a94ba
Compare
|
Rebased after |
lib/client-assets.php
Outdated
| 'colors' => $color_palette, | ||
| 'blockTypes' => $allowed_block_types, | ||
| 'titlePlaceholder' => apply_filters( 'enter_title_here', __( 'Add title', 'gutenberg' ), $post ), | ||
| 'alignWide' => $align_wide || ! empty( $gutenberg_theme_support[0]['wide-images'] ), // Backcompat. Use `align-wide` outside of `gutenberg` array. |
There was a problem hiding this comment.
PHPCS warnings from misaligned arrows here (causing the build failure)
There was a problem hiding this comment.
Actually, I think these are duplicated and need to be removed. Maybe from a bad rebase?
| onReplace( block.uid, rawHandler( { | ||
| HTML: serialize( block ), | ||
| mode: 'BLOCKS', | ||
| allowIframes: get( user, 'data.capabilities.unfiltered_html', false ), |
There was a problem hiding this comment.
Minor: String argument to get requires additional parsing and is slightly less performant than passing as an array, e.g.:
allowIframes: get( user, [ 'data', 'capabilities', 'unfiltered_html' ], false ),There was a problem hiding this comment.
Makes me wonder if we should have some equivalent of selectors for withAPIData too, rather than working with the REST properties directly, something like a currentUserCan
|
|
||
| getChildContext() { | ||
| return { | ||
| unfilteredHTML: get( this.props.user, 'data.capabilities.unfiltered_html', false ), |
There was a problem hiding this comment.
The name unfilteredHTML isn't entirely clear to me: At first, I thought this was passing some HTML string, not a true / false permissions thing. Maybe allowUnfilteredHTML ? isUnfilteredHTMLAllowed ?
There was a problem hiding this comment.
canUserUseUnfilteredHTML? It's a mouthful, but a recognizable phrasing.
| import inlineBlockCorrector from '../inline-block-corrector'; | ||
| import { deepFilterHTML } from '../utils'; | ||
|
|
||
| describe( 'inlineContentConverter', () => { |
| import { deepFilterHTML } from '../utils'; | ||
|
|
||
| describe( 'inlineContentConverter', () => { | ||
| it( 'should move inline-block content from paragraph', () => { |
There was a problem hiding this comment.
It would be useful to have some of these behaviors documented (README.md and/or JSDoc on the functions themselves). By the name inlineBlockCorrector, I had no idea what to expect from its behavior.
I'm coming to this mostly unfamiliar with the raw handlers, so I expect it'd be a common sentiment.
blocks/api/raw-handling/utils.js
Outdated
| ); | ||
| } | ||
|
|
||
| export function isInlineBlock( node ) { |
There was a problem hiding this comment.
Fun with JavaScript 😄
blocks/api/raw-handling/index.js
Outdated
| formattingTransformer, | ||
| stripAttributes, | ||
| commentRemover, | ||
| ...iframeUnwrapper, |
There was a problem hiding this comment.
Since we're already dealing with an array (the one provided to deepFilterHTML), we can simplify this:
deepFilterHTML( piece, compact( [
…
allowIframes && unwrapper,
inlineBlockCorrector,
…
] ) )Alternatively, we could use .filter( Boolean ).
| */ | ||
| const { ELEMENT_NODE } = window.Node; | ||
|
|
||
| export default function( node ) { |
There was a problem hiding this comment.
This needs a comment and a high-level explanation of what and why.
| const hasImage = node.querySelector( 'img' ); | ||
|
|
||
| return tag === 'img' || ( hasImage && ! hasText ) || ( hasImage && tag === 'figure' ); | ||
| return tag === 'img' || ( hasImage && tag === 'figure' ); |
There was a problem hiding this comment.
Do we know this to be an improvement? For instance, pasting <p>Behold my picture: <img src="..."> Isn't it amazing?</p> yields Image<…> + Paragraph<Behold…amazing?>.
I ask because it change seems tangential to the iframe support. Should we try this separately?
There was a problem hiding this comment.
Yes, the same fix is needed for iframes as well as images. Otherwise the image just ends up inside a paragraph. Most of the time, this structure goes together with alignment, so it is not visually clear where the image was anchored.
blocks/api/raw-handling/utils.js
Outdated
| br: {}, | ||
| }; | ||
|
|
||
| const inlineBlockWhiteList = { |
There was a problem hiding this comment.
I'm a bit concerned that all these lists and moving parts in raw-handling grow hard to keep track of, e.g. "inline" vs "inline wrapper" vs. "inline block". Docs in this file would help.
|
|
||
| getChildContext() { | ||
| return { | ||
| unfilteredHTML: get( this.props.user, 'data.capabilities.unfiltered_html', false ), |
There was a problem hiding this comment.
canUserUseUnfilteredHTML? It's a mouthful, but a recognizable phrasing.
1c29b3e to
6d56c2d
Compare
|
I think I addressed all concerns. |
6d56c2d to
2f30eeb
Compare
|
Rebased. |
2f30eeb to
6a54e94
Compare
|
This PR also indirectly fixes a bug where multiple images in a paragraph are all removed except for the first. |
| /** | ||
| * External dependencies | ||
| */ | ||
| import { equal } from 'assert'; |
There was a problem hiding this comment.
Curious why we're using the built-in assert lib here rather than Jest?
There was a problem hiding this comment.
It's been used all over this paste module since the beginning. I can change this.
There was a problem hiding this comment.
Not a fan of the globals :|
blocks/api/raw-handling/utils.js
Outdated
|
|
||
| export function isWhitelisted( element ) { | ||
| return !! whitelist[ element.nodeName.toLowerCase() ]; | ||
| return !! whitelist.hasOwnProperty( element.nodeName.toLowerCase() ); |
There was a problem hiding this comment.
The type coercion is unnecessary (hasOwnProperty will certainly return a boolean).
blocks/api/raw-handling/utils.js
Outdated
| export function isInline( node, tagName ) { | ||
| const nodeName = node.nodeName.toLowerCase(); | ||
| return !! inlineWhitelist[ nodeName ] || isInlineForTag( nodeName, tagName ); | ||
| return !! inlineWhitelist.hasOwnProperty( nodeName ) || isInlineForTag( nodeName, tagName ); |
There was a problem hiding this comment.
The type coercion is unnecessary (hasOwnProperty will certainly return a boolean).
blocks/api/raw-handling/utils.js
Outdated
| * @return {boolean} True if embedded content, false if not. | ||
| */ | ||
| export function isEmbedded( node ) { | ||
| return !! embeddedWhiteList.hasOwnProperty( node.nodeName.toLowerCase() ); |
There was a problem hiding this comment.
The type coercion is unnecessary (hasOwnProperty will certainly return a boolean).
blocks/api/raw-handling/utils.js
Outdated
|
|
||
| export function isInlineWrapper( node ) { | ||
| return !! inlineWrapperWhiteList[ node.nodeName.toLowerCase() ]; | ||
| return !! inlineWrapperWhiteList.hasOwnProperty( node.nodeName.toLowerCase() ); |
There was a problem hiding this comment.
The type coercion is unnecessary (hasOwnProperty will certainly return a boolean).
blocks/rich-text/index.js
Outdated
| plainText: this.pastedPlainText, | ||
| mode, | ||
| tagName: this.props.tagName, | ||
| allowIframes: this.context.canUserUseUnfilteredHTML, |
There was a problem hiding this comment.
Are we ever expecting allowScript, allowInput, allowStyle?
Maybe we just pass the canUserUseUnfilteredHTML verbatim as the property name?
|
Thanks @aduth, feedback addressed. :) |
bbb2e78 to
fedb8d0
Compare
|
After reviews from 3 people in the last two weeks, I think this is ready for merge. |

Description
How Has This Been Tested?