Right now, it seems like code blocks are handled by creating a new "block" for each line of code, instead of keeping all of the code text inside a single block. Which means that it is impossible to have two code adjacent code blocks, since they will be rendered as one.
For example, imagine wanting to have a block of javascript followed immediately by a block of css, with no extra paragraphs or lines in between:

The demo gets around this because it uses "unstyled" lines, so the workaround is to just chuck an extra unstyled line between them. But as soon as you try to do the same with paragraphs, you end up with an entire paragraph between them, instead of two blocks of code.
In other words, this output is impossible:
<p>...</p>
<p>...</p>
<pre><code>...</code></pre>
<pre><code>...</code></pre>
<p>...</p>
Because you'd instead have to do this:
<p>...</p>
<p>...</p>
<pre><code>...</code></pre>
<p></p>
<pre><code>...</code></pre>
<p>...</p>
This weirdness comes up in other places, where if you're trying to serialize code blocks, you need to make sure that you continue as long as the i+1 block is also a code block. And it also comes up when trying to attach "syntax" data to a block, since you actually need to loop and attach it to all blocks that are next to each other.
Rendering wise, to get around it feeling like each line is a block, a separate wrapper <pre> tag is rendered with a .public-DraftStyleDefault-pre class. But this is kind of just patching over the problem.
It seems like code blocks should be handled as first-class, where lines are separated by \n instead of by creating separate blocks. Otherwise, the leaky abstraction ends up being a problem in lots of different places throughout the codebase.
@ianstormtaylor Does this plugin help achieve your desired behavior? https://github.com/icelab/draft-js-block-breakout-plugin
@oyeanuj I don't think so, but could be missing something there. I think even with the breakout, the limitation on adjacent code-block blocks is hardcoded in Draft core.
Although, unrelated, that plugin is sweet, I'd implemented it internally for other use cases and will switch over to it. So, thanks!
Is the limitation really that you can't combine two adjacent blocks, or that when you are editing within a block pressing the 'enter' key will split the block into two, instead of just adding a newline? I wonder if that's possible to customize in the keybindings.
On a completely side note, @ianstormtaylor, your editor looks great. I'd really like to take a look at it if it's open source.
Thanks @so4pmaker! That editor itself isn't open source, nope, but I am working on Slate to make arriving at something similar to it super easy. But not that exact one 😄
Just read through the _why?_ of stale. First class plugins is very
lucrative I must say.
On Thursday, July 28, 2016, Ian Storm Taylor [email protected]
wrote:
Thanks @so4pmaker https://github.com/so4pmaker! That editor itself
isn't open source, nope, but I am working on Slate
https://github.com/ianstormtaylor/slate to make arriving at something
similar to it super easy. But not that exact one 😄—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/facebook/draft-js/issues/452#issuecomment-235724230,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AC2W89mvFxC1kyVSiALkJ9DDeYQcTjcHks5qZ8sqgaJpZM4IxX0t
.
@ianstormtaylor did you ever find a work around for this?
@ap190 nope, I switching to using Slate.
I found a work around ,just use keyBindingFn;
Talk is cheap.Here is my code ,using draft-js-plugin:
import { getDefaultKeyBinding, Modifier, EditorState } from 'draft-js';
import { getCurrentBlock } from '../utils';
export default (store) => {
return {
keyBindingFn: (e, { getEditorState, setEditorState }) => {
const editorState = getEditorState();
const { block } = getCurrentBlock(editorState);
if (e.keyCode === 13 && block.getType() === 'code-block') {
const newContentState = Modifier.insertText(editorState.getCurrentContent(), editorState.getSelection(), '\n');
const newEditorState = EditorState.push(editorState, newContentState, "insert-characters");
setEditorState(newEditorState);
return 'add-newline';
}
return getDefaultKeyBinding(e);
},
};
};
And outside, the handleKeyCommand:
handleKeyCommand = (command, editorState) => {
console.log(command);
//这里对code-block回撤之后多出来一个block进行work-around
if (command === 'add-newline') {
return 'handled';
}
const newState = RichUtils.handleKeyCommand(editorState, command);
if (newState) {
this.onChange(newState);
return true;
}
return false;
}
@joshmarinacci That's a good idea.Thank you.
Most helpful comment
I found a work around ,just use keyBindingFn;
Talk is cheap.Here is my code ,using draft-js-plugin:
And outside, the handleKeyCommand: