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

Only use rich text value internally to the RichText component #10439

Merged
merged 6 commits into from
Oct 10, 2018

Conversation

ellatrix
Copy link
Member

@ellatrix ellatrix commented Oct 9, 2018

Description

This is a proposal to use the string format on the RichText component by default.

Benefits:

  • The block attribute values are plain HTML, so I'd be no longer concerned about plugin authors manipulating the raw rich text value directly.
  • Plain HTML can be passed to createBlock to create templates.
  • The rich text value is only used internally to rich text. No other code should be aware of this value shape.
  • It would be okay if the value is not serialisable as JSON. It will never be in the global state.
  • The value can be stored in the block comments.
  • No need to start recommending different formats for different use cases such as post meta.
  • The format is internal only so we can continue to make improvements.

Cons:

  • Slightly less performant, but I would consider this is negligible.

How has this been tested?

Screenshots

Types of changes

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.

@ellatrix
Copy link
Member Author

ellatrix commented Oct 9, 2018

@youknowriad This may be of interest to you.

@ellatrix ellatrix added the [Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable label Oct 9, 2018
@ellatrix ellatrix added this to the 4.0 milestone Oct 9, 2018
Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

It does feel nicer from the block's author pov to only have to deal with html strings. (I proposed this a long time ago :P) But what about performance? Having to serialize/parse html for RichText on each render seems overkill?


/**
* Internal dependencies
*/
export { matcher as node } from './node';
export { matcher as children } from './children';

export function richText( selector, multilineTag ) {
export function html( selector, multilineTag ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the regular html matcher from hpq is not sufficient?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because this one would accept multilineTag as an argument for multiline RichText values. Otherwise we'd have to go back to the query matcher and map the values to and from RichText. I don't mind doing that with strings though. Before this was an issue because it would create a new array or object every time, but with a string we can easily compare.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for explaining, I'm not too concerned about that. multiline seems fine.

Copy link
Member

Choose a reason for hiding this comment

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

This feels a bit strange to me as well, since it's something of a preprocessing filter that doesn't serve much purpose outside the RichText use-case.

Curious: What happens if we don't have this at all?

Copy link
Member Author

Choose a reason for hiding this comment

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

It would include e.g. the cite. As I said, the alternative would be to revert to using query and map the values on each render. I like that solution less, but since it's just a string now I don't care as much.

Copy link
Member

@aduth aduth Oct 10, 2018

Choose a reason for hiding this comment

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

We're looking at this too much through the lens of Rich Text. If we need the matcher to support filtering, that's one thing. But on that basis alone, "multiline" doesn't make much sense to me. I'd rather some general support of aggregates, a property which more accurately reflects the child selector (e.g. #6716 (comment)), or reverting to query as you mention.

Copy link
Member

Choose a reason for hiding this comment

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

Where will this discussion continue? Are we going to launch 4.0 with the multiline property for html attribute sources?

Copy link
Contributor

Choose a reason for hiding this comment

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

I personally thought it was a good compromise as opposed to the "artificial" key we had to use when using the query matcher. And I thought this "multiline" option was supposed to fix that.

@ellatrix
Copy link
Member Author

ellatrix commented Oct 9, 2018

But what about performance? Having to serialize/parse html for RichText on each render seems overkill?

Honestly I think it is negligible, but we can do some testing. The only addition would be serialising to HTML on input and this should be very fast. Additionally this only happens per RichText instance, not the whole block or whole editor content.

@ellatrix ellatrix force-pushed the try/rich-text-string-value branch 2 times, most recently from 0fed26a to 8ed4ae2 Compare October 9, 2018 14:15
@ellatrix ellatrix force-pushed the try/rich-text-string-value branch from 8ed4ae2 to 4e1599c Compare October 9, 2018 14:55
@youknowriad
Copy link
Contributor

I'm still hesitant between this and #10370. Regardless, I think we should do something in synchronizeBlocksWithTemplate in this PR to ensure a smooth transition from old templates where the source is html but the template contain an array as a value. (upgrade and probably deprecate as well).

The last hesitation for me would be the performance, so we do when do we do this parsing/serialization:

  • on first render of the RichText component we parse
  • if the prop value changes, we parse again?
  • When tinymce triggers a change, I suppose we parse and serialize?

How does this differ from having the attribute as the internal representation directly?

Also pinging @aduth for a second opinion.

@youknowriad
Copy link
Contributor

I pushed a commit on this branch making the current templates work:

add_action( 'init', function() {
	register_post_type( 'book', [
		'label' => 'Book',
		'show_in_rest' => true,
		'public' => true,
		'show_ui' => true,
		'supports' => [ 'title', 'editor' ],
		'template' => [
			[ 'core/paragraph', [
				'content' => 'Hello first paragraph!',
			] ],
			[ 'core/paragraph', [
				'content' => [
					'Hello ',
					[
						'type' => 'strong',
						'props' => [ 'children' => 'world' ]
					],
					'!'
				],
			] ],

			[ 'core/gallery', [
				'images' => [
					[
						'url' => 'https://picsum.photos/200/300',
						'caption' => [
							'Hello ',
								[
									'type' => 'strong',
									'props' => [ 'children' => 'world' ]
								],
								'!'
						]
					]
				],
			] ],
		],
		'template_lock' => 'all',
	] );
} );

@youknowriad
Copy link
Contributor

Last thing here, I'd like to add is to remove the "children" deprecations for now. My idea is the following:

  • Ship this new format without deprecations
  • This will allow us to test it in real scenarios in prod without asking people to change their blocks yet.
  • If the result is satisfying in terms of performance, we reintroduce the deprecations in the next version asking people to use "html strings" consistently.

@youknowriad youknowriad force-pushed the try/rich-text-string-value branch from 68bba9d to 9ec19f0 Compare October 10, 2018 09:44
Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

There are many subtle differences in the output html produced for snapshots in unit tests which raises questions why it has changed.

@@ -63,7 +63,7 @@ describe( 'splitting and merging blocks', () => {
await page.keyboard.press( 'Backspace' );

// Replace contents of first paragraph with "Bar".
await pressTimes( 'Backspace', 3 );
await pressTimes( 'Backspace', 4 );
Copy link
Member

Choose a reason for hiding this comment

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

That's surprising, any ideas why it needs to be updated?

Copy link
Member Author

Choose a reason for hiding this comment

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

The caret is now placed outside the inline boundary so it requires one more backspace.

Copy link
Member

Choose a reason for hiding this comment

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

I don't know that its strictly an issue here, but caret placement in and around inline boundaries has been historically problematic and inconsistent and we should be careful to avoid worsening this. e.g. in some cases depending on internal state of TinyMCE, caret will still move inside inline boundary when backspacing (e.g. if Enter + Backspace when at end of a paragraph inside inline boundary).

Related: #9040 (internal state not an issue if its not preserved)

exports[`adding blocks should clean TinyMCE content 1`] = `""`;
exports[`adding blocks should clean TinyMCE content 1`] = `
"<!-- wp:paragraph -->
<p></p>
Copy link
Member

Choose a reason for hiding this comment

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

Do we know why it's different?

@@ -10,7 +10,7 @@ exports[`templates Using a CPT with a predefined template Should add a custom po
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class=\\"wp-block-quote\\"><p></p></blockquote>
<blockquote class=\\"wp-block-quote\\"></blockquote>
Copy link
Member

Choose a reason for hiding this comment

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

Do we know why it no longer prints <p />?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because the initial content of quote will be undefined. This is how it was before the rich text value merge:

https://github.com/WordPress/gutenberg/pull/7890/files#diff-632d636fb9c39f4f593363386f77cedf

@@ -179,7 +178,7 @@ export class RichText extends Component {
} ) );

// Save back to HTML from React tree
const html = '<' + tagName + '>' + toHTMLString( value ) + '</' + tagName + '>';
const html = '<' + tagName + '>' + value + '</' + tagName + '>';
Copy link
Member

Choose a reason for hiding this comment

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

@hypest can you help testing if this still works with mobile app?

Copy link
Contributor

Choose a reason for hiding this comment

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

Tested against the current mobile app master (wordpress-mobile/gutenberg-mobile@6f5e350) and works fine 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

❤️ to both of you.

value: '',
};

RichTextContainer.getTextContent = ( html ) => {
Copy link
Member

Choose a reason for hiding this comment

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

It feels like RichText component should be moved to @wordpress/rich-text package to avoid this duality where you can have two version of each of the public methods:

import { join } from '@wordpress/rich-text';
import { RichText } from '@wordpress/editor';

join === RichText.join; // false

It feels like with the changes proposed join should remain private, and RichText.join would be the only public API.

Copy link
Member Author

Choose a reason for hiding this comment

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

This has changed now.

},
},
],

merge( attributes, attributesToMerge ) {
return {
content: concat( attributes.content, attributesToMerge.content ),
content: RichText.concat( attributes.content, attributesToMerge.content ),
Copy link
Member

Choose a reason for hiding this comment

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

What's the difference between this and attributes.content + attributesToMerge.content ?

Will that difference be obvious to someone who thinks that they are working with strings?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm actually changing this right now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated.


/**
* Internal dependencies
*/
export { matcher as node } from './node';
export { matcher as children } from './children';

export function richText( selector, multilineTag ) {
export function html( selector, multilineTag ) {
Copy link
Member

Choose a reason for hiding this comment

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

This feels a bit strange to me as well, since it's something of a preprocessing filter that doesn't serve much purpose outside the RichText use-case.

Curious: What happens if we don't have this at all?

@@ -191,15 +191,13 @@ export function matcherFromSource( sourceConfig ) {

return matcher;
case 'html':
return html( sourceConfig.selector );
return html( sourceConfig.selector, sourceConfig.multiline );
Copy link
Member

Choose a reason for hiding this comment

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

It's not obvious what purpose multiline serves when considering html in isolation outside the RichText use-case. We're kinda muddying the distinction between these sources.

}

const content = <RawHTML>{ html }</RawHTML>;

if ( Tag ) {
return <Tag { ...props }>{ content }</Tag>;
return <Tag { ...omit( props, [ 'format', 'multiline' ] ) }>{ content }</Tag>;
Copy link
Member

Choose a reason for hiding this comment

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

Are these considered deprecated? Will they ever be removed?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can remove multiline as it was added after the last release.

@youknowriad youknowriad force-pushed the try/rich-text-string-value branch from cef3ef9 to 643133b Compare October 10, 2018 12:49
@aduth
Copy link
Member

aduth commented Oct 10, 2018

Previously: #5380 (Some "gotchas" which might be relevant here)

@aduth
Copy link
Member

aduth commented Oct 10, 2018

Reiterating Riad's point, this is certainly an improvement from the developer experience angle over what we'd be introducing with rich-text (and had with children). I feel quite positive about it from that angle.

Trying to understand the performance impact, I think the impact is an acceptable compromise. It makes me wonder what options we might have for future optimization: If I press a single character, shouldn't this be able to be applied to the internal representation easily without re-parsing/filtering the element in its entirety? Not saying that needs to be done here or even immediately after, but if that's an idea which has been considered to be pursued, I could see how it would offset (or even produce net benefit to) the performance cost paid here.

Re: #5380 and with regard to other ongoing work with annotations, do we plan to support the use case where developers can interact with the rich text value if they need to? I suppose that is a matter of using the rich-text package and its utilities? There is an added cost here if it requires double-creating the same rich-text value from a single field.

Interestingly one of the issues with #5380 which led to its closing was the need for a custom serializer, which we now have (twice over).

In all, I think we're in a much better position than we were in #5380 with our separations (rich-text, escape-html) to support this.

- `wp.blocks.children.fromDOM` has been removed. Please use `wp.richTextValue.create` instead.
- `wp.blocks.children.concat` has been removed. Please use `wp.richTextValue.concat` instead.
- `wp.blocks.children.getChildrenArray` has been removed. Please use `wp.richTextValue.create` instead.
Gutenberg's deprecation policy is intended to support backwards-compatibility for two minor releases, when possible. The current deprecations are listed below and are grouped by _the version at which they will be removed completely_. If your plugin depends on these behaviors, you must update to the recommended alternative before the noted version.s
Copy link
Member Author

Choose a reason for hiding this comment

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

There's a trailing 's' here :)

@ellatrix
Copy link
Member Author

Trying to understand the performance impact, I think the impact is an acceptable compromise. It makes me wonder what options we might have for future optimization: If I press a single character, shouldn't this be able to be applied to the internal representation easily without re-parsing/filtering the element in its entirety? Not saying that needs to be done here or even immediately after, but if that's an idea which has been considered to be pursued, I could see how it would offset (or even produce net benefit to) the performance cost paid here.

Yes, I've been thinking about this too. Some browsers pass extra info to the input event which we could use to apply it immediately to the internal state.

Re: #5380 and with regard to other ongoing work with annotations, do we plan to support the use case where developers can interact with the rich text value if they need to? I suppose that is a matter of using the rich-text package and its utilities? There is an added cost here if it requires double-creating the same rich-text value from a single field.

Yes, through the formatting API (and perhaps and additional future ones) you'll be able to interact with the internal rich text values with helpers. Nothing changes here.

Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

  1. New post
  2. Enter title
  3. Click writing prompt
  4. Cmd+B to bold
  5. Click "Save draft"
  6. Reload page

Expected: One of either:

Actual: Empty paragraph, no strong.

Related to writing flow E2E change.

@@ -203,7 +203,7 @@ export const settings = {

return ( href &&
<div>
{ ! isEmpty( fileName ) &&
{ ! RichText.isEmpty( fileName ) &&
Copy link
Member

Choose a reason for hiding this comment

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

fileName is a string. Why should we need utility.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we could get rid of the is empty utility as well now. I'm fine either way.

Copy link
Member

Choose a reason for hiding this comment

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

Considering them as strings, I see no need for the utility.

aduth
aduth previously requested changes Oct 10, 2018
Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

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

  1. New post
  2. Click writing prompt
  3. Cmd+B to bold
  4. Type something
  5. Press Enter
  6. Press Backspace
  7. Press Enter

Expected: Typing in second paragraph.
Actual: Second paragraph created, but caret remains in first.

Works as expected in 3.9.0.
Should have E2E case (could extend "should merge into inline boundary position")

@ellatrix
Copy link
Member Author

Thanks for the tests @aduth, addressing them now.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

LGTM 👍

I acknowledge that there's still a small bug when merging blocks. Let's create an issue for it and address it separately.

@ellatrix ellatrix dismissed aduth’s stale review October 10, 2018 17:44

Some issues address, the other will be addressed separately.

@ellatrix ellatrix merged commit e7d674d into master Oct 10, 2018
@ellatrix ellatrix deleted the try/rich-text-string-value branch October 10, 2018 17:45
@ktmn
Copy link

ktmn commented Oct 19, 2018

@youknowriad

I pushed a commit on this branch making the current templates work

When a block attribute was for storing rich text value I used type: 'array' for it previously, now it should have no type at all, correct? That seems the only way for me to make it work with the old templates and new rich text.

If the result is satisfying in terms of performance, we reintroduce the deprecations in the next version asking people to use "html strings" consistently.

Does that mean any old blocks that stored the rich text value as an array (in block comments, not using source: 'html') will eventually break?
Because when I don't enforce the block attribute type, creating a new block will store it as a string:

<!-- wp:custom/block {"content":"Content"} -->
<div class="wp-block-custom-block">Content</div>
<!-- /wp:custom/block -->

but when the block was previously created by a template for example:

<wp.editor.InnerBlocks
	template={[
		['custom/block', {content: ['Content']}],
	]}
/>

it will be stored as an array

<!-- wp:custom/block {"content":["Content"]} -->
<div class="wp-block-custom-block">Content</div>
<!-- /wp:custom/block -->

Is that block going to be invalid somewhere down the line?

What is the alternative way to create templates now? How do I convert this to new format for example:

[ 'core/paragraph', [
	'content' => [
		'Hello ',
		[
			'type' => 'strong',
			'props' => [ 'children' => 'world' ]
		],
		'!'
	],
] ],

Or can I keep using this format?

I'm so confused about these rich text changes, 4.0 broke everything even though I thought it was going to be backwards compatible. (Every block got This block contains unexpected or invalid content. error because my attribute type was array which I suppose wasn't supposed to be defined? Then I changed it to string which I thought was the way to go but then old templates didn't work, now I removed it completely and there's a PR that will change it to string again #10756 (?), which will break old templates? So confused...)

@youknowriad
Copy link
Contributor

@ktmn Sorry for the breakage. It was meant to be backward compatible but we probably missed something there, a bug. Can I suggest that you you try Gutenberg RC's before their release. We did these RC periods specifically to gather feedback about things we missed?

That said, can you create a separate issue with a small block example and the corresponding template that broke so we could take a look?

@ktmn
Copy link

ktmn commented Oct 19, 2018

@youknowriad Yeah it's my bad for missing the RC, never followed the WordPress blog to see it's announcement.

I'm just trying to figure out what the attribute type for rich text needs to be and how to do the new templates.

That said, can you create a separate issue with a small block example and the corresponding template that broke so we could take a look?

For example this plugin with Gutenberg 4.0, create an "Advanced button", add some text to it, save and refresh. This block contains unexpected or invalid content. This isn't my plugin or anything but it already exhibits some lack of backwards compatibility.

Oh, and old templates "break" if the rich text attribute is type: 'string' since the old template inserts an array and it gets removed (breaks after refresh). So the solution is to not use a type, so it's not a bug, it was never supposed to have a type?

@youknowriad
Copy link
Contributor

So here's the best path forward in term of blocks:

  • use string
  • use html instead of children as a source
  • use strings in templates.

We did manage to try to transform array in templates automatically to strings when the source is html to ensure backward compatibility.

How's that look for you?

@youknowriad
Copy link
Contributor

What I am wondering is why your blocks without any change broke the templates as we tried to keep the children sources with their corresponding templates as is.

@ktmn
Copy link

ktmn commented Oct 19, 2018

What I am wondering is why your blocks without any change broke the templates as we tried to keep the children sources with their corresponding templates as is.

In short, this is how my block looked like:

{
	attributes: {
		content: {
			type: 'array',
		},
	},
	edit: ({attributes, setAttributes}) => {
		return (
			<div className='custom-block'>
				<wp.editor.RichText
					value={attributes.content}
					onChange={value => setAttributes({content: value})}
				/>
			</div>
		)
	},
	save: ({attributes}) => {
		return (
			<div className='custom-block'>
				{attributes.content}
			</div>
		)
	},
}

After 4.0.0 that produced This block contains unexpected or invalid content. after refreshing the editor, since the rich text now returns a string and I guess it get's removed from the block comments because it doesn't match the type specified.

So I changed it to string:

{
	attributes: {
		content: {
			type: 'string',
		},
	},
	...
}

and ran into issues with html being escaped, such as bold text or multiline.
I figured out I gotta use <RichText.Content> so I did.

{
	attributes: {
		content: {
			type: 'array',
		},
	},
	edit: ({attributes, setAttributes}) => {
		return (
			<div className='custom-block'>
				<wp.editor.RichText
					value={attributes.content}
					onChange={value => setAttributes({content: value})}
				/>
			</div>
		)
	},
	save: ({attributes}) => {
		return (
			<div className='custom-block'>
				<wp.editor.RichText.Content value={attributes.content} />
			</div>
		)
	},
}

Then I have a block that is basically a preset of blocks, so it looked something like this:

{
	attributes: {},
	edit: ({attributes, setAttributes}) => {
		return (
			<div className='my-other-block'>
				<wp.editor.InnerBlocks
					template={[
						['custom/block', {
							content: ['Content'],
						}],
					]}
				/>
			</div>
		)
	},
	save: ({attributes}) => {
		return (
			<div className='my-other-block'>
				<wp.editor.InnerBlocks.Content />
			</div>
		)
	},
}

Notice the content in the template is type array, the old format, but the block earlier used string value now. It will render the InnerBlocks fine when you insert the block, but after refresh the content attribute is gone from the custom/block block comments and I get an error (~The block has been modified externally).

So to solve that I removed the type from custom/block:

{
	attributes: {
		content: {},
	},
	...
}

Now it works. It can use string from <RichText> and array from old templates. That's how I reconciled 4.0.

I'm not saying anything is bugged, this is just how it went down for me.

Now I'm just wondering:

  1. Is it correct to have no type for the attribute?

  2. Do I keep the old array templates (of which I have about 20 different ones, 1200 lines)? Or do I need to convert them to string format.

  3. And if so, how does bold and <br> etc look like in the new string format? Are there examples?

@youknowriad
Copy link
Contributor

Is it correct to have no type for the attribute?

It's correct but I expect the first issue is that the block was initially doing something wrong: You're rendering the content in html and at the same time saving it to the block's wrapping comment (because there's no source).

You could try adding source: "children", selector: ".custom-block" to the attribute's definition.

@ktmn
Copy link

ktmn commented Oct 20, 2018

You're rendering the content in html and at the same time saving it to the block's wrapping comment (because there's no source).

You could try adding source: "children", selector: ".custom-block" to the attribute's definition.

I do that because the selectors are not capable handling more complex blocks.

For example if I have a button:

<div class="button">
    Content
</div>

it can work easily with this attribute:

{
    content: {
        source: 'html', // not 'children' anymore, right?
        selector: '.button',
    },
}

but when there's a block control that allows to add an icon for example, making the output like this:

<div class="button">
    Content
    <i class="icon banana"></i>
</div>

I can no longer fetch only the content without having to wrap it first in a span or something.

Now maybe the button also has a toggle control allowing the button to only show the icon, resulting in this render:

<div class="button">
    <i class="icon banana"></i>
</div>

then the content would be gone, even if the user just tried to test what this option looks like.

Of course I use the source when possible but most of the time I need to keep the value in the comments. I really hope that's supported, I mean it has been working fine always.

For string rich text <em> is stored in the comments like this \u003cem\u003Content\u003c/em\u003e and it works fine, but if I put this string in a template it doesn't. So how would I do this in templates?

@youknowriad
Copy link
Contributor

youknowriad commented Oct 20, 2018

Gotcha, thanks for the explanation. There's something we need to check separately. An issue with this block would be good to check why the template is not working.

{
	attributes: {
		content: {
			type: 'array',
		},
	},
	edit: ({attributes, setAttributes}) => {
		return (
			<div className='custom-block'>
				<wp.editor.RichText
					value={attributes.content}
					onChange={value => setAttributes({content: value})}
				/>
			</div>
		)
	},
	save: ({attributes}) => {
		return (
			<div className='custom-block'>
				{attributes.content}
			</div>
		)
	},
}

Separately, I'd advocate to transform everything into string including the template content.

mkaz added a commit to WordPress/gutenberg-examples that referenced this pull request Oct 21, 2021
In the attributes, The source of `children` is no longer supported and should be
changed to `html` along with the type changing to `string`.

See PR comment here:
WordPress/gutenberg#10439 (comment)
mkaz added a commit to WordPress/gutenberg-examples that referenced this pull request Oct 21, 2021
* Add the block.json schema to each block.json file

Added schea defintion to each file, this allows validation and auto
complete in supported browers.

	"$schema": "https://json.schemastore.org/block.json"

Required fixing the textDomain => textdomain

Highlighted an issue with `source: children` not documented.

* Switch type/source to string/children

In the attributes, The source of `children` is no longer supported and should be
changed to `html` along with the type changing to `string`.

See PR comment here:
WordPress/gutenberg#10439 (comment)
goldentroll added a commit to goldentroll/gutenberg-examples that referenced this pull request Mar 13, 2023
* Add the block.json schema to each block.json file

Added schea defintion to each file, this allows validation and auto
complete in supported browers.

	"$schema": "https://json.schemastore.org/block.json"

Required fixing the textDomain => textdomain

Highlighted an issue with `source: children` not documented.

* Switch type/source to string/children

In the attributes, The source of `children` is no longer supported and should be
changed to `html` along with the type changing to `string`.

See PR comment here:
WordPress/gutenberg#10439 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Rich Text Related to the Rich Text component that allows developers to render a contenteditable
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants