-
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
Adding a controlled editor using the grammar parser #113
Conversation
Where are these controls defined? I see the benefit being that it's easy to reuse controls between blocks, but we should also make it easy to create new controls as well.
Similarly, how does one control the behavior for switching between block types? There'd been some discussion previously about whether a block should define what it can turn into vs. what it can be initialized from, or whether a block must be able to convert itself back to a basic text form from which any block can be initialized, etc. etc.
Should a block be expected to provide icon markup? What if multiple blocks use the same icon (avoid duplicate markup)? What if a block implementer wants to leverage a standard icon, and we need to update that standard icon over time? |
Cross-linking #104 for API explorations here. |
Yeah the API is not the main point of this prototype, I wanted to test/validate the principles (controlled, grammar, state, a contenteditable wrapper).
For now the controls are defined on the global config variable gutenberg/controlled-grammar-editor/main.js Lines 11 to 48 in 76a62ac
Right! for now this prototype does not answer this question, the switch prototype is only used to show the switch UI. But I imagine adding a
This is temporary due to the lack of build etc... it was just handy for now, we probably should use "classnames" or an "iconID" (Gridicons or Dashicons) |
The UI Prototype is starting to get strong enough, I thought it was time to tackle some technical aspects and try to tie the moving pieces together. So, I'm sharing this prototype (buggy?) with the following characteristics:
First and probably the most important property, is that it's a "controlled" editor which means it has a global state object, containing all the data needed to display the editor. the UI is a projection of this state.
It also uses the WP Post Grammar parser, to parse the initial data from a string and store it as the initial state. (I intentionally limited the parsing to the first level, no nested blocks yet)
Not yet implemented but easy enough, writing a serializer that takes the blocks stored in the global state and generate the new
string
to be stored as post contentIt has most of the UI present in the UI prototype. I can take this further to match the UI Prototype, but sharing the prototype sooner seemed a good idea before going further.
This prototype also borrows some ideas from @aduth prototype here to allow multi-block selection.
Notice the
render*
functions. These functions can easily be switched to use @aduth wpBlocks, preact, react or similar, I avoided libraries intentionally.The hardest issues
I said earlier that it may be a bit buggy, because one difficult task to achieve when dealing with contenteditable on a controlled editor is how to save and update the caret position and the selected text. In this early prototype I'm using the rangy lib to save/restore the position between two renders. Not a perfect solution, but a temporary one.
Another tricky part, is how to catch changes on the contenteditable blocks and save them on the state. My solution to this is having a
update
function as part of the block API, each type of block takes the previous saved block, the current contenteditable dom element corresponding to this block and should save these updates and generate a new block object to save in state.Block API
So for this prototype, the block API for now is something like :