diff --git a/app/assets/javascripts/content_editor/components/wrappers/reference_label.vue b/app/assets/javascripts/content_editor/components/wrappers/reference_label.vue
index 08efcd643679cfd07fed780f66c7cf26bb2cb229..c67e699cf954d5b73406c0a165dfd9893835468a 100644
--- a/app/assets/javascripts/content_editor/components/wrappers/reference_label.vue
+++ b/app/assets/javascripts/content_editor/components/wrappers/reference_label.vue
@@ -22,9 +22,10 @@ export default {
   },
   computed: {
     isScopedLabel() {
-      return isScopedLabel({ title: this.node.attrs.originalText });
+      return isScopedLabel({ title: this.node.attrs.originalText || this.node.attrs.text });
     },
   },
+  fallbackLabelBackgroundColor: '#ccc',
 };
 </script>
 <template>
@@ -32,7 +33,7 @@ export default {
     <gl-label
       size="sm"
       :scoped="isScopedLabel"
-      :background-color="node.attrs.color"
+      :background-color="node.attrs.color || $options.fallbackLabelBackgroundColor"
       :title="node.attrs.text"
       class="gl-pointer-events-none"
     />
diff --git a/app/assets/javascripts/content_editor/extensions/link.js b/app/assets/javascripts/content_editor/extensions/link.js
index b83814103d153398b8931d540f9050a3bc34a480..584e7b9e4f79a6f5cc26b690c78ce8d0e6378fea 100644
--- a/app/assets/javascripts/content_editor/extensions/link.js
+++ b/app/assets/javascripts/content_editor/extensions/link.js
@@ -40,7 +40,6 @@ export default Link.extend({
   },
   addAttributes() {
     return {
-      ...this.parent?.(),
       uploading: {
         default: false,
         renderHTML: ({ uploading }) => (uploading ? { class: 'with-attachment-icon' } : {}),
diff --git a/app/assets/javascripts/content_editor/extensions/paste_markdown.js b/app/assets/javascripts/content_editor/extensions/paste_markdown.js
index 82fa5ce6c1d9f0bb749da8bef447dc7df3340543..db13438de5e0d746564d41d5468c8ca1e2d4f1bd 100644
--- a/app/assets/javascripts/content_editor/extensions/paste_markdown.js
+++ b/app/assets/javascripts/content_editor/extensions/paste_markdown.js
@@ -1,5 +1,7 @@
+import OrderedMap from 'orderedmap';
 import { Extension } from '@tiptap/core';
 import { Plugin, PluginKey } from '@tiptap/pm/state';
+import { Schema, DOMParser as ProseMirrorDOMParser, DOMSerializer } from '@tiptap/pm/model';
 import { __ } from '~/locale';
 import { VARIANT_DANGER } from '~/alert';
 import createMarkdownDeserializer from '../services/gl_api_markdown_deserializer';
@@ -9,47 +11,55 @@ import Diagram from './diagram';
 import Frontmatter from './frontmatter';
 
 const TEXT_FORMAT = 'text/plain';
+const GFM_FORMAT = 'text/x-gfm';
 const HTML_FORMAT = 'text/html';
 const VS_CODE_FORMAT = 'vscode-editor-data';
 const CODE_BLOCK_NODE_TYPES = [CodeBlockHighlight.name, Diagram.name, Frontmatter.name];
 
+function parseHTML(schema, html) {
+  const parser = new DOMParser();
+  const startTag = '<body>';
+  const endTag = '</body>';
+  const { body } = parser.parseFromString(startTag + html + endTag, 'text/html');
+  return { document: ProseMirrorDOMParser.fromSchema(schema).parse(body) };
+}
+
 export default Extension.create({
   name: 'pasteMarkdown',
   priority: EXTENSION_PRIORITY_HIGHEST,
   addOptions() {
     return {
       renderMarkdown: null,
+      serializer: null,
     };
   },
   addCommands() {
     return {
-      pasteMarkdown: (markdown) => () => {
+      pasteContent: (content = '', processMarkdown = true) => async () => {
         const { editor, options } = this;
         const { renderMarkdown, eventHub } = options;
         const deserializer = createMarkdownDeserializer({ render: renderMarkdown });
 
-        deserializer
-          .deserialize({ schema: editor.schema, markdown })
+        const pasteSchemaSpec = { ...editor.schema.spec };
+        pasteSchemaSpec.marks = OrderedMap.from(pasteSchemaSpec.marks).remove('span');
+        pasteSchemaSpec.nodes = OrderedMap.from(pasteSchemaSpec.nodes).remove('div').remove('pre');
+        const schema = new Schema(pasteSchemaSpec);
+
+        const promise = processMarkdown
+          ? deserializer.deserialize({ schema, markdown: content })
+          : Promise.resolve(parseHTML(schema, content));
+
+        promise
           .then(({ document }) => {
-            if (!document) {
-              return;
-            }
+            if (!document) return;
 
-            const { state, view } = editor;
-            const { tr, selection } = state;
             const { firstChild } = document.content;
-            const content =
+            const toPaste =
               document.content.childCount === 1 && firstChild.type.name === 'paragraph'
                 ? firstChild.content
                 : document.content;
 
-            if (selection.to - selection.from > 0) {
-              tr.replaceWith(selection.from, selection.to, content);
-            } else {
-              tr.insert(selection.from, content);
-            }
-
-            view.dispatch(tr);
+            editor.commands.insertContent(toPaste.toJSON());
           })
           .catch(() => {
             eventHub.$emit(ALERT_EVENT, {
@@ -65,24 +75,57 @@ export default Extension.create({
   addProseMirrorPlugins() {
     let pasteRaw = false;
 
+    const handleCutAndCopy = (view, event) => {
+      const slice = view.state.selection.content();
+      const gfmContent = this.options.serializer.serialize({ doc: slice.content });
+      const documentFragment = DOMSerializer.fromSchema(view.state.schema).serializeFragment(
+        slice.content,
+      );
+      const div = document.createElement('div');
+      div.appendChild(documentFragment);
+
+      event.clipboardData.setData(TEXT_FORMAT, div.innerText);
+      event.clipboardData.setData(HTML_FORMAT, div.innerHTML);
+      event.clipboardData.setData(GFM_FORMAT, gfmContent);
+
+      event.preventDefault();
+      event.stopPropagation();
+    };
+
     return [
       new Plugin({
         key: new PluginKey('pasteMarkdown'),
         props: {
+          handleDOMEvents: {
+            copy: handleCutAndCopy,
+            cut: (view, event) => {
+              handleCutAndCopy(view, event);
+              this.editor.commands.deleteSelection();
+            },
+          },
           handleKeyDown: (_, event) => {
             pasteRaw = event.key === 'v' && (event.metaKey || event.ctrlKey) && event.shiftKey;
           },
 
           handlePaste: (view, event) => {
             const { clipboardData } = event;
-            const content = clipboardData.getData(TEXT_FORMAT);
-            const { state } = view;
-            const { tr, selection } = state;
-            const { from, to } = selection;
+
+            const gfmContent = clipboardData.getData(GFM_FORMAT);
+
+            if (gfmContent) {
+              return this.editor.commands.pasteContent(gfmContent, true);
+            }
+
+            const textContent = clipboardData.getData(TEXT_FORMAT);
+            const htmlContent = clipboardData.getData(HTML_FORMAT);
+
+            const { from, to } = view.state.selection;
 
             if (pasteRaw) {
-              tr.insertText(content.replace(/^\s+|\s+$/gm, ''), from, to);
-              view.dispatch(tr);
+              this.editor.commands.insertContentAt(
+                { from, to },
+                textContent.replace(/^\s+|\s+$/gm, ''),
+              );
               return true;
             }
 
@@ -91,18 +134,19 @@ export default Extension.create({
             const vsCodeMeta = hasVsCode ? JSON.parse(clipboardData.getData(VS_CODE_FORMAT)) : {};
             const language = vsCodeMeta.mode;
 
-            if (!content || (hasHTML && !hasVsCode) || (hasVsCode && language !== 'markdown')) {
-              return false;
-            }
-
             // if a code block is active, paste as plain text
-            if (CODE_BLOCK_NODE_TYPES.some((type) => this.editor.isActive(type))) {
+            if (!textContent || CODE_BLOCK_NODE_TYPES.some((type) => this.editor.isActive(type))) {
               return false;
             }
 
-            this.editor.commands.pasteMarkdown(content);
+            if (hasVsCode) {
+              return this.editor.commands.pasteContent(
+                language === 'markdown' ? textContent : `\`\`\`${language}\n${textContent}\n\`\`\``,
+                true,
+              );
+            }
 
-            return true;
+            return this.editor.commands.pasteContent(hasHTML ? htmlContent : textContent, !hasHTML);
           },
         },
       }),
diff --git a/app/assets/javascripts/content_editor/extensions/reference_label.js b/app/assets/javascripts/content_editor/extensions/reference_label.js
index 6fe904ed787c799198786784030c2a6e36b2cd12..9cd55a0f87c280d6acad67a0bf6d13dd2990a6e4 100644
--- a/app/assets/javascripts/content_editor/extensions/reference_label.js
+++ b/app/assets/javascripts/content_editor/extensions/reference_label.js
@@ -20,7 +20,13 @@ export default Reference.extend({
       },
       color: {
         default: null,
-        parseHTML: (element) => element.querySelector('.gl-label-text').style.backgroundColor,
+        parseHTML: (element) => {
+          let color = element.querySelector('.gl-label-text').style.backgroundColor;
+          if (!color || color.startsWith('var'))
+            color = element.style.getPropertyValue('--label-background-color');
+
+          return color;
+        },
       },
     };
   },
diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js
index 834fb72daba1c1eea99913ea1958c3461083ec1c..ee1f706ec7e335df4cc25aab9e3e82caafa190a8 100644
--- a/app/assets/javascripts/content_editor/services/create_content_editor.js
+++ b/app/assets/javascripts/content_editor/services/create_content_editor.js
@@ -64,7 +64,7 @@ import Text from '../extensions/text';
 import Video from '../extensions/video';
 import WordBreak from '../extensions/word_break';
 import { ContentEditor } from './content_editor';
-import createMarkdownSerializer from './markdown_serializer';
+import MarkdownSerializer from './markdown_serializer';
 import createGlApiMarkdownDeserializer from './gl_api_markdown_deserializer';
 import createRemarkMarkdownDeserializer from './remark_markdown_deserializer';
 import AssetResolver from './asset_resolver';
@@ -97,6 +97,12 @@ export const createContentEditor = ({
 
   const eventHub = eventHubFactory();
   const assetResolver = new AssetResolver({ renderMarkdown });
+  const serializer = new MarkdownSerializer({ serializerConfig });
+  const deserializer = window.gon?.features?.preserveUnchangedMarkdown
+    ? createRemarkMarkdownDeserializer()
+    : createGlApiMarkdownDeserializer({
+        render: renderMarkdown,
+      });
 
   const builtInContentEditorExtensions = [
     Attachment.configure({ uploadsPath, renderMarkdown, eventHub }),
@@ -139,7 +145,7 @@ export const createContentEditor = ({
     MathInline,
     OrderedList,
     Paragraph,
-    PasteMarkdown.configure({ eventHub, renderMarkdown }),
+    PasteMarkdown.configure({ eventHub, renderMarkdown, serializer }),
     Reference.configure({ assetResolver }),
     ReferenceLabel,
     ReferenceDefinition,
@@ -167,12 +173,6 @@ export const createContentEditor = ({
 
   const trackedExtensions = allExtensions.map(trackInputRulesAndShortcuts);
   const tiptapEditor = createTiptapEditor({ extensions: trackedExtensions, ...tiptapOptions });
-  const serializer = createMarkdownSerializer({ serializerConfig });
-  const deserializer = window.gon?.features?.preserveUnchangedMarkdown
-    ? createRemarkMarkdownDeserializer()
-    : createGlApiMarkdownDeserializer({
-        render: renderMarkdown,
-      });
 
   return new ContentEditor({
     tiptapEditor,
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index 3b77064e903df6a6fc193bcf76f6ec2e52e9ffe2..20899dcf5bdc457f5edbc790de429c6949bcc50f 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -67,6 +67,7 @@ import {
   renderContent,
   renderBulletList,
   renderReference,
+  renderReferenceLabel,
   preserveUnchanged,
   bold,
   italic,
@@ -197,7 +198,7 @@ const defaultSerializerConfig = {
     [OrderedList.name]: preserveUnchanged(renderOrderedList),
     [Paragraph.name]: preserveUnchanged(defaultMarkdownSerializer.nodes.paragraph),
     [Reference.name]: renderReference,
-    [ReferenceLabel.name]: renderReference,
+    [ReferenceLabel.name]: renderReferenceLabel,
     [ReferenceDefinition.name]: preserveUnchanged({
       render: (state, node, parent, index, same, sourceMarkdown) => {
         const nextSibling = parent.maybeChild(index + 1);
@@ -273,19 +274,22 @@ const createChangeTracker = (doc, pristineDoc) => {
   return changeTracker;
 };
 
-/**
- * Converts a ProseMirror document to Markdown. See the
- * following documentation to learn how to implement
- * custom node and mark serializer functions.
- *
- * https://github.com/prosemirror/prosemirror-markdown
- *
- * @param {Object} params.nodes ProseMirror node serializer functions
- * @param {Object} params.marks ProseMirror marks serializer config
- *
- * @returns a markdown serializer
- */
-export default ({ serializerConfig = {} } = {}) => ({
+export default class MarkdownSerializer {
+  /**
+   * Converts a ProseMirror document to Markdown. See the
+   * following documentation to learn how to implement
+   * custom node and mark serializer functions.
+   *
+   * https://github.com/prosemirror/prosemirror-markdown
+   *
+   * @param {Object} params.nodes ProseMirror node serializer functions
+   * @param {Object} params.marks ProseMirror marks serializer config
+   *
+   * @returns a markdown serializer
+   */
+  constructor({ serializerConfig = {} } = {}) {
+    this.serializerConfig = serializerConfig;
+  }
   /**
    * Serializes a ProseMirror document as Markdown. If a node contains
    * sourcemap metadata, the serializer is capable of restoring the
@@ -301,16 +305,16 @@ export default ({ serializerConfig = {} } = {}) => ({
    * changed.
    * @returns A String that represents the serialized document as Markdown
    */
-  serialize: ({ doc, pristineDoc }) => {
+  serialize({ doc, pristineDoc }) {
     const changeTracker = createChangeTracker(doc, pristineDoc);
     const serializer = new ProseMirrorMarkdownSerializer(
       {
         ...defaultSerializerConfig.nodes,
-        ...serializerConfig.nodes,
+        ...this.serializerConfig.nodes,
       },
       {
         ...defaultSerializerConfig.marks,
-        ...serializerConfig.marks,
+        ...this.serializerConfig.marks,
       },
     );
 
@@ -318,5 +322,5 @@ export default ({ serializerConfig = {} } = {}) => ({
       tightLists: true,
       changeTracker,
     });
-  },
-});
+  }
+}
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index 9d8dec96152f7b7ec8c1ba420c9b28af041bc014..b6bcda8d801c61691aabd73efd36889db3b2f788 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -157,6 +157,10 @@ function setIsInBlockTable(table, value) {
   });
 }
 
+function ensureSpace(state) {
+  if (!state.atBlank() && !state.out.endsWith(' ')) state.write(' ');
+}
+
 function unsetIsInBlockTable(table) {
   tableMap.delete(table);
 
@@ -457,9 +461,15 @@ export function renderOrderedList(state, node) {
 }
 
 export function renderReference(state, node) {
+  ensureSpace(state);
   state.write(node.attrs.originalText || node.attrs.text);
 }
 
+export function renderReferenceLabel(state, node) {
+  ensureSpace(state);
+  state.write(node.attrs.originalText || `~${state.quote(node.attrs.text)}`);
+}
+
 const generateBoldTags = (wrapTagName = openTag) => {
   return (_, mark) => {
     const type = /^(\*\*|__|<strong|<b).*/.exec(mark.attrs.sourceMarkdown)?.[1];
diff --git a/glfm_specification/output_example_snapshots/prosemirror_json.yml b/glfm_specification/output_example_snapshots/prosemirror_json.yml
index 8cce959c8f895505d5762da84cab0044e0a321d5..bc6293b54b228a51a863242eee2cf5ba896c507a 100644
--- a/glfm_specification/output_example_snapshots/prosemirror_json.yml
+++ b/glfm_specification/output_example_snapshots/prosemirror_json.yml
@@ -3195,10 +3195,8 @@
                   {
                     "type": "link",
                     "attrs": {
-                      "href": "bar",
-                      "target": "_blank",
-                      "class": null,
                       "uploading": false,
+                      "href": "bar",
                       "title": null,
                       "canonicalSrc": "bar",
                       "isReference": false
@@ -3282,10 +3280,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": false
@@ -3804,10 +3800,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "bar",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "bar",
                   "title": null,
                   "canonicalSrc": "bar",
                   "isReference": false
@@ -3965,10 +3959,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4008,10 +4000,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "the title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4051,10 +4041,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "my_(url)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "my_(url)",
                   "title": "title (with parens)",
                   "canonicalSrc": "foo*bar\\]",
                   "isReference": true
@@ -4094,10 +4082,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "my%20url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "my%20url",
                   "title": "title",
                   "canonicalSrc": "foo bar",
                   "isReference": true
@@ -4137,10 +4123,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "\ntitle\nline1\nline2\n",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4213,10 +4197,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4280,10 +4262,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4347,10 +4327,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url%5Cbar*baz",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url%5Cbar*baz",
                   "title": "foo\"bar\\baz",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4376,10 +4354,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4419,10 +4395,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "first",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "first",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4490,10 +4464,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4533,10 +4505,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/%CF%86%CE%BF%CF%85",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/%CF%86%CE%BF%CF%85",
                   "title": null,
                   "canonicalSrc": "αγω",
                   "isReference": true
@@ -4740,10 +4710,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4826,10 +4794,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4873,10 +4839,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4944,10 +4908,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/foo-url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/foo-url",
                   "title": "foo",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -4966,10 +4928,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/bar-url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/bar-url",
                   "title": "bar",
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -4988,10 +4948,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/baz-url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/baz-url",
                   "title": null,
                   "canonicalSrc": "baz",
                   "isReference": true
@@ -5017,10 +4975,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -10816,10 +10772,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com?find=%5C*",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com?find=%5C*",
                   "title": null,
                   "canonicalSrc": "http://example.com?find=%5C*",
                   "isReference": false
@@ -10854,10 +10808,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/bar*",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/bar*",
                   "title": "ti*tle",
                   "canonicalSrc": "/bar*",
                   "isReference": false
@@ -10883,10 +10835,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/bar*",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/bar*",
                   "title": "ti*tle",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -11045,10 +10995,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/f%C3%B6%C3%B6",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/f%C3%B6%C3%B6",
                   "title": "föö",
                   "canonicalSrc": "/f%C3%B6%C3%B6",
                   "isReference": false
@@ -11074,10 +11022,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/f%C3%B6%C3%B6",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/f%C3%B6%C3%B6",
                   "title": "föö",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -11612,10 +11558,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "`",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "`",
                   "title": null,
                   "canonicalSrc": "`",
                   "isReference": false
@@ -11665,10 +11609,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar.%60baz",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar.%60baz",
                   "title": null,
                   "canonicalSrc": "http://foo.bar.%60baz",
                   "isReference": false
@@ -12823,10 +12765,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -13295,10 +13235,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -13366,10 +13304,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -13727,10 +13663,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -14635,10 +14569,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -14668,10 +14600,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -14823,10 +14753,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar/?q=**",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar/?q=**",
                   "title": null,
                   "canonicalSrc": "http://foo.bar/?q=**",
                   "isReference": false
@@ -14856,10 +14784,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar/?q=__",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar/?q=__",
                   "title": null,
                   "canonicalSrc": "http://foo.bar/?q=__",
                   "isReference": false
@@ -14933,10 +14859,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": "title",
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -14962,10 +14886,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -14991,10 +14913,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "",
                   "title": null,
                   "canonicalSrc": "",
                   "isReference": false
@@ -15020,10 +14940,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "",
                   "title": null,
                   "canonicalSrc": "",
                   "isReference": false
@@ -15064,10 +14982,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/my%20uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/my%20uri",
                   "title": null,
                   "canonicalSrc": "/my%20uri",
                   "isReference": false
@@ -15123,10 +15039,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "b)c",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "b)c",
                   "title": null,
                   "canonicalSrc": "b)c",
                   "isReference": false
@@ -15191,10 +15105,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "(foo)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "(foo)",
                   "title": null,
                   "canonicalSrc": "(foo)",
                   "isReference": false
@@ -15220,10 +15132,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo(and(bar))",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo(and(bar))",
                   "title": null,
                   "canonicalSrc": "foo(and(bar))",
                   "isReference": false
@@ -15249,10 +15159,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo(and(bar)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo(and(bar)",
                   "title": null,
                   "canonicalSrc": "foo(and(bar)",
                   "isReference": false
@@ -15278,10 +15186,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo(and(bar)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo(and(bar)",
                   "title": null,
                   "canonicalSrc": "foo(and(bar)",
                   "isReference": false
@@ -15307,10 +15213,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo):",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo):",
                   "title": null,
                   "canonicalSrc": "foo):",
                   "isReference": false
@@ -15336,10 +15240,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "#fragment",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "#fragment",
                   "title": null,
                   "canonicalSrc": "#fragment",
                   "isReference": false
@@ -15359,10 +15261,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com#fragment",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com#fragment",
                   "title": null,
                   "canonicalSrc": "http://example.com#fragment",
                   "isReference": false
@@ -15382,10 +15282,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com?foo=3#frag",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com?foo=3#frag",
                   "title": null,
                   "canonicalSrc": "http://example.com?foo=3#frag",
                   "isReference": false
@@ -15411,10 +15309,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo%5Cbar",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo%5Cbar",
                   "title": null,
                   "canonicalSrc": "foo%5Cbar",
                   "isReference": false
@@ -15440,10 +15336,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo%20b%C3%A4",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "foo%20b%C3%A4",
                   "title": null,
                   "canonicalSrc": "foo%20b%C3%A4",
                   "isReference": false
@@ -15469,10 +15363,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "%22title%22",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "%22title%22",
                   "title": null,
                   "canonicalSrc": "%22title%22",
                   "isReference": false
@@ -15498,10 +15390,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -15527,10 +15417,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title \"\"",
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -15556,10 +15444,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url%C2%A0%22title%22",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url%C2%A0%22title%22",
                   "title": null,
                   "canonicalSrc": "/url%C2%A0%22title%22",
                   "isReference": false
@@ -15600,10 +15486,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title \"and\" title",
                   "canonicalSrc": "/url",
                   "isReference": false
@@ -15629,10 +15513,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": "title",
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15673,10 +15555,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15721,10 +15601,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15750,10 +15628,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15779,10 +15655,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15797,10 +15671,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15818,10 +15690,8 @@
               {
                 "type": "link",
                 "attrs": {
+                  "uploading": false,
                   "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
-                  "uploading": false,
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15842,10 +15712,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15890,10 +15758,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15922,10 +15788,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -15968,10 +15832,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -16041,10 +15903,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -16070,10 +15930,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "baz*",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "baz*",
                   "title": null,
                   "canonicalSrc": "baz*",
                   "isReference": false
@@ -16166,10 +16024,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com/?search=%5D(uri)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com/?search=%5D(uri)",
                   "title": null,
                   "canonicalSrc": "http://example.com/?search=%5D(uri)",
                   "isReference": false
@@ -16195,10 +16051,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -16238,10 +16092,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16281,10 +16133,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16324,10 +16174,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16342,10 +16190,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16363,10 +16209,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16387,10 +16231,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16449,10 +16291,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16495,10 +16335,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "/uri",
                   "isReference": false
@@ -16517,10 +16355,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16573,10 +16409,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16598,10 +16432,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16645,10 +16477,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16688,10 +16518,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref",
                   "isReference": true
@@ -16802,10 +16630,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com/?search=%5D%5Bref%5D",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com/?search=%5D%5Bref%5D",
                   "title": null,
                   "canonicalSrc": "http://example.com/?search=%5D%5Bref%5D",
                   "isReference": false
@@ -16845,10 +16671,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -16888,10 +16712,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "толпой",
                   "isReference": true
@@ -16949,10 +16771,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo bar",
                   "isReference": true
@@ -16982,10 +16802,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -17029,10 +16847,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -17100,10 +16916,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url1",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17230,10 +17044,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "ref\\[",
                   "isReference": true
@@ -17287,10 +17099,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uri",
                   "title": null,
                   "canonicalSrc": "bar\\\\",
                   "isReference": true
@@ -17364,10 +17174,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17407,10 +17215,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "*foo* bar",
                   "isReference": true
@@ -17428,10 +17234,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "*foo* bar",
                   "isReference": true
@@ -17471,10 +17275,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17514,10 +17316,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17561,10 +17361,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17604,10 +17402,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "*foo* bar",
                   "isReference": true
@@ -17625,10 +17421,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "*foo* bar",
                   "isReference": true
@@ -17672,10 +17466,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "*foo* bar",
                   "isReference": true
@@ -17693,10 +17485,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "*foo* bar",
                   "isReference": true
@@ -17744,10 +17534,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17787,10 +17575,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17830,10 +17616,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -17924,10 +17708,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "foo*",
                   "isReference": true
@@ -17953,10 +17735,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url2",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url2",
                   "title": null,
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -18010,10 +17790,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url1",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -18053,10 +17831,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "",
                   "title": null,
                   "canonicalSrc": "",
                   "isReference": false
@@ -18096,10 +17872,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url1",
                   "title": null,
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -18147,10 +17921,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": null,
                   "canonicalSrc": "baz",
                   "isReference": true
@@ -18190,10 +17962,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url2",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url2",
                   "title": null,
                   "canonicalSrc": "bar",
                   "isReference": true
@@ -18208,10 +17978,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url1",
                   "title": null,
                   "canonicalSrc": "baz",
                   "isReference": true
@@ -18269,10 +18037,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url1",
                   "title": null,
                   "canonicalSrc": "baz",
                   "isReference": true
@@ -19015,10 +18781,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/url",
                   "title": "title",
                   "canonicalSrc": "foo",
                   "isReference": true
@@ -19058,10 +18822,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar.baz",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar.baz",
                   "title": null,
                   "canonicalSrc": "http://foo.bar.baz",
                   "isReference": false
@@ -19087,10 +18849,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar.baz/test?q=hello&id=22&boolean",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar.baz/test?q=hello&id=22&boolean",
                   "title": null,
                   "canonicalSrc": "http://foo.bar.baz/test?q=hello&id=22&boolean",
                   "isReference": false
@@ -19116,10 +18876,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": null,
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": null,
                   "title": null,
                   "canonicalSrc": null,
                   "isReference": false
@@ -19145,10 +18903,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "MAILTO:FOO@BAR.BAZ",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "MAILTO:FOO@BAR.BAZ",
                   "title": null,
                   "canonicalSrc": "MAILTO:FOO@BAR.BAZ",
                   "isReference": false
@@ -19174,10 +18930,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": null,
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": null,
                   "title": null,
                   "canonicalSrc": null,
                   "isReference": false
@@ -19203,10 +18957,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": null,
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": null,
                   "title": null,
                   "canonicalSrc": null,
                   "isReference": false
@@ -19232,10 +18984,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://../",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://../",
                   "title": null,
                   "canonicalSrc": "http://../",
                   "isReference": false
@@ -19261,10 +19011,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": null,
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": null,
                   "title": null,
                   "canonicalSrc": null,
                   "isReference": false
@@ -19294,10 +19042,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar/baz",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar/baz",
                   "title": null,
                   "canonicalSrc": "http://foo.bar/baz",
                   "isReference": false
@@ -19327,10 +19073,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com/%5C%5B%5C",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com/%5C%5B%5C",
                   "title": null,
                   "canonicalSrc": "http://example.com/%5C%5B%5C",
                   "isReference": false
@@ -19356,10 +19100,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:foo@bar.example.com",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:foo@bar.example.com",
                   "title": null,
                   "canonicalSrc": "mailto:foo@bar.example.com",
                   "isReference": false
@@ -19385,10 +19127,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:foo+special@Bar.baz-bar0.com",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:foo+special@Bar.baz-bar0.com",
                   "title": null,
                   "canonicalSrc": "mailto:foo+special@Bar.baz-bar0.com",
                   "isReference": false
@@ -19418,10 +19158,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:foo+@bar.example.com",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:foo+@bar.example.com",
                   "title": null,
                   "canonicalSrc": "mailto:foo+@bar.example.com",
                   "isReference": false
@@ -19470,10 +19208,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://foo.bar",
                   "title": null,
                   "canonicalSrc": "http://foo.bar",
                   "isReference": false
@@ -19533,10 +19269,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://example.com",
                   "title": null,
                   "canonicalSrc": "http://example.com",
                   "isReference": false
@@ -19562,10 +19296,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:foo@bar.example.com",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:foo@bar.example.com",
                   "title": null,
                   "canonicalSrc": "mailto:foo@bar.example.com",
                   "isReference": false
@@ -19591,10 +19323,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.commonmark.org",
                   "title": null,
                   "canonicalSrc": "http://www.commonmark.org",
                   "isReference": false
@@ -19624,10 +19354,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org/help",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.commonmark.org/help",
                   "title": null,
                   "canonicalSrc": "http://www.commonmark.org/help",
                   "isReference": false
@@ -19661,10 +19389,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.commonmark.org",
                   "title": null,
                   "canonicalSrc": "http://www.commonmark.org",
                   "isReference": false
@@ -19692,10 +19418,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org/a.b",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.commonmark.org/a.b",
                   "title": null,
                   "canonicalSrc": "http://www.commonmark.org/a.b",
                   "isReference": false
@@ -19725,10 +19449,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=Markup+(business)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=Markup+(business)",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
                   "isReference": false
@@ -19748,10 +19470,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=Markup+(business)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=Markup+(business)",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
                   "isReference": false
@@ -19779,10 +19499,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=Markup+(business)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=Markup+(business)",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
                   "isReference": false
@@ -19810,10 +19528,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=Markup+(business)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=Markup+(business)",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=Markup+(business)",
                   "isReference": false
@@ -19839,10 +19555,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=(business))+ok",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=(business))+ok",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=(business))+ok",
                   "isReference": false
@@ -19868,10 +19582,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=commonmark&hl=en",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=commonmark&hl=en",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=commonmark&hl=en",
                   "isReference": false
@@ -19891,10 +19603,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.google.com/search?q=commonmark",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.google.com/search?q=commonmark",
                   "title": null,
                   "canonicalSrc": "http://www.google.com/search?q=commonmark",
                   "isReference": false
@@ -19924,10 +19634,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org/he",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://www.commonmark.org/he",
                   "title": null,
                   "canonicalSrc": "http://www.commonmark.org/he",
                   "isReference": false
@@ -19957,10 +19665,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://commonmark.org",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "http://commonmark.org",
                   "title": null,
                   "canonicalSrc": "http://commonmark.org",
                   "isReference": false
@@ -19984,10 +19690,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "https://encrypted.google.com/search?q=Markup+(business)",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "https://encrypted.google.com/search?q=Markup+(business)",
                   "title": null,
                   "canonicalSrc": "https://encrypted.google.com/search?q=Markup+(business)",
                   "isReference": false
@@ -20026,10 +19730,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:foo@bar.baz",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:foo@bar.baz",
                   "title": null,
                   "canonicalSrc": "mailto:foo@bar.baz",
                   "isReference": false
@@ -20059,10 +19761,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:hello+xyz@mail.example",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:hello+xyz@mail.example",
                   "title": null,
                   "canonicalSrc": "mailto:hello+xyz@mail.example",
                   "isReference": false
@@ -20092,10 +19792,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:a.b-c_d@a.b",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:a.b-c_d@a.b",
                   "title": null,
                   "canonicalSrc": "mailto:a.b-c_d@a.b",
                   "isReference": false
@@ -20115,10 +19813,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "mailto:a.b-c_d@a.b",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "mailto:a.b-c_d@a.b",
                   "title": null,
                   "canonicalSrc": "mailto:a.b-c_d@a.b",
                   "isReference": false
@@ -21347,10 +21043,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip",
                   "title": null,
                   "canonicalSrc": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip",
                   "isReference": false
@@ -21376,10 +21070,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip",
                   "title": null,
                   "canonicalSrc": "/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip",
                   "isReference": false
@@ -21433,10 +21125,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "test-file.zip",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "test-file.zip",
                   "title": null,
                   "canonicalSrc": "test-file.zip",
                   "isReference": false
@@ -23118,10 +22808,8 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "https://gitlab.com",
-                  "target": "_blank",
-                  "class": null,
                   "uploading": false,
+                  "href": "https://gitlab.com",
                   "title": null,
                   "canonicalSrc": "https://gitlab.com",
                   "isReference": false
diff --git a/package.json b/package.json
index 71c2c49000ca968bb49a9d913a5052b0f97b2e1a..f02d0a1f8646270adb06d2dea6a85da9ea2dbcbc 100644
--- a/package.json
+++ b/package.json
@@ -169,6 +169,7 @@
     "monaco-editor-webpack-plugin": "^6.0.0",
     "monaco-yaml": "4.0.0",
     "mousetrap": "1.6.5",
+    "orderedmap": "^2.1.1",
     "papaparse": "^5.3.1",
     "patch-package": "^6.4.7",
     "pdfjs-dist": "^2.16.105",
diff --git a/spec/frontend/content_editor/extensions/paste_markdown_spec.js b/spec/frontend/content_editor/extensions/paste_markdown_spec.js
index c9997e3c58fb83b97bb104cefc4729609bdd0201..baf0919fec80f7eb75da1fde4b1b9a7e4103ec89 100644
--- a/spec/frontend/content_editor/extensions/paste_markdown_spec.js
+++ b/spec/frontend/content_editor/extensions/paste_markdown_spec.js
@@ -4,24 +4,28 @@ import Diagram from '~/content_editor/extensions/diagram';
 import Frontmatter from '~/content_editor/extensions/frontmatter';
 import Heading from '~/content_editor/extensions/heading';
 import Bold from '~/content_editor/extensions/bold';
+import Italic from '~/content_editor/extensions/italic';
 import { VARIANT_DANGER } from '~/alert';
 import eventHubFactory from '~/helpers/event_hub_factory';
 import { ALERT_EVENT } from '~/content_editor/constants';
 import waitForPromises from 'helpers/wait_for_promises';
+import MarkdownSerializer from '~/content_editor/services/markdown_serializer';
 import { createTestEditor, createDocBuilder, waitUntilNextDocTransaction } from '../test_utils';
 
 const CODE_BLOCK_HTML = '<pre class="js-syntax-highlight" lang="javascript">var a = 2;</pre>';
 const DIAGRAM_HTML =
   '<img data-diagram="nomnoml" data-diagram-src="data:text/plain;base64,WzxmcmFtZT5EZWNvcmF0b3IgcGF0dGVybl0=">';
 const FRONTMATTER_HTML = '<pre lang="yaml" data-lang-params="frontmatter">key: value</pre>';
-const PARAGRAPH_HTML = '<p>Just a regular paragraph</p>';
+const PARAGRAPH_HTML = '<p>Some text with <strong>bold</strong> and <em>italic</em> text.</p>';
 
 describe('content_editor/extensions/paste_markdown', () => {
   let tiptapEditor;
   let doc;
   let p;
   let bold;
+  let italic;
   let heading;
+  let codeBlock;
   let renderMarkdown;
   let eventHub;
   const defaultData = { 'text/plain': '**bold text**' };
@@ -35,28 +39,36 @@ describe('content_editor/extensions/paste_markdown', () => {
     tiptapEditor = createTestEditor({
       extensions: [
         Bold,
+        Italic,
         CodeBlockHighlight,
         Diagram,
         Frontmatter,
         Heading,
-        PasteMarkdown.configure({ renderMarkdown, eventHub }),
+        PasteMarkdown.configure({ renderMarkdown, eventHub, serializer: new MarkdownSerializer() }),
       ],
     });
 
     ({
-      builders: { doc, p, bold, heading },
+      builders: { doc, p, bold, italic, heading, codeBlock },
     } = createDocBuilder({
       tiptapEditor,
       names: {
         bold: { markType: Bold.name },
+        italic: { markType: Italic.name },
         heading: { nodeType: Heading.name },
+        codeBlock: { nodeType: CodeBlockHighlight.name },
       },
     }));
   });
 
-  const buildClipboardEvent = ({ data = {}, types = ['text/plain'] } = {}) => {
-    return Object.assign(new Event('paste'), {
-      clipboardData: { types, getData: jest.fn((type) => data[type] || defaultData[type]) },
+  const buildClipboardEvent = ({ eventName = 'paste', data = {}, types = ['text/plain'] } = {}) => {
+    return Object.assign(new Event(eventName), {
+      clipboardData: {
+        types,
+        getData: jest.fn((type) => data[type] || defaultData[type]),
+        setData: jest.fn(),
+        clearData: jest.fn(),
+      },
     });
   };
 
@@ -80,13 +92,13 @@ describe('content_editor/extensions/paste_markdown', () => {
   };
 
   it.each`
-    types                                                | data                                                  | handled  | desc
-    ${['text/plain']}                                    | ${{}}                                                 | ${true}  | ${'handles plain text'}
-    ${['text/plain', 'text/html']}                       | ${{}}                                                 | ${false} | ${'doesn’t handle html format'}
-    ${['text/plain', 'text/html', 'vscode-editor-data']} | ${{ 'vscode-editor-data': '{ "mode": "markdown" }' }} | ${true}  | ${'handles vscode markdown'}
-    ${['text/plain', 'text/html', 'vscode-editor-data']} | ${{ 'vscode-editor-data': '{ "mode": "ruby" }' }}     | ${false} | ${'doesn’t vscode code snippet'}
-  `('$desc', async ({ types, handled, data }) => {
-    expect(await triggerPasteEventHandler(buildClipboardEvent({ types, data }))).toBe(handled);
+    types                                                | data                                                  | formatDesc
+    ${['text/plain']}                                    | ${{}}                                                 | ${'plain text'}
+    ${['text/plain', 'text/html']}                       | ${{}}                                                 | ${'html format'}
+    ${['text/plain', 'text/html', 'vscode-editor-data']} | ${{ 'vscode-editor-data': '{ "mode": "markdown" }' }} | ${'vscode markdown'}
+    ${['text/plain', 'text/html', 'vscode-editor-data']} | ${{ 'vscode-editor-data': '{ "mode": "ruby" }' }}     | ${'vscode snippet'}
+  `('handles $formatDesc', async ({ types, data }) => {
+    expect(await triggerPasteEventHandler(buildClipboardEvent({ types, data }))).toBe(true);
   });
 
   it.each`
@@ -101,6 +113,45 @@ describe('content_editor/extensions/paste_markdown', () => {
     expect(await triggerPasteEventHandler(buildClipboardEvent())).toBe(handled);
   });
 
+  describe.each`
+    eventName | expectedDoc
+    ${'cut'}  | ${() => doc(p())}
+    ${'copy'} | ${() => doc(p('Some text with ', bold('bold'), ' and ', italic('italic'), ' text.'))}
+  `('when $eventName event is triggered', ({ eventName, expectedDoc }) => {
+    let event;
+    beforeEach(() => {
+      event = buildClipboardEvent({ eventName });
+
+      jest.spyOn(event, 'preventDefault');
+      jest.spyOn(event, 'stopPropagation');
+
+      tiptapEditor.commands.insertContent(PARAGRAPH_HTML);
+      tiptapEditor.commands.selectAll();
+      tiptapEditor.view.dispatchEvent(event);
+    });
+
+    it('prevents default', () => {
+      expect(event.preventDefault).toHaveBeenCalled();
+      expect(event.stopPropagation).toHaveBeenCalled();
+    });
+
+    it('sets the clipboard data', () => {
+      expect(event.clipboardData.setData).toHaveBeenCalledWith(
+        'text/plain',
+        'Some text with bold and italic text.',
+      );
+      expect(event.clipboardData.setData).toHaveBeenCalledWith('text/html', PARAGRAPH_HTML);
+      expect(event.clipboardData.setData).toHaveBeenCalledWith(
+        'text/x-gfm',
+        'Some text with **bold** and _italic_ text.',
+      );
+    });
+
+    it('modifies the document', () => {
+      expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc().toJSON());
+    });
+  });
+
   describe('when pasting raw markdown source', () => {
     describe('when rendering markdown succeeds', () => {
       beforeEach(() => {
@@ -162,6 +213,97 @@ describe('content_editor/extensions/paste_markdown', () => {
       });
     });
 
+    describe('when pasting html content', () => {
+      it('strips out any stray div, pre, span tags', async () => {
+        renderMarkdown.mockResolvedValueOnce(
+          '<div><span dir="auto"><strong>bold text</strong></span></div><pre><code>some code</code></pre>',
+        );
+
+        const expectedDoc = doc(p(bold('bold text')), p('some code'));
+
+        await triggerPasteEventHandlerAndWaitForTransaction(
+          buildClipboardEvent({
+            types: ['text/html'],
+            data: {
+              'text/html':
+                '<div><span dir="auto"><strong>bold text</strong></span></div><pre><code>some code</code></pre>',
+            },
+          }),
+        );
+
+        expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc.toJSON());
+      });
+    });
+
+    describe('when pasting text/x-gfm', () => {
+      it('processes the content as markdown, even if html content exists', async () => {
+        renderMarkdown.mockResolvedValueOnce('<strong>bold text</strong>');
+
+        const expectedDoc = doc(p(bold('bold text')));
+
+        await triggerPasteEventHandlerAndWaitForTransaction(
+          buildClipboardEvent({
+            types: ['text/x-gfm'],
+            data: {
+              'text/x-gfm': '**bold text**',
+              'text/plain': 'irrelevant text',
+              'text/html': '<div>some random irrelevant html</div>',
+            },
+          }),
+        );
+
+        expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc.toJSON());
+      });
+    });
+
+    describe('when pasting vscode-editor-data', () => {
+      it('pastes the content as a code block', async () => {
+        renderMarkdown.mockResolvedValueOnce(
+          '<div class="gl-relative markdown-code-block js-markdown-code">&#x000A;<pre data-sourcepos="1:1-3:3" data-canonical-lang="ruby" class="code highlight js-syntax-highlight language-ruby" lang="ruby" v-pre="true"><code><span id="LC1" class="line" lang="ruby"><span class="nb">puts</span> <span class="s2">"Hello World"</span></span></code></pre>&#x000A;<copy-code></copy-code>&#x000A;</div>',
+        );
+
+        const expectedDoc = doc(
+          codeBlock(
+            { language: 'ruby', class: 'code highlight js-syntax-highlight language-ruby' },
+            'puts "Hello World"',
+          ),
+        );
+
+        await triggerPasteEventHandlerAndWaitForTransaction(
+          buildClipboardEvent({
+            types: ['vscode-editor-data', 'text/plain', 'text/html'],
+            data: {
+              'vscode-editor-data': '{ "version": 1, "mode": "ruby" }',
+              'text/plain': 'puts "Hello World"',
+              'text/html':
+                '<meta charset=\'utf-8\'><div style="color: #d4d4d4;background-color: #1e1e1e;font-family: \'Fira Code\', Menlo, Monaco, \'Courier New\', monospace, Menlo, Monaco, \'Courier New\', monospace;font-weight: normal;font-size: 14px;line-height: 21px;white-space: pre;"><div><span style="color: #dcdcaa;">puts</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"Hello world"</span></div></div>',
+            },
+          }),
+        );
+
+        expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc.toJSON());
+      });
+
+      it('pastes as regular markdown if language is markdown', async () => {
+        renderMarkdown.mockResolvedValueOnce('<p><strong>bold text</strong></p>');
+
+        const expectedDoc = doc(p(bold('bold text')));
+
+        await triggerPasteEventHandlerAndWaitForTransaction(
+          buildClipboardEvent({
+            types: ['vscode-editor-data', 'text/plain', 'text/html'],
+            data: {
+              'vscode-editor-data': '{ "version": 1, "mode": "markdown" }',
+              'text/plain': '**bold text**',
+              'text/html': '<p><strong>bold text</strong></p>',
+            },
+          }),
+        );
+
+        expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc.toJSON());
+      });
+    });
+
     describe('when rendering markdown fails', () => {
       beforeEach(() => {
         renderMarkdown.mockRejectedValueOnce();
diff --git a/spec/frontend/content_editor/remark_markdown_processing_spec.js b/spec/frontend/content_editor/remark_markdown_processing_spec.js
index 359e69c083a8f4ce802c01ea548da7b0d431d943..927a7d59899e680ff06f20d2ec0a56601082a96b 100644
--- a/spec/frontend/content_editor/remark_markdown_processing_spec.js
+++ b/spec/frontend/content_editor/remark_markdown_processing_spec.js
@@ -30,7 +30,7 @@ import TaskList from '~/content_editor/extensions/task_list';
 import TaskItem from '~/content_editor/extensions/task_item';
 import Video from '~/content_editor/extensions/video';
 import remarkMarkdownDeserializer from '~/content_editor/services/remark_markdown_deserializer';
-import markdownSerializer from '~/content_editor/services/markdown_serializer';
+import MarkdownSerializer from '~/content_editor/services/markdown_serializer';
 import { SAFE_VIDEO_EXT, SAFE_AUDIO_EXT, DIAGRAM_LANGUAGES } from '~/content_editor/constants';
 
 import { createTestEditor, createDocBuilder } from './test_utils';
@@ -158,7 +158,7 @@ describe('Client side Markdown processing', () => {
   };
 
   const serialize = (document) =>
-    markdownSerializer({}).serialize({
+    new MarkdownSerializer().serialize({
       doc: document,
       pristineDoc: document,
     });
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 71885003b6ca434d00e773bd2e42709f2eed0bf6..0771eab201278aec54e7aeaeba253843a967b034 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -26,6 +26,8 @@ import Link from '~/content_editor/extensions/link';
 import ListItem from '~/content_editor/extensions/list_item';
 import OrderedList from '~/content_editor/extensions/ordered_list';
 import Paragraph from '~/content_editor/extensions/paragraph';
+import Reference from '~/content_editor/extensions/reference';
+import ReferenceLabel from '~/content_editor/extensions/reference_label';
 import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
 import Sourcemap from '~/content_editor/extensions/sourcemap';
 import Strike from '~/content_editor/extensions/strike';
@@ -35,7 +37,7 @@ import TableHeader from '~/content_editor/extensions/table_header';
 import TableRow from '~/content_editor/extensions/table_row';
 import TaskItem from '~/content_editor/extensions/task_item';
 import TaskList from '~/content_editor/extensions/task_list';
-import markdownSerializer from '~/content_editor/services/markdown_serializer';
+import MarkdownSerializer from '~/content_editor/services/markdown_serializer';
 import remarkMarkdownDeserializer from '~/content_editor/services/remark_markdown_deserializer';
 import { createTiptapEditor, createDocBuilder } from '../test_utils';
 
@@ -76,6 +78,8 @@ const {
     orderedList,
     paragraph,
     referenceDefinition,
+    reference,
+    referenceLabel,
     strike,
     table,
     tableCell,
@@ -116,6 +120,8 @@ const {
     orderedList: { nodeType: OrderedList.name },
     paragraph: { nodeType: Paragraph.name },
     referenceDefinition: { nodeType: ReferenceDefinition.name },
+    reference: { nodeType: Reference.name },
+    referenceLabel: { nodeType: ReferenceLabel.name },
     strike: { markType: Strike.name },
     table: { nodeType: Table.name },
     tableCell: { nodeType: TableCell.name },
@@ -134,7 +140,7 @@ const {
 });
 
 const serialize = (...content) =>
-  markdownSerializer({}).serialize({
+  new MarkdownSerializer().serialize({
     doc: doc(...content),
   });
 
@@ -281,6 +287,77 @@ hi
     ).toBe('![GitLab][gitlab-url]');
   });
 
+  it('correctly serializes references', () => {
+    expect(
+      serialize(
+        paragraph(
+          reference({
+            referenceType: 'issue',
+            originalText: '#123',
+            href: '/gitlab-org/gitlab-test/-/issues/123',
+            text: '#123',
+          }),
+        ),
+      ),
+    ).toBe('#123');
+  });
+
+  it('correctly renders a reference label', () => {
+    expect(
+      serialize(
+        paragraph(
+          referenceLabel({
+            referenceType: 'label',
+            originalText: '~foo',
+            href: '/gitlab-org/gitlab-test/-/labels/foo',
+            text: '~foo',
+          }),
+        ),
+      ),
+    ).toBe('~foo');
+  });
+
+  it('correctly renders a reference label without originalText', () => {
+    expect(
+      serialize(
+        paragraph(
+          referenceLabel({
+            referenceType: 'label',
+            href: '/gitlab-org/gitlab-test/-/labels/foo',
+            text: 'Foo Bar',
+          }),
+        ),
+      ),
+    ).toBe('~"Foo Bar"');
+  });
+
+  it('ensures spaces between multiple references', () => {
+    expect(
+      serialize(
+        paragraph(
+          reference({
+            referenceType: 'issue',
+            originalText: '#123',
+            href: '/gitlab-org/gitlab-test/-/issues/123',
+            text: '#123',
+          }),
+          referenceLabel({
+            referenceType: 'label',
+            originalText: '~foo',
+            href: '/gitlab-org/gitlab-test/-/labels/foo',
+            text: '~foo',
+          }),
+          reference({
+            referenceType: 'issue',
+            originalText: '#456',
+            href: '/gitlab-org/gitlab-test/-/issues/456',
+            text: '#456',
+          }),
+        ),
+      ),
+    ).toBe('#123 ~foo #456');
+  });
+
   it.each`
     src
     ${'data:image/png;base64,iVBORw0KGgoAAAAN'}
@@ -1485,7 +1562,7 @@ paragraph
 
       editAction(document);
 
-      const serialized = markdownSerializer({}).serialize({
+      const serialized = new MarkdownSerializer().serialize({
         pristineDoc: document,
         doc: tiptapEditor.state.doc,
       });
diff --git a/spec/frontend/content_editor/test_utils.js b/spec/frontend/content_editor/test_utils.js
index 9357381c0535ac1741e8fea89682437c5d8343f9..2184a829cf0cc93d41645035fb6c1af47efabe1b 100644
--- a/spec/frontend/content_editor/test_utils.js
+++ b/spec/frontend/content_editor/test_utils.js
@@ -37,6 +37,8 @@ import Link from '~/content_editor/extensions/link';
 import ListItem from '~/content_editor/extensions/list_item';
 import OrderedList from '~/content_editor/extensions/ordered_list';
 import ReferenceDefinition from '~/content_editor/extensions/reference_definition';
+import Reference from '~/content_editor/extensions/reference';
+import ReferenceLabel from '~/content_editor/extensions/reference_label';
 import Strike from '~/content_editor/extensions/strike';
 import Table from '~/content_editor/extensions/table';
 import TableCell from '~/content_editor/extensions/table_cell';
@@ -291,6 +293,8 @@ export const createTiptapEditor = (extensions = []) =>
       ListItem,
       OrderedList,
       ReferenceDefinition,
+      Reference,
+      ReferenceLabel,
       Strike,
       Table,
       TableCell,
diff --git a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
index f2194f46ab411fe48f5ca096d65d841d184ec486..87b2c42c5b8b9d943b1b3f2e07bd01df5caf15de 100644
--- a/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
+++ b/spec/scripts/lib/glfm/update_example_snapshots_spec.rb
@@ -815,10 +815,8 @@
                         {
                           "type": "link",
                           "attrs": {
-                            "href": "/uploads/groups-test-file",
-                            "target": "_blank",
-                            "class": null,
                             "uploading": false,
+                            "href": "/uploads/groups-test-file",
                             "title": null,
                             "canonicalSrc": "/uploads/groups-test-file",
                             "isReference": false
@@ -844,10 +842,8 @@
                         {
                           "type": "link",
                           "attrs": {
-                            "href": "projects-test-file",
-                            "target": "_blank",
-                            "class": null,
                             "uploading": false,
+                            "href": "projects-test-file",
                             "title": null,
                             "canonicalSrc": "projects-test-file",
                             "isReference": false
@@ -903,10 +899,8 @@
                         {
                           "type": "link",
                           "attrs": {
-                            "href": "project-wikis-test-file",
-                            "target": "_blank",
-                            "class": null,
                             "uploading": false,
+                            "href": "project-wikis-test-file",
                             "title": null,
                             "canonicalSrc": "project-wikis-test-file",
                             "isReference": false
diff --git a/yarn.lock b/yarn.lock
index 2f04b2236d4b6e11b135c2d44bfa56a031931341..cb4fe862d0fb046d72afd452bf0f8fccf93bd6c5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9872,10 +9872,10 @@ optionator@^0.9.1:
     type-check "^0.4.0"
     word-wrap "^1.2.3"
 
-orderedmap@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.0.0.tgz#12ff5ef6ea9d12d6430b80c701b35475e1c9ff34"
-  integrity sha512-buf4PoAMlh45b8a8gsGy/X6w279TSqkyAS0C0wdTSJwFSU+ljQFJON5I8NfjLHoCXwpSROIo2wr0g33T+kQshQ==
+orderedmap@^2.0.0, orderedmap@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/orderedmap/-/orderedmap-2.1.1.tgz#61481269c44031c449915497bf5a4ad273c512d2"
+  integrity sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==
 
 os-browserify@^0.3.0:
   version "0.3.0"