diff --git a/package.json b/package.json
index 7e9aa1e..fe1c6d6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "draft-js-markdown-plugin",
-  "version": "2.1.1",
+  "version": "3.0.0",
   "description": "A DraftJS plugin for supporting Markdown syntax shortcuts, fork of draft-js-markdown-shortcuts-plugin",
   "main": "lib/index.js",
   "scripts": {
diff --git a/src/__test__/plugin.test.js b/src/__test__/plugin.test.js
index 22f7dc9..a8c6388 100755
--- a/src/__test__/plugin.test.js
+++ b/src/__test__/plugin.test.js
@@ -542,7 +542,8 @@ describe("draft-js-markdown-plugin", () => {
               expect(modifierSpy).toHaveBeenCalledWith(
                 defaultInlineWhitelist,
                 currentEditorState,
-                " "
+                " ",
+                undefined
               );
             });
             it("unstickys inline style", () => {
@@ -660,115 +661,6 @@ describe("draft-js-markdown-plugin", () => {
           expect(store.setEditorState).toHaveBeenCalledWith(newEditorState);
         });
       });
-      describe("handlePastedText", () => {
-        let pastedText;
-        let html;
-        beforeEach(() => {
-          pastedText = `_hello world_
-          Hello`;
-          html = undefined;
-          subject = () =>
-            plugin.handlePastedText(
-              pastedText,
-              html,
-              store.getEditorState(),
-              store
-            );
-        });
-        [
-          "replaceText",
-          // TODO(@mxstbr): This broke when switching mocha->jest, fix it!
-          // 'insertEmptyBlock',
-          "handleBlockType",
-          "handleImage",
-          "handleLink",
-          "handleInlineStyle",
-        ].forEach(modifier => {
-          describe(modifier, () => {
-            beforeEach(() => {
-              createMarkdownPlugin.__Rewire__(modifier, modifierSpy); // eslint-disable-line no-underscore-dangle
-            });
-            it("returns handled", () => {
-              expect(subject()).toBe("handled");
-              expect(modifierSpy).toHaveBeenCalled();
-            });
-          });
-        });
-        describe("nothing in clipboard", () => {
-          beforeEach(() => {
-            pastedText = "";
-          });
-          it("returns not-handled", () => {
-            expect(subject()).toBe("not-handled");
-          });
-        });
-        describe("pasted just text", () => {
-          beforeEach(() => {
-            pastedText = "hello";
-            createMarkdownPlugin.__Rewire__("replaceText", modifierSpy); // eslint-disable-line no-underscore-dangle
-          });
-          it("returns handled", () => {
-            expect(subject()).toBe("handled");
-            expect(modifierSpy).toHaveBeenCalledWith(
-              currentEditorState,
-              "hello"
-            );
-          });
-        });
-        describe("pasted just text with new line code", () => {
-          beforeEach(() => {
-            pastedText = "hello\nworld";
-            const rawContentState = {
-              entityMap: {},
-              blocks: [
-                {
-                  key: "item1",
-                  text: "",
-                  type: "unstyled",
-                  depth: 0,
-                  inlineStyleRanges: [],
-                  entityRanges: [],
-                  data: {},
-                },
-              ],
-            };
-            const otherRawContentState = {
-              entityMap: {},
-              blocks: [
-                {
-                  key: "item2",
-                  text: "H1",
-                  type: "header-one",
-                  depth: 0,
-                  inlineStyleRanges: [],
-                  entityRanges: [],
-                  data: {},
-                },
-              ],
-            };
-            /* eslint-disable no-underscore-dangle */
-            createMarkdownPlugin.__Rewire__("replaceText", () =>
-              createEditorState(rawContentState, currentSelectionState)
-            );
-            createMarkdownPlugin.__Rewire__("checkReturnForState", () =>
-              createEditorState(otherRawContentState, currentSelectionState)
-            );
-            /* eslint-enable no-underscore-dangle */
-          });
-          it("return handled", () => {
-            expect(subject()).toBe("handled");
-          });
-        });
-        describe("passed `html` argument", () => {
-          beforeEach(() => {
-            pastedText = "# hello";
-            html = "<h1>hello</h1>";
-          });
-          it("returns not-handled", () => {
-            expect(subject()).toBe("not-handled");
-          });
-        });
-      });
     });
   });
 });
diff --git a/src/index.js b/src/index.js
index f824b5e..ba85f2e 100755
--- a/src/index.js
+++ b/src/index.js
@@ -131,7 +131,8 @@ function checkCharacterForState(config, editorState, character) {
     newEditorState = handleInlineStyle(
       config.features.inline,
       editorState,
-      character
+      character,
+      config.customInlineMatchers
     );
   }
   return newEditorState;
@@ -415,64 +416,6 @@ const createMarkdownPlugin = (_config = {}) => {
         }
       }
     },
-    handlePastedText(text, html, editorState, { setEditorState }) {
-      let newEditorState = editorState;
-      let buffer = [];
-
-      if (html) {
-        return "not-handled";
-      }
-
-      // If we're in a code block don't add markdown to it
-      if (inCodeBlock(editorState)) {
-        setEditorState(insertText(editorState, text));
-        return "handled";
-      }
-
-      for (let i = 0; i < text.length; i++) {
-        // eslint-disable-line no-plusplus
-        if (INLINE_STYLE_CHARACTERS.indexOf(text[i]) >= 0) {
-          newEditorState = replaceText(
-            newEditorState,
-            buffer.join("") + text[i]
-          );
-          newEditorState = checkCharacterForState(
-            config,
-            newEditorState,
-            text[i]
-          );
-          buffer = [];
-        } else if (text[i].charCodeAt(0) === 10) {
-          newEditorState = replaceText(newEditorState, buffer.join(""));
-          const tmpEditorState = checkReturnForState(
-            config,
-            newEditorState,
-            {}
-          );
-          if (newEditorState === tmpEditorState) {
-            newEditorState = insertEmptyBlock(tmpEditorState);
-          } else {
-            newEditorState = tmpEditorState;
-          }
-          buffer = [];
-        } else if (i === text.length - 1) {
-          newEditorState = replaceText(
-            newEditorState,
-            buffer.join("") + text[i]
-          );
-          buffer = [];
-        } else {
-          buffer.push(text[i]);
-        }
-      }
-
-      if (editorState !== newEditorState) {
-        setEditorState(newEditorState);
-        return "handled";
-      }
-
-      return "not-handled";
-    },
   };
 };
 
diff --git a/src/modifiers/__test__/changeCurrentInlineStyle-test.js b/src/modifiers/__test__/changeCurrentInlineStyle-test.js
index 7f45d70..8424e68 100644
--- a/src/modifiers/__test__/changeCurrentInlineStyle-test.js
+++ b/src/modifiers/__test__/changeCurrentInlineStyle-test.js
@@ -43,6 +43,51 @@ describe("changeCurrentInlineStyle", () => {
       "CODE"
     );
     expect(newEditorState).not.toEqual(editorState);
+    expect(Draft.convertToRaw(newEditorState.getCurrentContent())).toEqual(
+      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" },
+      ])
+    );
+  });
+  it("handles a style terminator properly", () => {
+    const text = "foo **bar** baz";
+    const editorState = createEditorState(text, []);
+    const matchArr = ["**bar** ", "bar", " "];
+    matchArr.index = 4;
+    matchArr.input = text;
+    const newEditorState = changeCurrentInlineStyle(
+      editorState,
+      matchArr,
+      "BOLD"
+    );
+    expect(newEditorState).not.toEqual(editorState);
     expect(Draft.convertToRaw(newEditorState.getCurrentContent())).toEqual(
       rawContentState(
         "foo bar baz",
@@ -50,10 +95,10 @@ describe("changeCurrentInlineStyle", () => {
           {
             length: 3,
             offset: 4,
-            style: "CODE",
+            style: "BOLD",
           },
         ],
-        "CODE"
+        "BOLD"
       )
     );
   });
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,
diff --git a/src/modifiers/changeCurrentInlineStyle.js b/src/modifiers/changeCurrentInlineStyle.js
index c611c76..e76215f 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,16 +22,32 @@ const changeCurrentInlineStyle = (editorState, matchArr, style) => {
     focusOffset,
   });
 
-  const inlineStyles = [];
-  const markdownCharacterLength = (matchArr[0].length - matchArr[1].length) / 2;
+  let newEditorState = editorState;
 
-  let newContentState = currentContent;
+  // remove all styles if applying code style
+  if (style === "CODE") {
+    newEditorState = removeInlineStyles(newEditorState, wordSelection);
+  }
+
+  let newContentState = newEditorState.getCurrentContent();
+
+  // check if match contains a terminator group at the end
+  let matchTerminatorLength = 0;
+  if (matchArr.length == 3) {
+    matchTerminatorLength = matchArr[2].length;
+  }
+
+  const markdownCharacterLength =
+    (matchArr[0].length - matchArr[1].length - matchTerminatorLength) / 2;
 
   // remove markdown delimiter at end
   newContentState = Modifier.removeRange(
     newContentState,
     wordSelection.merge({
-      anchorOffset: wordSelection.getFocusOffset() - markdownCharacterLength,
+      anchorOffset:
+        wordSelection.getFocusOffset() -
+        markdownCharacterLength -
+        matchTerminatorLength,
     })
   );
 
@@ -50,12 +71,23 @@ const changeCurrentInlineStyle = (editorState, matchArr, style) => {
     newContentState,
     wordSelection.merge({
       anchorOffset: index,
-      focusOffset: focusOffset - markdownCharacterLength * 2,
+      focusOffset:
+        focusOffset - markdownCharacterLength * 2 - matchTerminatorLength,
     }),
     style
   );
 
-  const newEditorState = EditorState.push(
+  // Check if a terminator exists and re-add it after the styled text
+  if (matchTerminatorLength > 0) {
+    newContentState = Modifier.insertText(
+      newContentState,
+      afterSelection,
+      matchArr[2]
+    );
+    afterSelection = newContentState.getSelectionAfter();
+  }
+
+  newEditorState = EditorState.push(
     editorState,
     newContentState,
     "change-inline-style"
diff --git a/src/modifiers/handleInlineStyle.js b/src/modifiers/handleInlineStyle.js
index f494425..bead9e6 100644
--- a/src/modifiers/handleInlineStyle.js
+++ b/src/modifiers/handleInlineStyle.js
@@ -4,12 +4,14 @@ import { inlineMatchers } from "../constants";
 import insertText from "./insertText";
 import { getCurrentLine as getLine } from "../utils";
 
-const handleChange = (editorState, line, whitelist) => {
+const handleChange = (editorState, line, whitelist, customInlineMatchers) => {
   let newEditorState = editorState;
-  Object.keys(inlineMatchers)
+  const matchers = Object.assign({}, inlineMatchers, customInlineMatchers);
+
+  Object.keys(matchers)
     .filter(matcher => whitelist.includes(matcher))
     .some(k => {
-      inlineMatchers[k].some(re => {
+      matchers[k].some(re => {
         let matchArr;
         do {
           matchArr = re.exec(line);
@@ -31,19 +33,30 @@ const handleChange = (editorState, line, whitelist) => {
 const handleInlineStyle = (
   whitelist,
   editorStateWithoutCharacter,
-  character
+  character,
+  customInlineMatchers = {}
 ) => {
   const editorState = insertText(editorStateWithoutCharacter, character);
   let selection = editorState.getSelection();
   let line = getLine(editorState);
-  let newEditorState = handleChange(editorState, line, whitelist);
+  let newEditorState = handleChange(
+    editorState,
+    line,
+    whitelist,
+    customInlineMatchers
+  );
   let lastEditorState = editorState;
 
   // Recursively resolve markdown, e.g. _*text*_ should turn into both italic and bold
   while (newEditorState !== lastEditorState) {
     lastEditorState = newEditorState;
     line = getLine(newEditorState);
-    newEditorState = handleChange(newEditorState, line, whitelist);
+    newEditorState = handleChange(
+      newEditorState,
+      line,
+      whitelist,
+      customInlineMatchers
+    );
   }
 
   if (newEditorState !== editorState) {
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);
+};