-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Editable: state as a cleaned up tree #3048
Conversation
6f18bbd
to
e6ffd52
Compare
While quickly putting this alternative together, I used dom-react to loop through the nodes. I wonder if we want to keep this though. The most important thing it does is mapping attributes to React canonical ones and parse the style attribute to JSON. If we don't mind attributes with dashes in the state... we could loop ourselves and drop this. With React 16, it seems still recommended to use the canonical attributes, so then we would need to map from state to React, instead of dom to React. |
blocks/editable/test/index.js
Outdated
} ); | ||
|
||
it( 'should render null when false passed as value', () => { | ||
const wrapper = shallow( <Editable.Value value={ [ false ] } /> ); |
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.
Is this needed? Not sure how that could happen.
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.
(Same for the above.)
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.
We can drop it, I just wanted to track down why this fails in test env.
It turns out we are using React 15 and this break most of the code used. I will look into an upgrade to React 16 tomorrow to get rid of |
e6ffd52
to
14315b3
Compare
blocks/editable/index.js
Outdated
return createElement( type, { ...props, key: i }, valueToReact( children ) ); | ||
} ); | ||
|
||
// We are still using React 15, so can't return array or string directly... |
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.
Only in test environment are we using React 15.
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.
Hopefully not that long: #3079 :)
As soon as we land React upgrade for tests (#3079) I will update PR to stop using hacky |
14315b3
to
eebaeca
Compare
I rebased with We have still 14 failing tests, but 12 of them are directly related to the different JSON representation of components. There are 2 tests failing that we still need to investigate:
|
eebaeca
to
0b5428f
Compare
blocks/api/test/source.js
Outdated
const match = parse( html, sources.node() ); | ||
|
||
expect( renderToString( match ) ).toBe( `<body>${ html }</body>` ); | ||
expect( renderToString( valueToElement( [ match ] ) ) ).toBe( `<body>${ html }</body>` ); |
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.
@iseulde this test is failing. I didn't find a way to fix it. There is some issue with the sources.node
parser. It inlines string nodes and nodes represented as an array. Once this is sorted out we should be good to do.
It also fails for this HTML fixture.
<blockquote class="wp-block-pullquote alignnone">
<p>Paragraph <strong>one</strong></p>
<p>Paragraph two</p>
<footer>by whomever</footer>
</blockquote>
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.
I think I fixed it :)
4cf568b
to
03c9bc0
Compare
blocks/library/table/index.js
Outdated
@@ -27,10 +28,29 @@ registerBlockType( 'core/table', { | |||
type: 'array', | |||
source: children( 'table' ), | |||
default: [ |
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.
We might want to keep what we had before and provide transformation layer instead. I wanted to make it work.
@iseulde @aduth @youknowriad - I manage to make it work with both the existing unit tests and the browser. There
|
blocks/api/source.js
Outdated
@@ -44,7 +43,7 @@ export const children = withKnownSourceFlag( ( selector ) => { | |||
} | |||
|
|||
if ( match ) { | |||
return nodeListToReact( match.childNodes || [], createElement ); | |||
return nodeListToReact( match.childNodes || [], toArray ); |
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.
I guess dom-react
should be something like dom-traverse
?
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.
Should I read it as we should introduce a facade for dom-react
? I think it would make a lot of sense.
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.
I guess
dom-react
should be something likedom-traverse
?
Yeah, this confused me as well, and I thought we were creating instances of React elements and then converting those into arrays. Understand better now, but the naming is a bit misleading. I also wonder how much of the React-isms we really need to be accounting for (e.g. key
) or if it's enough to pick attributes from node.attributes
(see 6521f06).
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.
Honestly I just did this to spin up a fast POC. Would prefer if we get rid of this too.
blocks/editable/index.js
Outdated
@@ -36,7 +36,7 @@ import { EVENTS } from './constants'; | |||
|
|||
const { BACKSPACE, DELETE, ENTER } = keycodes; | |||
|
|||
function createTinyMCEElement( type, props, ...children ) { | |||
function toArray( type, props, ...children ) { |
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.
Should we name it valueFromElement
(to be consistent with valueToElement
)?
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.
Good idea, I like your proposal :)
blocks/api/source.js
Outdated
@@ -58,6 +57,6 @@ export const node = withKnownSourceFlag( ( selector ) => { | |||
match = domNode.querySelector( selector ); | |||
} | |||
|
|||
return nodeToReact( match, createElement ); | |||
return flatten( nodeToReact( match, toArray ) ); |
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.
Why does this need to flatten?
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.
Yes, this one is tricky. I had to flatten it to mirror what is happening in the editor. Somehow it wraps with one additional array when you compare with what is passed to <Editable />
or <Editable.value />
. It was quite hard to find a setup where all moving parts are satisfied: <Editable />
, <Editable.value />
, pasting from other documents. It might be a better idea to wrap value with another array in Editable. I'm not sure what's better here.
525b9c4
to
107a6d9
Compare
107a6d9
to
e9b7111
Compare
const [ type, props, ...children ] = element; | ||
const reactProps = Object.keys( props ).reduce( ( accumulator, key ) => { | ||
const mapping = { | ||
class: 'className', |
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.
It looks like adding those 2 mappings is enough to satisfy React.
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.
Okey, style needs its own handling, because I see this: https://reactjs.org/docs/error-decoder.html?invariant=62&args[]=
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.
All keys must go camel case, too.
}; | ||
}, { key: i } ); | ||
|
||
return createElement( type, { ...reactProps }, ...valueToElement( children ) ); |
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.
It can be simply reactProps
:)
@@ -850,7 +882,7 @@ export default class Editable extends Component { | |||
getSettings={ this.getSettings } | |||
onSetup={ this.onSetup } | |||
style={ style } | |||
defaultValue={ value } | |||
defaultValue={ valueToElement( value ) } |
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.
Can we use applySimpleNodeList
in here, too?
@gziolo @iseulde How reasonable do you think (in parallel to the work here) to implement our own I'm finding we're repeatedly bumping up against issues with React's serialization, most recently summarized at #3353 (comment). |
@aduth But then we can't use React elements inside the save function? Or would it be mixed? |
Right, I would think still supporting React elements, but "turning off" some of the sanitization behaviors, and supporting other object shapes. |
Should we consider this now as succeeded by #4049? |
Yes, probably it makes the most sense. This one was very helpful in the context of exploring what we really need. We should focus on one approach and finally get it merged :D |
Closing for now in favour of #4049. |
Description
Tries to address #2750.
This branch was created as a proof of concept and alternative to #2786. Logging it as a PR, but it's still a work-in-progress.
The goal is to have the editable state as a true (simple arrays), a cleaned up version of the current state as a React tree.