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

Gutenberg Block for Tweet Shortcode? #7597

Closed
wants to merge 21 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
728f07a
A good start maybe?
georgestephanis Aug 4, 2017
f3c43aa
Correct how we refer to the tweet attribute.
georgestephanis Aug 5, 2017
b9da75c
Update the prop when the field changes. Still not thrilled with this…
georgestephanis Aug 5, 2017
1fbb0d4
Add a dummy function to explore how we can parse this on initialization.
georgestephanis Aug 5, 2017
6817940
Somewhat tidier way of doing the script.
georgestephanis Aug 5, 2017
2e98277
Clear out some unused chaff.
georgestephanis Aug 7, 2017
7b3729b
Flesh out how to find the tweet url from the node.
georgestephanis Aug 7, 2017
eb7499e
Don't return the result of the array directly.
georgestephanis Aug 7, 2017
3d3cb22
Use onChange not onInput to satisfy browser console nag.
georgestephanis Aug 7, 2017
9b2f478
Add in handling for other optional attributes.
georgestephanis Aug 7, 2017
9b22ae0
Wrap it in the generated classname? Probably a good idea?
georgestephanis Aug 7, 2017
6fbc6c2
Oops, forgot the closing parens.
georgestephanis Aug 7, 2017
fb52f65
Set the generated shortcode to single.
georgestephanis Aug 7, 2017
2b8a30a
Change to an array so we can return multiples.
georgestephanis Aug 7, 2017
8d9f1f4
Add BlockControls AlignmentToolbar.
georgestephanis Aug 7, 2017
0b5476f
Add sidebar width control.
georgestephanis Aug 7, 2017
baa38bc
If there's a className to be set, wrap it in a div so it can be set o…
georgestephanis Aug 7, 2017
ba90d71
This is necessary so React doesn't turn `"` into `"`
georgestephanis Aug 7, 2017
32a0ea5
Rewrite attributes array to a function.
Aug 17, 2017
1f52720
Are you the keymaster?
Aug 17, 2017
ebe3953
Alias `el` to `wp.element.createElement`
Aug 17, 2017
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
58 changes: 58 additions & 0 deletions modules/shortcodes/tweet.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

add_shortcode( 'tweet', array( 'Jetpack_Tweet', 'jetpack_tweet_shortcode' ) );
add_action( 'enqueue_block_editor_assets', array( 'Jetpack_Tweet', 'enqueue_block_editor_assets' ) );

class Jetpack_Tweet {

Expand Down Expand Up @@ -142,4 +143,61 @@ static public function jetpack_tweet_shortcode_script() {
}
}

static public function enqueue_block_editor_assets() {
wp_enqueue_script( 'wp-blocks' );
wp_enqueue_script( 'wp-i18n' );
wp_enqueue_script( 'wp-element' );
wp_enqueue_script( 'shortcode' );
add_action( 'admin_print_footer_scripts', array( __CLASS__, 'admin_footer' ), 999 );
}

static public function admin_footer() {
?>
<script>
( function( wp ) {
var blockStyle = {
backgroundColor: '#900',
color: '#fff',
padding: '20px'
};

wp.blocks.registerBlockType( 'jetpack/tweet', {
title: wp.i18n.__( 'Tweet', 'jetpack' ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A text domain solution hasn't yet been implemented for __, so the second parameter has no effect here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue at nylen/gutenberg-examples#9

icon: 'twitter',
category: 'layout',

attributes : {
tweet : wp.blocks.query.query( 'input[name=tweet]').value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea with attribute matchers (or, perhaps soon to be called "sourced" values) is to avoid duplicating data between comment attributes and the actual saved markup of the block. For example, we don't need to serialize an image's URL into the comments blob if we know we can easily grab it from the img's src attribute. In more complex examples, duplication is inevitable or there's a need for hidden metadata.

So what we define in attributes purely relates to getting an object representation of the block back from the saved content, nothing to do with the edit-able render.

In your case, the saved content is a shortcode, from which you want to extract the tweet value. There's not a matcher for this (arguments could be made either way for whether we should add conveniences for shortcodes), so you might just want to let this live in comment metadata. Currently this is automatic if you set an attribute from your edit form but don't define it in the attributes property, but this is likely to change soon to be more explicit (i.e. define all attributes, both the ones sourced from content and those serialized into comments).

I'm supposing you were expecting that defining this here would establish a link between the attribute value and the input from edit, which is not the case. Instead, you'll want to explicitly call props.setAttributes from your edit function when the input changes, similar to the concept of a controlled input in React.

onInput: function( event ) {
	props.setAttributes({
		tweet: event.target.value
	});
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. I wasn't expecting anything really, just playing around and seeing how things connect.

Regarding extracting stuff out -- can the attribute matcher / sourced values be a custom function passed in that will return what we care about from the contents somehow? If so, I could just call wp.shortcode.next() on the contents of the block to extract and parse the shortcode and its parameters -- I've already enqueued shortcodes.js on the page for later usage building it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently this is possible by defining attributes as a function, which is passed the raw content (string) of the block and expected to return an object of attributes.

https://github.com/WordPress/gutenberg/blob/33542dd/blocks/api/parser.js#L28-L29
https://github.com/WordPress/gutenberg/blob/master/blocks/README.md#wpblocksregisterblocktype-name-string-typedefinition-object-

However, with increasing pressure to introduce server-capable attributes schemas / parsing, I'm not sure whether this can be relied upon.

Some more discussion at: WordPress/gutenberg#1905

},

edit : function( props ) {
return wp.element.createElement(
'input',
{
name : 'tweet',
type : 'url',
value : props.tweet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

props isn't the attributes of the block, but attributes can be accessed from props.attributes. There are a number of other values in props as well, such as setAttributes noted in the previous comment.

Instead, this would be: props.attributes.tweet

},
null
);
},

save : function( props ) {
return wp.shortcode.string({
tag : 'tweet',
attrs : {
named : {},
numeric : [
props.tweet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, this would be: props.attributes.tweet

]
}
});
}

} );
} )( window.wp );
</script>
<?php
}

} // class end