Repository: withspectrum/draft-js-markdown-plugin
Pull request #83 (2018-05-24 07:57:41)

Unsticky inline styles
This "unstickies" inline styles, so that when you type *bold* text, backspace to the ending edge of the bold text and start typing again the bold doesn't "stick" to the text, only when typing within it. This feels much better than before.

Recorded demo: ![](https://i.imgur.com/gWSLp06.gif)
Live demo: https://public-mffnxzocik.now.sh

/cc @brianlovin @wmertens this should be a fix for the issues you were having!


Patch:
diff --git a/src/index.js b/src/index.js
index 60cd795..29825b2 100755
--- a/src/index.js
+++ b/src/index.js
@@ -202,6 +202,27 @@ function checkReturnForState(config, editorState, ev) {
   return newEditorState;
 }
 
+const unstickyInlineStyles = (character, editorState) => {
+  const selection = editorState.getSelection();
+  if (!selection.isCollapsed()) return editorState;
+
+  const startOffset = selection.getStartOffset();
+  const content = editorState.getCurrentContent();
+  const block = content.getBlockForKey(selection.getStartKey());
+  const entity = block.getEntityAt(startOffset - 1);
+  if (entity !== null) return editorState;
+
+  // If we're currently in a style, but the next character doesn't have a style (or doesn't exist)
+  // we insert the characters manually without the inline style to "unsticky" them
+  const style = block.getInlineStyleAt(startOffset - 1);
+  if (style.size === 0) return editorState;
+  const nextStyle = block.getInlineStyleAt(startOffset);
+  if (nextStyle.size !== 0) return editorState;
+
+  const newContent = Modifier.insertText(content, selection, character);
+  return EditorState.push(editorState, newContent, "insert-characters");
+};
+
 const defaultConfig = {
   renderLanguageSelect: defaultRenderSelect,
   languages: defaultLanguages,
@@ -347,6 +368,12 @@ const createMarkdownPlugin = (_config = {}) => {
       // If we're in a link - don't transform markdown
       if (inLink(editorState)) return "not-handled";
 
+      const unsticky = unstickyInlineStyles(character, editorState);
+      if (editorState !== unsticky) {
+        setEditorState(unsticky);
+        return "handled";
+      }
+
       const newEditorState = checkCharacterForState(
         config,
         editorState,


Test patch:
diff --git a/src/__test__/plugin.test.js b/src/__test__/plugin.test.js
index 7b805d0..22f7dc9 100755
--- a/src/__test__/plugin.test.js
+++ b/src/__test__/plugin.test.js
@@ -180,7 +180,7 @@ describe("draft-js-markdown-plugin", () => {
           expect(subject()).toBe("not-handled");
         });
 
-        it("resets curent inline style", () => {
+        it("resets current inline style", () => {
           currentRawContentState = {
             entityMap: {},
             blocks: [
@@ -545,6 +545,39 @@ describe("draft-js-markdown-plugin", () => {
                 " "
               );
             });
+            it("unstickys inline style", () => {
+              currentRawContentState = {
+                entityMap: {},
+                blocks: [
+                  {
+                    key: "item1",
+                    text: "item1",
+                    type: "unstyled",
+                    depth: 0,
+                    inlineStyleRanges: [
+                      { offset: 0, length: 5, style: "BOLD" },
+                    ],
+                    entityRanges: [],
+                    data: {},
+                  },
+                ],
+              };
+
+              currentSelectionState = currentSelectionState.merge({
+                focusOffset: 5,
+                anchorOffset: 5,
+              });
+
+              expect(subject()).toBe("handled");
+              expect(store.setEditorState).toHaveBeenCalled();
+              newEditorState = store.setEditorState.mock.calls[0][0];
+              const block = newEditorState.getCurrentContent().getLastBlock();
+              const length = block.getLength();
+              expect(block.getInlineStyleAt(length - 1).toJS()).toEqual([]);
+              expect(block.getInlineStyleAt(length - 2).toJS()).toEqual([
+                "BOLD",
+              ]);
+            });
           });
         });
         describe("character is not a space", () => {