Repository: withspectrum/draft-js-markdown-plugin
Pull request #97 (2018-06-25 12:59:14)

remove styles and links inside inline code block
fixes for https://github.com/withspectrum/draft-js-markdown-plugin/issues/96


Patch:
diff --git a/src/modifiers/changeCurrentInlineStyle.js b/src/modifiers/changeCurrentInlineStyle.js
index c611c76..3ecdbdf 100644
--- a/src/modifiers/changeCurrentInlineStyle.js
+++ b/src/modifiers/changeCurrentInlineStyle.js
@@ -1,5 +1,6 @@
 import { OrderedSet } from "immutable";
 import { EditorState, SelectionState, Modifier } from "draft-js";
+import removeInlineStyles from "./removeInlineStyles";
 
 const changeCurrentInlineStyle = (editorState, matchArr, style) => {
   const currentContent = editorState.getCurrentContent();
@@ -8,8 +9,12 @@ const changeCurrentInlineStyle = (editorState, matchArr, style) => {
   const { index } = matchArr;
   const blockMap = currentContent.getBlockMap();
   const block = blockMap.get(key);
-  const currentInlineStyle = block.getInlineStyleAt(index).merge();
-  const newStyle = currentInlineStyle.merge([style]);
+  const currentInlineStyle = block.getInlineStyleAt(index);
+  // do not modify the text if it is inside code style
+  const hasCodeStyle = currentInlineStyle.find(style => style === "CODE");
+  if (hasCodeStyle) {
+    return editorState;
+  }
   const focusOffset = index + matchArr[0].length;
 
   const wordSelection = SelectionState.createEmpty(key).merge({
@@ -17,10 +22,15 @@ const changeCurrentInlineStyle = (editorState, matchArr, style) => {
     focusOffset,
   });
 
-  const inlineStyles = [];
+  let newEditorState = editorState;
+  // remove all styles if applying code style
+  if (style === "CODE") {
+    newEditorState = removeInlineStyles(newEditorState, wordSelection);
+  }
+
   const markdownCharacterLength = (matchArr[0].length - matchArr[1].length) / 2;
 
-  let newContentState = currentContent;
+  let newContentState = newEditorState.getCurrentContent();
 
   // remove markdown delimiter at end
   newContentState = Modifier.removeRange(
@@ -55,7 +65,7 @@ const changeCurrentInlineStyle = (editorState, matchArr, style) => {
     style
   );
 
-  const newEditorState = EditorState.push(
+  newEditorState = EditorState.push(
     editorState,
     newContentState,
     "change-inline-style"
diff --git a/src/modifiers/removeInlineStyles.js b/src/modifiers/removeInlineStyles.js
new file mode 100644
index 0000000..6d70038
--- /dev/null
+++ b/src/modifiers/removeInlineStyles.js
@@ -0,0 +1,17 @@
+import { EditorState, RichUtils, Modifier } from "draft-js";
+
+export default (editorState, selection = editorState.getSelection()) => {
+  const styles = ["BOLD", "ITALIC", "STRIKETHROUGH", "CODE"];
+
+  let newEditorState = EditorState.push(
+    editorState,
+    styles.reduce(
+      (newContentState, style) =>
+        Modifier.removeInlineStyle(newContentState, selection, style),
+      editorState.getCurrentContent()
+    ),
+    "change-inline-style"
+  );
+
+  return RichUtils.toggleLink(newEditorState, selection, null);
+};


Test patch:
diff --git a/src/modifiers/__test__/changeCurrentInlineStyle-test.js b/src/modifiers/__test__/changeCurrentInlineStyle-test.js
index 7f45d70..d60a21b 100644
--- a/src/modifiers/__test__/changeCurrentInlineStyle-test.js
+++ b/src/modifiers/__test__/changeCurrentInlineStyle-test.js
@@ -44,17 +44,36 @@ describe("changeCurrentInlineStyle", () => {
     );
     expect(newEditorState).not.toEqual(editorState);
     expect(Draft.convertToRaw(newEditorState.getCurrentContent())).toEqual(
-      rawContentState(
-        "foo bar baz",
-        [
-          {
-            length: 3,
-            offset: 4,
-            style: "CODE",
-          },
-        ],
-        "CODE"
-      )
+      rawContentState("foo bar baz", [
+        {
+          length: 3,
+          offset: 4,
+          style: "CODE",
+        },
+      ])
+    );
+  });
+  it("removes inline styles when applying code style", () => {
+    const text = "`some bold text`";
+    const editorState = createEditorState(text, [
+      {
+        length: 4,
+        offset: 6,
+        style: "BOLD",
+      },
+    ]);
+    const matchArr = ["`some bold text`", "some bold text"];
+    matchArr.index = 0;
+    matchArr.input = text;
+    let newEditorState = changeCurrentInlineStyle(
+      editorState,
+      matchArr,
+      "CODE"
+    );
+    expect(Draft.convertToRaw(newEditorState.getCurrentContent())).toEqual(
+      rawContentState("some bold text", [
+        { length: 14, offset: 0, style: "CODE" },
+      ])
     );
   });
 });
diff --git a/src/modifiers/__test__/handleInlineStyle-test.js b/src/modifiers/__test__/handleInlineStyle-test.js
index a4f3bcd..a04fce9 100644
--- a/src/modifiers/__test__/handleInlineStyle-test.js
+++ b/src/modifiers/__test__/handleInlineStyle-test.js
@@ -47,14 +47,14 @@ describe("handleInlineStyle", () => {
   });
 
   const testCases = {
-    "converts a mix of code, bold and italic and strikethrough in one go": {
-      character: "`",
+    "converts a mix of bold and italic and strikethrough in one go": {
+      character: "*",
       before: {
         entityMap: {},
         blocks: [
           {
             key: "item1",
-            text: "`h~el*lo _inline~_* style",
+            text: "*h~ello _inline~_ style",
             type: "unstyled",
             depth: 0,
             inlineStyleRanges: [],
@@ -72,32 +72,55 @@ describe("handleInlineStyle", () => {
             type: "unstyled",
             depth: 0,
             inlineStyleRanges: [
-              {
-                length: 12,
-                offset: 0,
-                style: "CODE",
-              },
-              {
-                length: 11,
-                offset: 1,
-                style: "STRIKETHROUGH",
-              },
-              {
-                length: 9,
-                offset: 3,
-                style: "BOLD",
-              },
-              {
-                length: 6,
-                offset: 6,
-                style: "ITALIC",
-              },
+              { length: 12, offset: 0, style: "BOLD" },
+              { length: 11, offset: 1, style: "STRIKETHROUGH" },
+              { length: 6, offset: 6, style: "ITALIC" },
             ],
             entityRanges: [],
             data: {},
           },
         ],
       },
+      selection: new SelectionState({
+        anchorKey: "item1",
+        anchorOffset: 17,
+        focusKey: "item1",
+        focusOffset: 17,
+        isBackward: false,
+        hasFocus: true,
+      }),
+    },
+
+    "should not covert inside the code style": {
+      character: "`",
+      before: {
+        entityMap: {},
+        blocks: [
+          {
+            key: "item1",
+            text: "`h~el*lo _inline~_* style",
+            type: "unstyled",
+            depth: 0,
+            inlineStyleRanges: [],
+            entityRanges: [],
+            data: {},
+          },
+        ],
+      },
+      after: {
+        entityMap: {},
+        blocks: [
+          {
+            key: "item1",
+            text: "h~el*lo _inline~_* style",
+            type: "unstyled",
+            depth: 0,
+            inlineStyleRanges: [{ length: 18, offset: 0, style: "CODE" }],
+            entityRanges: [],
+            data: {},
+          },
+        ],
+      },
       selection: new SelectionState({
         anchorKey: "item1",
         anchorOffset: 19,