From 0a39d5fd074490a332540c16511b469a1c6b7e63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Enrique=20Alc=C3=A1ntara?= <ealcantara@gitlab.com>
Date: Fri, 29 Jul 2022 16:12:57 +0000
Subject: [PATCH] Add basic URL resolution to client-side renderer

Add an API to the Hast to ProseMirror converter
module that allows applying a transformation
function to every attribute that matches a
given criteria for every node in the document
tree

The purpose of this API is allowing to resolve
an asset or link URL in the same way that we do
in the server side backend renderer
---
 .../services/hast_to_prosemirror_converter.js |  81 ++-
 .../services/remark_markdown_deserializer.js  |  28 +
 .../services/serialization_helpers.js         |   5 +-
 .../javascripts/lib/utils/url_utility.js      |  24 +
 glfm_specification/example_snapshots/html.yml | 324 ++++-----
 .../example_snapshots/prosemirror_json.yml    | 630 +++++++++---------
 .../remark_markdown_processing_spec.js        |  74 +-
 .../services/markdown_serializer_spec.js      |  75 ++-
 spec/frontend/lib/utils/url_utility_spec.js   |  24 +
 9 files changed, 713 insertions(+), 552 deletions(-)

diff --git a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
index 312ab88de4a0a..5eda0ff8b1a82 100644
--- a/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
+++ b/app/assets/javascripts/content_editor/services/hast_to_prosemirror_converter.js
@@ -21,7 +21,7 @@
 
 import { Mark } from 'prosemirror-model';
 import { visitParents, SKIP } from 'unist-util-visit-parents';
-import { isFunction, isString, noop } from 'lodash';
+import { isFunction, isString, noop, mapValues } from 'lodash';
 
 const NO_ATTRIBUTES = {};
 
@@ -73,28 +73,47 @@ function createSourceMapAttributes(hastNode, markdown) {
 }
 
 /**
- * Compute ProseMirror node’s attributes from a Hast node.
- * By default, this function includes sourcemap position
- * information in the object returned.
- *
- * Other attributes are retrieved by invoking a getAttrs
- * function provided by the ProseMirror node factory spec.
- *
- * @param {*} proseMirrorNodeSpec ProseMirror node spec object
- * @param {HastNode} hastNode A hast node
- * @param {Array<HastNode>} hastParents All the ancestors of the hastNode
- * @param {String} markdown Markdown source file’s content
- *
- * @returns An object that contains a ProseMirror node’s attributes
+ * Creates a function that resolves the attributes
+ * of a ProseMirror node based on a hast node.
+ *
+ * @param {Object} params Parameters
+ * @param {String} params.markdown Markdown source from which the AST was generated
+ * @param {Object} params.attributeTransformer An object that allows applying a transformation
+ * function to all the attributes listed in the attributes property.
+ * @param {Array} params.attributeTransformer.attributes A list of attributes names
+ * that the getAttrs function should apply the transformation
+ * @param {Function} params.attributeTransformer.transform A function that applies
+ * a transform operation on an attribute value.
+ * @returns A `getAttrs` function
  */
-function getAttrs(proseMirrorNodeSpec, hastNode, hastParents, markdown) {
-  const { getAttrs: specGetAttrs } = proseMirrorNodeSpec;
+const getAttrsFactory = ({ attributeTransformer, markdown }) =>
+  /**
+   * Compute ProseMirror node’s attributes from a Hast node.
+   * By default, this function includes sourcemap position
+   * information in the object returned.
+   *
+   * Other attributes are retrieved by invoking a getAttrs
+   * function provided by the ProseMirror node factory spec.
+   *
+   * @param {Object} proseMirrorNodeSpec ProseMirror node spec object
+   * @param {Object} hastNode A hast node
+   * @param {Array} hastParents All the ancestors of the hastNode
+   * @param {String} markdown Markdown source file’s content
+   * @returns An object that contains a ProseMirror node’s attributes
+   */
+  function getAttrs(proseMirrorNodeSpec, hastNode, hastParents) {
+    const { getAttrs: specGetAttrs } = proseMirrorNodeSpec;
+    const attributes = {
+      ...createSourceMapAttributes(hastNode, markdown),
+      ...(isFunction(specGetAttrs) ? specGetAttrs(hastNode, hastParents, markdown) : {}),
+    };
 
-  return {
-    ...createSourceMapAttributes(hastNode, markdown),
-    ...(isFunction(specGetAttrs) ? specGetAttrs(hastNode, hastParents, markdown) : {}),
+    return mapValues(attributes, (value, key) =>
+      attributeTransformer.attributes.includes(key)
+        ? attributeTransformer.transform(value, key)
+        : value,
+    );
   };
-}
 
 /**
  * Keeps track of the Hast -> ProseMirror conversion process.
@@ -322,7 +341,13 @@ class HastToProseMirrorConverterState {
  *
  * @returns An object that contains ProseMirror node factories
  */
-const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, markdown) => {
+const createProseMirrorNodeFactories = (
+  schema,
+  proseMirrorFactorySpecs,
+  attributeTransformer,
+  markdown,
+) => {
+  const getAttrs = getAttrsFactory({ attributeTransformer, markdown });
   const factories = {
     root: {
       selector: 'root',
@@ -355,20 +380,20 @@ const createProseMirrorNodeFactories = (schema, proseMirrorFactorySpecs, markdow
         const nodeType = schema.nodeType(proseMirrorName);
 
         state.closeUntil(parent);
-        state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
+        state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent), factory);
       };
     } else if (factory.type === 'inline') {
       const nodeType = schema.nodeType(proseMirrorName);
       factory.handle = (state, hastNode, parent) => {
         state.closeUntil(parent);
-        state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
+        state.openNode(nodeType, hastNode, getAttrs(factory, hastNode, parent), factory);
         // Inline nodes do not have children therefore they are immediately closed
         state.closeNode();
       };
     } else if (factory.type === 'mark') {
       const markType = schema.marks[proseMirrorName];
       factory.handle = (state, hastNode, parent) => {
-        state.openMark(markType, hastNode, getAttrs(factory, hastNode, parent, markdown), factory);
+        state.openMark(markType, hastNode, getAttrs(factory, hastNode, parent), factory);
       };
     } else if (factory.type === 'ignore') {
       factory.handle = noop;
@@ -581,9 +606,15 @@ export const createProseMirrorDocFromMdastTree = ({
   factorySpecs,
   wrappableTags,
   tree,
+  attributeTransformer,
   markdown,
 }) => {
-  const proseMirrorNodeFactories = createProseMirrorNodeFactories(schema, factorySpecs, markdown);
+  const proseMirrorNodeFactories = createProseMirrorNodeFactories(
+    schema,
+    factorySpecs,
+    attributeTransformer,
+    markdown,
+  );
   const state = new HastToProseMirrorConverterState();
 
   visitParents(tree, (hastNode, ancestors) => {
diff --git a/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js b/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
index e38be6720633c..b9203daf0e8f3 100644
--- a/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
+++ b/app/assets/javascripts/content_editor/services/remark_markdown_deserializer.js
@@ -125,6 +125,7 @@ const factorySpecs = {
     selector: 'img',
     getAttrs: (hastNode) => ({
       src: hastNode.properties.src,
+      canonicalSrc: hastNode.properties.src,
       title: hastNode.properties.title,
       alt: hastNode.properties.alt,
     }),
@@ -154,6 +155,7 @@ const factorySpecs = {
     type: 'mark',
     selector: 'a',
     getAttrs: (hastNode) => ({
+      canonicalSrc: hastNode.properties.href,
       href: hastNode.properties.href,
       title: hastNode.properties.title,
     }),
@@ -182,6 +184,31 @@ const factorySpecs = {
   },
 };
 
+const resolveUrl = (url) => {
+  try {
+    return new URL(url, window.location.origin).toString();
+  } catch {
+    return null;
+  }
+};
+
+const attributeTransformer = {
+  attributes: ['href', 'src'],
+  transform: (url) => {
+    if (!url) {
+      return url;
+    }
+
+    /**
+     * Resolves a URL if provided. The URL is not resolved against
+     * the client origin initially to protect the URL protocol
+     * when it is available, for example, we want to preserve
+     * mailto and application-specific protocols
+     */
+    return resolveUrl(url);
+  },
+};
+
 export default () => {
   return {
     deserialize: async ({ schema, markdown }) => {
@@ -193,6 +220,7 @@ export default () => {
             factorySpecs,
             tree,
             wrappableTags,
+            attributeTransformer,
             markdown,
           }),
         skipRendering: ['footnoteReference', 'footnoteDefinition', 'code', 'definition'],
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index 97bad375aea1f..3f8019adcf96d 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -1,4 +1,5 @@
 import { uniq, isString, omit, isFunction } from 'lodash';
+import { removeLastSlashInUrlPath, removeUrlProtocol } from '../../lib/utils/url_utility';
 
 const defaultAttrs = {
   td: { colspan: 1, rowspan: 1, colwidth: null },
@@ -497,9 +498,7 @@ const linkType = (sourceMarkdown) => {
   return LINK_HTML;
 };
 
-const removeUrlProtocol = (url) => url.replace(/^\w+:\/?\/?/, '');
-
-const normalizeUrl = (url) => decodeURIComponent(removeUrlProtocol(url));
+const normalizeUrl = (url) => decodeURIComponent(removeLastSlashInUrlPath(removeUrlProtocol(url)));
 
 /**
  * Validates that the provided URL is well-formed
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index 597fa49120b7c..ca90eee69c7e3 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -669,3 +669,27 @@ export function constructWebIDEPath({
     webIDEUrl(`/${sourceProjectFullPath}/merge_requests/${iid}`),
   );
 }
+
+/**
+ * Examples
+ *
+ * http://gitlab.com => gitlab.com
+ * https://gitlab.com => gitlab.com
+ *
+ * @param {String} url
+ * @returns A url without a protocol / scheme
+ */
+export const removeUrlProtocol = (url) => url.replace(/^\w+:\/?\/?/, '');
+
+/**
+ * Examples
+ *
+ * https://www.gitlab.com/path/ => https://www.gitlab.com/path
+ * https://www.gitlab.com/?query=search => https://www.gitlab.com?query=search
+ * https://www.gitlab.com/#fragment => https://www.gitlab.com#fragment
+ *
+ * @param {String} url
+ * @returns A URL that does not have a path that ends with slash
+ */
+export const removeLastSlashInUrlPath = (url) =>
+  url.replace(/\/$/, '').replace(/\/(\?|#){1}([^/]*)$/, '$1$2');
diff --git a/glfm_specification/example_snapshots/html.yml b/glfm_specification/example_snapshots/html.yml
index 105a0d26409f9..f89f03ecc31e4 100644
--- a/glfm_specification/example_snapshots/html.yml
+++ b/glfm_specification/example_snapshots/html.yml
@@ -1682,7 +1682,7 @@
   static: |-
     <div><a href="bar">*foo*</a></div>
   wysiwyg: |-
-    <div><p><a target="_blank" rel="noopener noreferrer nofollow" href="bar">*foo*</a></p></div>
+    <div><p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/bar" canonicalsrc="bar">*foo*</a></p></div>
 04_06__leaf_blocks__html_blocks__013:
   canonical: |
     <table><tr><td>
@@ -1723,7 +1723,7 @@
     *bar*
     </a>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo">
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo" canonicalsrc="foo">
     *bar*
     </a></p>
 04_06__leaf_blocks__html_blocks__016:
@@ -2065,7 +2065,7 @@
     baz</a></p>
   wysiwyg: |-
     <p>Foo
-    <a target="_blank" rel="noopener noreferrer nofollow" href="bar">
+    <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/bar" canonicalsrc="bar">
     baz</a></p>
 04_06__leaf_blocks__html_blocks__040:
   canonical: |
@@ -2145,7 +2145,7 @@
     <p data-sourcepos="3:1-3:5" dir="auto"><a href="/url" title="title">foo</a></p>
   wysiwyg: |-
     <pre>[foo]: /url "title"</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__002:
   canonical: |
     <p><a href="/url" title="the title">foo</a></p>
@@ -2153,7 +2153,7 @@
     <p data-sourcepos="5:1-5:5" dir="auto"><a href="/url" title="the title">foo</a></p>
   wysiwyg: |-
     <pre>[foo]: /url "the title"</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="the title">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="the title" canonicalsrc="/url">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__003:
   canonical: |
     <p><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
@@ -2161,7 +2161,7 @@
     <p data-sourcepos="3:1-3:11" dir="auto"><a href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
   wysiwyg: |-
     <pre>[foo*bar\]]: my_(url) "title (with parens)"</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="my_(url)" title="title (with parens)">Foo*bar]</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/my_(url)" title="title (with parens)" canonicalsrc="my_(url)">Foo*bar]</a></p>
 04_07__leaf_blocks__link_reference_definitions__004:
   canonical: |
     <p><a href="my%20url" title="title">Foo bar</a></p>
@@ -2169,7 +2169,7 @@
     <p data-sourcepos="5:1-5:9" dir="auto"><a href="my%20url" title="title">Foo bar</a></p>
   wysiwyg: |-
     <pre>[foo bar]: my url "title"</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="my%20url" title="title">Foo bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/my%20url" title="title" canonicalsrc="my%20url">Foo bar</a></p>
 04_07__leaf_blocks__link_reference_definitions__005:
   canonical: |
     <p><a href="/url" title="
@@ -2189,11 +2189,11 @@
     line1
     line2
     "</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="
     title
     line1
     line2
-    ">foo</a></p>
+    " canonicalsrc="/url">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__006:
   canonical: |
     <p>[foo]: /url 'title</p>
@@ -2214,7 +2214,7 @@
     <p data-sourcepos="4:1-4:5" dir="auto"><a href="/url">foo</a></p>
   wysiwyg: |-
     <pre>[foo]: /url</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__008:
   canonical: |
     <p>[foo]:</p>
@@ -2232,7 +2232,7 @@
     <p data-sourcepos="3:1-3:5" dir="auto"><a href="">foo</a></p>
   wysiwyg: |-
     <pre>[foo]: </pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="" canonicalsrc="">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__010:
   canonical: |
     <p>[foo]: <bar>(baz)</p>
@@ -2250,14 +2250,14 @@
     <p data-sourcepos="3:1-3:5" dir="auto"><a href="/url%5Cbar*baz" title='foo"bar\baz'>foo</a></p>
   wysiwyg: |-
     <pre>[foo]: /url\bar*baz "foo"bar\baz"</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url%5Cbar*baz" title="foo&quot;bar\baz">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url%5Cbar*baz" title="foo&quot;bar\baz" canonicalsrc="/url%5Cbar*baz">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__012:
   canonical: |
     <p><a href="url">foo</a></p>
   static: |-
     <p data-sourcepos="1:1-1:5" dir="auto"><a href="url">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="url">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="url">foo</a></p>
     <pre>[foo]: url</pre>
 04_07__leaf_blocks__link_reference_definitions__013:
   canonical: |
@@ -2265,7 +2265,7 @@
   static: |-
     <p data-sourcepos="1:1-1:5" dir="auto"><a href="first">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="first">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/first" canonicalsrc="first">foo</a></p>
     <pre>[foo]: first</pre>
     <pre>[foo]: second</pre>
 04_07__leaf_blocks__link_reference_definitions__014:
@@ -2275,7 +2275,7 @@
     <p data-sourcepos="3:1-3:5" dir="auto"><a href="/url">Foo</a></p>
   wysiwyg: |-
     <pre>[foo]: /url</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">Foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__015:
   canonical: |
     <p><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
@@ -2283,7 +2283,7 @@
     <p data-sourcepos="3:1-3:8" dir="auto"><a href="/%CF%86%CE%BF%CF%85">αγω</a></p>
   wysiwyg: |-
     <pre>[αγω]: /φου</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/%CF%86%CE%BF%CF%85">αγω</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/%CF%86%CE%BF%CF%85" canonicalsrc="/%CF%86%CE%BF%CF%85">αγω</a></p>
 04_07__leaf_blocks__link_reference_definitions__016:
   canonical: ""
   static: ""
@@ -2367,7 +2367,7 @@
     <p data-sourcepos="3:3-3:5">bar</p>
     </blockquote>
   wysiwyg: |-
-    <h1><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Foo</a></h1>
+    <h1><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">Foo</a></h1>
     <pre>[foo]: /url</pre>
     <blockquote multiline="false"><p>bar</p></blockquote>
 04_07__leaf_blocks__link_reference_definitions__024:
@@ -2381,7 +2381,7 @@
   wysiwyg: |-
     <pre>[foo]: /url</pre>
     <h1>bar</h1>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__025:
   canonical: |
     <p>===
@@ -2392,7 +2392,7 @@
   wysiwyg: |-
     <pre>[foo]: /url</pre>
     <p>===
-    <a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
+    <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo</a></p>
 04_07__leaf_blocks__link_reference_definitions__026:
   canonical: |
     <p><a href="/foo-url" title="foo">foo</a>,
@@ -2406,9 +2406,9 @@
     <pre>[foo]: /foo-url "foo"</pre>
     <pre>[bar]: /bar-url "bar"</pre>
     <pre>[baz]: /baz-url</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/foo-url" title="foo">foo</a>,
-    <a target="_blank" rel="noopener noreferrer nofollow" href="/bar-url" title="bar">bar</a>,
-    <a target="_blank" rel="noopener noreferrer nofollow" href="/baz-url">baz</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo-url" title="foo" canonicalsrc="/foo-url">foo</a>,
+    <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/bar-url" title="bar" canonicalsrc="/bar-url">bar</a>,
+    <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/baz-url" canonicalsrc="/baz-url">baz</a></p>
 04_07__leaf_blocks__link_reference_definitions__027:
   canonical: |
     <p><a href="/url">foo</a></p>
@@ -2419,7 +2419,7 @@
     <blockquote data-sourcepos="3:1-3:13" dir="auto">
     </blockquote>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo</a></p>
     <blockquote multiline="false"><pre>[foo]: /url</pre></blockquote>
 04_07__leaf_blocks__link_reference_definitions__028:
   canonical: ""
@@ -4883,7 +4883,7 @@
   static: |-
     <p data-sourcepos="1:1-1:28" dir="auto"><a href="http://example.com?find=%5C*" rel="nofollow noreferrer noopener" target="_blank">http://example.com?find=\*</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?find=%5C*" canonicalsrc="http://example.com?find=%5C*">http://example.com?find=\*</a></p>
 06_02__inlines__backslash_escapes__010:
   canonical: |
     <a href="/bar\/)">
@@ -4897,14 +4897,14 @@
   static: |-
     <p data-sourcepos="1:1-1:23" dir="auto"><a href="/bar*" title="ti*tle">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/bar*" title="ti*tle">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/bar*" title="ti*tle" canonicalsrc="/bar*">foo</a></p>
 06_02__inlines__backslash_escapes__012:
   canonical: |
     <p><a href="/bar*" title="ti*tle">foo</a></p>
   static: |-
     <p data-sourcepos="1:1-1:5" dir="auto"><a href="/bar*" title="ti*tle">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/bar*" title="ti*tle">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/bar*" title="ti*tle" canonicalsrc="/bar*">foo</a></p>
     <pre>[foo]: /bar* "ti*tle"</pre>
 06_02__inlines__backslash_escapes__013:
   canonical: |
@@ -4987,14 +4987,14 @@
   static: |-
     <p data-sourcepos="1:1-1:37" dir="auto"><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/f%C3%B6%C3%B6" title="föö" canonicalsrc="/f%C3%B6%C3%B6">foo</a></p>
 06_03__inlines__entity_and_numeric_character_references__009:
   canonical: |
     <p><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
   static: |-
     <p data-sourcepos="1:1-1:5" dir="auto"><a href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/f%C3%B6%C3%B6" title="föö">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/f%C3%B6%C3%B6" title="föö" canonicalsrc="/f%C3%B6%C3%B6">foo</a></p>
     <pre>[foo]: /föö "föö"</pre>
 06_03__inlines__entity_and_numeric_character_references__010:
   canonical: |
@@ -5193,7 +5193,7 @@
   static: |-
     <p data-sourcepos="1:1-1:13" dir="auto"><a href="%60" rel="nofollow noreferrer noopener" target="_blank">`</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="`">`</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/%60" canonicalsrc="`">`</a></p>
 06_04__inlines__code_spans__018:
   canonical: |
     <p><code>&lt;http://foo.bar.</code>baz&gt;`</p>
@@ -5207,7 +5207,7 @@
   static: |-
     <p data-sourcepos="1:1-1:22" dir="auto"><a href="http://foo.bar.%60baz" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar.`baz</a>`</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar.`baz/" canonicalsrc="http://foo.bar.%60baz">http://foo.bar.`baz</a>`</p>
 06_04__inlines__code_spans__020:
   canonical: |
     <p>```foo``</p>
@@ -5615,7 +5615,7 @@
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto"><em>foo <a href="/url">bar</a></em></p>
   wysiwyg: |-
-    <p><em>foo </em><a target="_blank" rel="noopener noreferrer nofollow" href="/url"><em>bar</em></a></p>
+    <p><em>foo </em><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url"><em>bar</em></a></p>
 06_05__inlines__emphasis_and_strong_emphasis__055:
   canonical: |
     <p><em>foo
@@ -5723,7 +5723,7 @@
   static: |-
     <p data-sourcepos="1:1-1:19" dir="auto"><em>foo <a href="/url"><em>bar</em></a></em></p>
   wysiwyg: |-
-    <p><em>foo </em><a target="_blank" rel="noopener noreferrer nofollow" href="/url"><em>bar</em></a></p>
+    <p><em>foo </em><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url"><em>bar</em></a></p>
 06_05__inlines__emphasis_and_strong_emphasis__070:
   canonical: |
     <p>** is not an empty emphasis</p>
@@ -5744,7 +5744,7 @@
   static: |-
     <p data-sourcepos="1:1-1:19" dir="auto"><strong>foo <a href="/url">bar</a></strong></p>
   wysiwyg: |-
-    <p><strong>foo </strong><a target="_blank" rel="noopener noreferrer nofollow" href="/url"><strong>bar</strong></a></p>
+    <p><strong>foo </strong><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url"><strong>bar</strong></a></p>
 06_05__inlines__emphasis_and_strong_emphasis__073:
   canonical: |
     <p><strong>foo
@@ -5827,7 +5827,7 @@
   static: |-
     <p data-sourcepos="1:1-1:21" dir="auto"><strong>foo <a href="/url"><em>bar</em></a></strong></p>
   wysiwyg: |-
-    <p><strong>foo </strong><a target="_blank" rel="noopener noreferrer nofollow" href="/url"><strong><em>bar</em></strong></a></p>
+    <p><strong>foo </strong><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url"><strong><em>bar</em></strong></a></p>
 06_05__inlines__emphasis_and_strong_emphasis__084:
   canonical: |
     <p>__ is not an empty emphasis</p>
@@ -6107,21 +6107,21 @@
   static: |-
     <p data-sourcepos="1:1-1:13" dir="auto">*<a href="/url">bar*</a></p>
   wysiwyg: |-
-    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/url">bar*</a></p>
+    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">bar*</a></p>
 06_05__inlines__emphasis_and_strong_emphasis__124:
   canonical: |
     <p>_foo <a href="/url">bar_</a></p>
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto">_foo <a href="/url">bar_</a></p>
   wysiwyg: |-
-    <p>_foo <a target="_blank" rel="noopener noreferrer nofollow" href="/url">bar_</a></p>
+    <p>_foo <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">bar_</a></p>
 06_05__inlines__emphasis_and_strong_emphasis__125:
   canonical: |
     <p>*<img src="foo" title="*"/></p>
   static: |-
     <p data-sourcepos="1:1-1:27" dir="auto">*<a class="no-attachment-icon" href="foo" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" title="*" decoding="async" class="lazy" data-src="foo"></a></p>
   wysiwyg: |-
-    <p>*<img src="foo" title="*"></p>
+    <p>*<img src="http://test.host/foo" title="*" data-canonical-src="foo"></p>
 06_05__inlines__emphasis_and_strong_emphasis__126:
   canonical: |
     <p>**<a href="**"></p>
@@ -6156,14 +6156,14 @@
   static: |-
     <p data-sourcepos="1:1-1:25" dir="auto">**a<a href="http://foo.bar/?q=**" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar/?q=**</a></p>
   wysiwyg: |-
-    <p>**a<a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
+    <p>**a<a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/?q=**" canonicalsrc="http://foo.bar/?q=**">http://foo.bar/?q=**</a></p>
 06_05__inlines__emphasis_and_strong_emphasis__131:
   canonical: |
     <p>__a<a href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
   static: |-
     <p data-sourcepos="1:1-1:25" dir="auto">__a<a href="http://foo.bar/?q=__" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar/?q=__</a></p>
   wysiwyg: |-
-    <p>__a<a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
+    <p>__a<a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/?q=__" canonicalsrc="http://foo.bar/?q=__">http://foo.bar/?q=__</a></p>
 06_06__inlines__strikethrough_extension__001:
   canonical: |
     <p><del>Hi</del> Hello, world!</p>
@@ -6187,28 +6187,28 @@
   static: |-
     <p data-sourcepos="1:1-1:20" dir="auto"><a href="/uri" title="title">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri" title="title">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" title="title" canonicalsrc="/uri">link</a></p>
 06_07__inlines__links__002:
   canonical: |
     <p><a href="/uri">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:12" dir="auto"><a href="/uri">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link</a></p>
 06_07__inlines__links__003:
   canonical: |
     <p><a href="">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:8" dir="auto"><a href="">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="" canonicalsrc="">link</a></p>
 06_07__inlines__links__004:
   canonical: |
     <p><a href="">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:10" dir="auto"><a href="">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="" canonicalsrc="">link</a></p>
 06_07__inlines__links__005:
   canonical: |
     <p>[link](/my uri)</p>
@@ -6222,7 +6222,7 @@
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto"><a href="/my%20uri">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/my%20uri">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/my%20uri" canonicalsrc="/my%20uri">link</a></p>
 06_07__inlines__links__007:
   canonical: |
     <p>[link](foo
@@ -6247,7 +6247,7 @@
   static: |-
     <p data-sourcepos="1:1-1:10" dir="auto"><a href="b)c">a</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="b)c">a</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/b)c" canonicalsrc="b)c">a</a></p>
 06_07__inlines__links__010:
   canonical: |
     <p>[link](&lt;foo&gt;)</p>
@@ -6274,35 +6274,35 @@
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto"><a href="(foo)">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="(foo)">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/(foo)" canonicalsrc="(foo)">link</a></p>
 06_07__inlines__links__013:
   canonical: |
     <p><a href="foo(and(bar))">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:21" dir="auto"><a href="foo(and(bar))">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo(and(bar))">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo(and(bar))" canonicalsrc="foo(and(bar))">link</a></p>
 06_07__inlines__links__014:
   canonical: |
     <p><a href="foo(and(bar)">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:23" dir="auto"><a href="foo(and(bar)">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo(and(bar)">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo(and(bar)" canonicalsrc="foo(and(bar)">link</a></p>
 06_07__inlines__links__015:
   canonical: |
     <p><a href="foo(and(bar)">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:22" dir="auto"><a href="foo(and(bar)">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo(and(bar)">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo(and(bar)" canonicalsrc="foo(and(bar)">link</a></p>
 06_07__inlines__links__016:
   canonical: |
     <p><a href="foo):">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto"><a>link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo):">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo):" canonicalsrc="foo):">link</a></p>
 06_07__inlines__links__017:
   canonical: |
     <p><a href="#fragment">link</a></p>
@@ -6313,30 +6313,30 @@
     <p data-sourcepos="3:1-3:35" dir="auto"><a href="http://example.com#fragment" rel="nofollow noreferrer noopener" target="_blank">link</a></p>
     <p data-sourcepos="5:1-5:37" dir="auto"><a href="http://example.com?foo=3#frag" rel="nofollow noreferrer noopener" target="_blank">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="#fragment">link</a></p>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com#fragment">link</a></p>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com?foo=3#frag">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/#fragment" canonicalsrc="#fragment">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/#fragment" canonicalsrc="http://example.com#fragment">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?foo=3#frag" canonicalsrc="http://example.com?foo=3#frag">link</a></p>
 06_07__inlines__links__018:
   canonical: |
     <p><a href="foo%5Cbar">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto"><a href="foo%5Cbar">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo%5Cbar">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo%5Cbar" canonicalsrc="foo%5Cbar">link</a></p>
 06_07__inlines__links__019:
   canonical: |
     <p><a href="foo%20b%C3%A4">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:21" dir="auto"><a href="foo%20b%C3%A4">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="foo%20b%C3%A4">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/foo%20b%C3%A4" canonicalsrc="foo%20b%C3%A4">link</a></p>
 06_07__inlines__links__020:
   canonical: |
     <p><a href="%22title%22">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto"><a href="%22title%22">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="%22title%22">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/%22title%22" canonicalsrc="%22title%22">link</a></p>
 06_07__inlines__links__021:
   canonical: |
     <p><a href="/url" title="title">link</a>
@@ -6347,21 +6347,21 @@
     <a href="/url" title="title">link</a>
     <a href="/url" title="title">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">linklinklink</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">linklinklink</a></p>
 06_07__inlines__links__022:
   canonical: |
     <p><a href="/url" title="title &quot;&quot;">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:29" dir="auto"><a href="/url" title='title ""'>link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title &quot;&quot;">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title &quot;&quot;" canonicalsrc="/url">link</a></p>
 06_07__inlines__links__023:
   canonical: |
     <p><a href="/url%C2%A0%22title%22">link</a></p>
   static: |-
     <p data-sourcepos="1:1-1:21" dir="auto"><a href="/url%C2%A0%22title%22">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url%C2%A0%22title%22">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url%C2%A0%22title%22" canonicalsrc="/url%C2%A0%22title%22">link</a></p>
 06_07__inlines__links__024:
   canonical: |
     <p>[link](/url &quot;title &quot;and&quot; title&quot;)</p>
@@ -6375,14 +6375,14 @@
   static: |-
     <p data-sourcepos="1:1-1:32" dir="auto"><a href="/url" title='title "and" title'>link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title &quot;and&quot; title">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title &quot;and&quot; title" canonicalsrc="/url">link</a></p>
 06_07__inlines__links__026:
   canonical: |
     <p><a href="/uri" title="title">link</a></p>
   static: |-
     <p data-sourcepos="1:1-2:12" dir="auto"><a href="/uri" title="title">link</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri" title="title">link</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" title="title" canonicalsrc="/uri">link</a></p>
 06_07__inlines__links__027:
   canonical: |
     <p>[link] (/uri)</p>
@@ -6396,7 +6396,7 @@
   static: |-
     <p data-sourcepos="1:1-1:24" dir="auto"><a href="/uri">link [foo [bar]]</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [foo [bar]]</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link [foo [bar]]</a></p>
 06_07__inlines__links__029:
   canonical: |
     <p>[link] bar](/uri)</p>
@@ -6410,63 +6410,63 @@
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto">[link <a href="/uri">bar</a></p>
   wysiwyg: |-
-    <p>[link <a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar</a></p>
+    <p>[link <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">bar</a></p>
 06_07__inlines__links__031:
   canonical: |
     <p><a href="/uri">link [bar</a></p>
   static: |-
     <p data-sourcepos="1:1-1:18" dir="auto"><a href="/uri">link [bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link [bar</a></p>
 06_07__inlines__links__032:
   canonical: |
     <p><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
   static: |-
     <p data-sourcepos="1:1-1:30" dir="auto"><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link <em>foo </em><strong><em>bar<code>#</code></em></strong></a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link <em>foo </em><strong><em>bar<code>#</code></em></strong></a></p>
 06_07__inlines__links__033:
   canonical: |
     <p><a href="/uri"><img src="moon.jpg" alt="moon" /></a></p>
   static: |-
     <p data-sourcepos="1:1-1:25" dir="auto"><a href="/uri"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="moon" decoding="async" class="lazy" data-src="moon.jpg"></a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><img src="moon.jpg" alt="moon"></a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri"><img src="http://test.host/moon.jpg" alt="moon" data-canonical-src="moon.jpg"></a></p>
 06_07__inlines__links__034:
   canonical: |
     <p>[foo <a href="/uri">bar</a>](/uri)</p>
   static: |-
     <p data-sourcepos="1:1-1:23" dir="auto">[foo <a href="/uri">bar</a>](/uri)</p>
   wysiwyg: |-
-    <p>[foo <a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar</a>](/uri)</p>
+    <p>[foo <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">bar</a>](/uri)</p>
 06_07__inlines__links__035:
   canonical: |
     <p>[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
   static: |-
     <p data-sourcepos="1:1-1:37" dir="auto">[foo <em>[bar <a href="/uri">baz</a>](/uri)</em>](/uri)</p>
   wysiwyg: |-
-    <p>[foo <em>[bar </em><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><em>baz</em></a><em>](/uri)</em>](/uri)</p>
+    <p>[foo <em>[bar </em><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri"><em>baz</em></a><em>](/uri)</em>](/uri)</p>
 06_07__inlines__links__036:
   canonical: |
     <p><img src="uri3" alt="[foo](uri2)" /></p>
   static: |-
     <p data-sourcepos="1:1-1:28" dir="auto"><a class="no-attachment-icon" href="uri3" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="[foo](uri2)" decoding="async" class="lazy" data-src="uri3"></a></p>
   wysiwyg: |-
-    <p><img src="uri3" alt="[foo](uri2)"></p>
+    <p><img src="http://test.host/uri3" alt="[foo](uri2)" data-canonical-src="uri3"></p>
 06_07__inlines__links__037:
   canonical: |
     <p>*<a href="/uri">foo*</a></p>
   static: |-
     <p data-sourcepos="1:1-1:13" dir="auto">*<a href="/uri">foo*</a></p>
   wysiwyg: |-
-    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo*</a></p>
+    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">foo*</a></p>
 06_07__inlines__links__038:
   canonical: |
     <p><a href="baz*">foo *bar</a></p>
   static: |-
     <p data-sourcepos="1:1-1:16" dir="auto"><a href="baz*">foo *bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="baz*">foo *bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/baz*" canonicalsrc="baz*">foo *bar</a></p>
 06_07__inlines__links__039:
   canonical: |
     <p><em>foo [bar</em> baz]</p>
@@ -6494,14 +6494,14 @@
   static: |-
     <p data-sourcepos="1:1-1:39" dir="auto">[foo<a href="http://example.com/?search=%5D(uri)" rel="nofollow noreferrer noopener" target="_blank">http://example.com/?search=](uri)</a></p>
   wysiwyg: |-
-    <p>[foo<a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
+    <p>[foo<a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?search=%5D(uri)" canonicalsrc="http://example.com/?search=%5D(uri)">http://example.com/?search=](uri)</a></p>
 06_07__inlines__links__043:
   canonical: |
     <p><a href="/url" title="title">foo</a></p>
   static: |-
     <p data-sourcepos="1:1-1:10" dir="auto"><a href="/url" title="title">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a></p>
     <pre>[bar]: /url "title"</pre>
 06_07__inlines__links__044:
   canonical: |
@@ -6509,7 +6509,7 @@
   static: |-
     <p data-sourcepos="1:1-1:23" dir="auto"><a href="/uri">link [foo [bar]]</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [foo [bar]]</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link [foo [bar]]</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__045:
   canonical: |
@@ -6517,7 +6517,7 @@
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto"><a href="/uri">link [bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link [bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link [bar</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__046:
   canonical: |
@@ -6525,7 +6525,7 @@
   static: |-
     <p data-sourcepos="1:1-1:29" dir="auto"><a href="/uri">link <em>foo <strong>bar</strong> <code>#</code></em></a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">link <em>foo </em><strong><em>bar<code>#</code></em></strong></a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">link <em>foo </em><strong><em>bar<code>#</code></em></strong></a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__047:
   canonical: |
@@ -6533,7 +6533,7 @@
   static: |-
     <p data-sourcepos="1:1-1:24" dir="auto"><a href="/uri"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="moon" decoding="async" class="lazy" data-src="moon.jpg"></a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><img src="moon.jpg" alt="moon"></a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri"><img src="http://test.host/moon.jpg" alt="moon" data-canonical-src="moon.jpg"></a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__048:
   canonical: |
@@ -6541,7 +6541,7 @@
   static: |-
     <p data-sourcepos="1:1-1:22" dir="auto">[foo <a href="/uri">bar</a>]<a href="/uri">ref</a></p>
   wysiwyg: |-
-    <p>[foo <a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar</a>]<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">ref</a></p>
+    <p>[foo <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">bar</a>]<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">ref</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__049:
   canonical: |
@@ -6549,7 +6549,7 @@
   static: |-
     <p data-sourcepos="1:1-1:27" dir="auto">[foo <em>bar <a href="/uri">baz</a></em>]<a href="/uri">ref</a></p>
   wysiwyg: |-
-    <p>[foo <em>bar </em><a target="_blank" rel="noopener noreferrer nofollow" href="/uri"><em>baz</em></a>]<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">ref</a></p>
+    <p>[foo <em>bar </em><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri"><em>baz</em></a>]<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">ref</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__050:
   canonical: |
@@ -6557,7 +6557,7 @@
   static: |-
     <p data-sourcepos="1:1-1:12" dir="auto">*<a href="/uri">foo*</a></p>
   wysiwyg: |-
-    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo*</a></p>
+    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">foo*</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__051:
   canonical: |
@@ -6565,7 +6565,7 @@
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto"><a href="/uri">foo *bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo *bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">foo *bar</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__052:
   canonical: |
@@ -6589,7 +6589,7 @@
   static: |-
     <p data-sourcepos="1:1-1:39" dir="auto">[foo<a href="http://example.com/?search=%5D%5Bref%5D" rel="nofollow noreferrer noopener" target="_blank">http://example.com/?search=][ref]</a></p>
   wysiwyg: |-
-    <p>[foo<a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
+    <p>[foo<a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/?search=%5D%5Bref%5D" canonicalsrc="http://example.com/?search=%5D%5Bref%5D">http://example.com/?search=][ref]</a></p>
     <pre>[ref]: /uri</pre>
 06_07__inlines__links__055:
   canonical: |
@@ -6597,7 +6597,7 @@
   static: |-
     <p data-sourcepos="1:1-1:10" dir="auto"><a href="/url" title="title">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a></p>
     <pre>[bar]: /url "title"</pre>
 06_07__inlines__links__056:
   canonical: |
@@ -6605,7 +6605,7 @@
   static: |-
     <p data-sourcepos="1:1-1:47" dir="auto"><a href="/url">Толпой</a> is a Russian word.</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Толпой</a> is a Russian word.</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">Толпой</a> is a Russian word.</p>
     <pre>[толпой]: /url</pre>
 06_07__inlines__links__057:
   canonical: |
@@ -6614,14 +6614,14 @@
     <p data-sourcepos="4:1-4:14" dir="auto"><a href="/url">Baz</a></p>
   wysiwyg: |-
     <pre>[foo bar]: /url</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">Baz</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">Baz</a></p>
 06_07__inlines__links__058:
   canonical: |
     <p>[foo] <a href="/url" title="title">bar</a></p>
   static: |-
     <p data-sourcepos="1:1-1:11" dir="auto">[foo] <a href="/url" title="title">bar</a></p>
   wysiwyg: |-
-    <p>[foo] <a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">bar</a></p>
+    <p>[foo] <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">bar</a></p>
     <pre>[bar]: /url "title"</pre>
 06_07__inlines__links__059:
   canonical: |
@@ -6632,7 +6632,7 @@
     <a href="/url" title="title">bar</a></p>
   wysiwyg: |-
     <p>[foo]
-    <a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">bar</a></p>
+    <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">bar</a></p>
     <pre>[bar]: /url "title"</pre>
 06_07__inlines__links__060:
   canonical: |
@@ -6642,7 +6642,7 @@
   wysiwyg: |-
     <pre>[foo]: /url1</pre>
     <pre>[foo]: /url2</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url1" canonicalsrc="/url1">bar</a></p>
 06_07__inlines__links__061:
   canonical: |
     <p>[bar][foo!]</p>
@@ -6687,7 +6687,7 @@
   static: |-
     <p data-sourcepos="1:1-1:12" dir="auto"><a href="/uri">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">foo</a></p>
     <pre>[ref\[]: /uri</pre>
 06_07__inlines__links__066:
   canonical: |
@@ -6696,7 +6696,7 @@
     <p data-sourcepos="3:1-3:7" dir="auto"><a href="/uri">bar\</a></p>
   wysiwyg: |-
     <pre>[bar\\]: /uri</pre>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/uri">bar\</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/uri" canonicalsrc="/uri">bar\</a></p>
 06_07__inlines__links__067:
   canonical: |
     <p>[]</p>
@@ -6729,7 +6729,7 @@
   static: |-
     <p data-sourcepos="1:1-1:7" dir="auto"><a href="/url" title="title">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a></p>
     <pre>[foo]: /url "title"</pre>
 06_07__inlines__links__070:
   canonical: |
@@ -6737,7 +6737,7 @@
   static: |-
     <p data-sourcepos="1:1-1:13" dir="auto"><a href="/url" title="title"><em>foo</em> bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url"><em>foo</em> bar</a></p>
     <pre>[*foo* bar]: /url "title"</pre>
 06_07__inlines__links__071:
   canonical: |
@@ -6745,7 +6745,7 @@
   static: |-
     <p data-sourcepos="1:1-1:7" dir="auto"><a href="/url" title="title">Foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">Foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">Foo</a></p>
     <pre>[foo]: /url "title"</pre>
 06_07__inlines__links__072:
   canonical: |
@@ -6755,7 +6755,7 @@
     <p data-sourcepos="1:1-2:2" dir="auto"><a href="/url" title="title">foo</a>
     []</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a>
     []</p>
     <pre>[foo]: /url "title"</pre>
 06_07__inlines__links__073:
@@ -6764,7 +6764,7 @@
   static: |-
     <p data-sourcepos="1:1-1:5" dir="auto"><a href="/url" title="title">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a></p>
     <pre>[foo]: /url "title"</pre>
 06_07__inlines__links__074:
   canonical: |
@@ -6772,7 +6772,7 @@
   static: |-
     <p data-sourcepos="1:1-1:11" dir="auto"><a href="/url" title="title"><em>foo</em> bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url"><em>foo</em> bar</a></p>
     <pre>[*foo* bar]: /url "title"</pre>
 06_07__inlines__links__075:
   canonical: |
@@ -6780,7 +6780,7 @@
   static: |-
     <p data-sourcepos="1:1-1:13" dir="auto">[<a href="/url" title="title"><em>foo</em> bar</a>]</p>
   wysiwyg: |-
-    <p>[<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title"><em>foo</em> bar</a>]</p>
+    <p>[<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url"><em>foo</em> bar</a>]</p>
     <pre>[*foo* bar]: /url "title"</pre>
 06_07__inlines__links__076:
   canonical: |
@@ -6788,7 +6788,7 @@
   static: |-
     <p data-sourcepos="1:1-1:11" dir="auto">[[bar <a href="/url">foo</a></p>
   wysiwyg: |-
-    <p>[[bar <a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a></p>
+    <p>[[bar <a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo</a></p>
     <pre>[foo]: /url</pre>
 06_07__inlines__links__077:
   canonical: |
@@ -6796,7 +6796,7 @@
   static: |-
     <p data-sourcepos="1:1-1:5" dir="auto"><a href="/url" title="title">Foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">Foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">Foo</a></p>
     <pre>[foo]: /url "title"</pre>
 06_07__inlines__links__078:
   canonical: |
@@ -6804,7 +6804,7 @@
   static: |-
     <p data-sourcepos="1:1-1:9" dir="auto"><a href="/url">foo</a> bar</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo</a> bar</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo</a> bar</p>
     <pre>[foo]: /url</pre>
 06_07__inlines__links__079:
   canonical: |
@@ -6821,14 +6821,14 @@
     <p data-sourcepos="3:1-3:7" dir="auto">*<a href="/url">foo*</a></p>
   wysiwyg: |-
     <pre>[foo*]: /url</pre>
-    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="/url">foo*</a></p>
+    <p>*<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">foo*</a></p>
 06_07__inlines__links__081:
   canonical: |
     <p><a href="/url2">foo</a></p>
   static: |-
     <p data-sourcepos="1:1-1:10" dir="auto"><a href="/url2">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url2">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url2" canonicalsrc="/url2">foo</a></p>
     <pre>[foo]: /url1</pre>
     <pre>[bar]: /url2</pre>
 06_07__inlines__links__082:
@@ -6837,7 +6837,7 @@
   static: |-
     <p data-sourcepos="1:1-1:7" dir="auto"><a href="/url1">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url1" canonicalsrc="/url1">foo</a></p>
     <pre>[foo]: /url1</pre>
 06_07__inlines__links__083:
   canonical: |
@@ -6845,7 +6845,7 @@
   static: |-
     <p data-sourcepos="1:1-1:7" dir="auto"><a href="">foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="">foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="" canonicalsrc="">foo</a></p>
     <pre>[foo]: /url1</pre>
 06_07__inlines__links__084:
   canonical: |
@@ -6853,7 +6853,7 @@
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto"><a href="/url1">foo</a>(not a link)</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">foo</a>(not a link)</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url1" canonicalsrc="/url1">foo</a>(not a link)</p>
     <pre>[foo]: /url1</pre>
 06_07__inlines__links__085:
   canonical: |
@@ -6861,7 +6861,7 @@
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto">[foo]<a href="/url">bar</a></p>
   wysiwyg: |-
-    <p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="/url">bar</a></p>
+    <p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" canonicalsrc="/url">bar</a></p>
     <pre>[baz]: /url</pre>
 06_07__inlines__links__086:
   canonical: |
@@ -6869,7 +6869,7 @@
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto"><a href="/url2">foo</a><a href="/url1">baz</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="/url2">foo</a><a target="_blank" rel="noopener noreferrer nofollow" href="/url1">baz</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url2" canonicalsrc="/url2">foo</a><a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url1" canonicalsrc="/url1">baz</a></p>
     <pre>[baz]: /url1</pre>
     <pre>[bar]: /url2</pre>
 06_07__inlines__links__087:
@@ -6878,7 +6878,7 @@
   static: |-
     <p data-sourcepos="1:1-1:15" dir="auto">[foo]<a href="/url1">bar</a></p>
   wysiwyg: |-
-    <p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="/url1">bar</a></p>
+    <p>[foo]<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url1" canonicalsrc="/url1">bar</a></p>
     <pre>[baz]: /url1</pre>
     <pre>[foo]: /url2</pre>
 06_08__inlines__images__001:
@@ -6887,14 +6887,14 @@
   static: |-
     <p data-sourcepos="1:1-1:20" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo" title="title"></p>
+    <p><img src="http://test.host/url" alt="foo" title="title" data-canonical-src="/url"></p>
 06_08__inlines__images__002:
   canonical: |
     <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
   static: |-
     <p data-sourcepos="1:1-1:12" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
   wysiwyg: |-
-    <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
+    <p><img src="http://test.host/train.jpg" alt="foo bar" title="train &amp; tracks" data-canonical-src="train.jpg"></p>
     <pre>[foo *bar*]: train.jpg "train &amp; tracks"</pre>
 06_08__inlines__images__003:
   canonical: |
@@ -6902,21 +6902,21 @@
   static: |-
     <p data-sourcepos="1:1-1:26" dir="auto"><a class="no-attachment-icon" href="/url2" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" decoding="async" class="lazy" data-src="/url2"></a></p>
   wysiwyg: |-
-    <p><img src="/url2" alt="foo bar"></p>
+    <p><img src="http://test.host/url2" alt="foo bar" data-canonical-src="/url2"></p>
 06_08__inlines__images__004:
   canonical: |
     <p><img src="/url2" alt="foo bar" /></p>
   static: |-
     <p data-sourcepos="1:1-1:25" dir="auto"><a class="no-attachment-icon" href="/url2" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" decoding="async" class="lazy" data-src="/url2"></a></p>
   wysiwyg: |-
-    <p><img src="/url2" alt="foo bar"></p>
+    <p><img src="http://test.host/url2" alt="foo bar" data-canonical-src="/url2"></p>
 06_08__inlines__images__005:
   canonical: |
     <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks" /></p>
   static: |-
     <p data-sourcepos="1:1-1:14" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
   wysiwyg: |-
-    <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
+    <p><img src="http://test.host/train.jpg" alt="foo bar" title="train &amp; tracks" data-canonical-src="train.jpg"></p>
     <pre>[foo *bar*]: train.jpg "train &amp; tracks"</pre>
 06_08__inlines__images__006:
   canonical: |
@@ -6924,7 +6924,7 @@
   static: |-
     <p data-sourcepos="1:1-1:20" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="train &amp; tracks" decoding="async" class="lazy" data-src="train.jpg"></a></p>
   wysiwyg: |-
-    <p><img src="train.jpg" alt="foo bar" title="train &amp; tracks"></p>
+    <p><img src="http://test.host/train.jpg" alt="foo bar" title="train &amp; tracks" data-canonical-src="train.jpg"></p>
     <pre>[foobar]: train.jpg "train &amp; tracks"</pre>
 06_08__inlines__images__007:
   canonical: |
@@ -6932,35 +6932,35 @@
   static: |-
     <p data-sourcepos="1:1-1:17" dir="auto"><a class="no-attachment-icon" href="train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="train.jpg"></a></p>
   wysiwyg: |-
-    <p><img src="train.jpg" alt="foo"></p>
+    <p><img src="http://test.host/train.jpg" alt="foo" data-canonical-src="train.jpg"></p>
 06_08__inlines__images__008:
   canonical: |
     <p>My <img src="/path/to/train.jpg" alt="foo bar" title="title" /></p>
   static: |-
     <p data-sourcepos="1:1-1:45" dir="auto">My <a class="no-attachment-icon" href="/path/to/train.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/path/to/train.jpg"></a></p>
   wysiwyg: |-
-    <p>My <img src="/path/to/train.jpg" alt="foo bar" title="title"></p>
+    <p>My <img src="http://test.host/path/to/train.jpg" alt="foo bar" title="title" data-canonical-src="/path/to/train.jpg"></p>
 06_08__inlines__images__009:
   canonical: |
     <p><img src="url" alt="foo" /></p>
   static: |-
     <p data-sourcepos="1:1-1:13" dir="auto"><a class="no-attachment-icon" href="url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="url"></a></p>
   wysiwyg: |-
-    <p><img src="url" alt="foo"></p>
+    <p><img src="http://test.host/url" alt="foo" data-canonical-src="url"></p>
 06_08__inlines__images__010:
   canonical: |
     <p><img src="/url" alt="" /></p>
   static: |-
     <p data-sourcepos="1:1-1:9" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt=""></p>
+    <p><img src="http://test.host/url" alt="" data-canonical-src="/url"></p>
 06_08__inlines__images__011:
   canonical: |
     <p><img src="/url" alt="foo" /></p>
   static: |-
     <p data-sourcepos="1:1-1:11" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo"></p>
+    <p><img src="http://test.host/url" alt="foo" data-canonical-src="/url"></p>
     <pre>[bar]: /url</pre>
 06_08__inlines__images__012:
   canonical: |
@@ -6968,7 +6968,7 @@
   static: |-
     <p data-sourcepos="1:1-1:11" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo"></p>
+    <p><img src="http://test.host/url" alt="foo" data-canonical-src="/url"></p>
     <pre>[bar]: /url</pre>
 06_08__inlines__images__013:
   canonical: |
@@ -6976,7 +6976,7 @@
   static: |-
     <p data-sourcepos="1:1-1:8" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo" title="title"></p>
+    <p><img src="http://test.host/url" alt="foo" title="title" data-canonical-src="/url"></p>
     <pre>[foo]: /url "title"</pre>
 06_08__inlines__images__014:
   canonical: |
@@ -6984,7 +6984,7 @@
   static: |-
     <p data-sourcepos="1:1-1:14" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo bar" title="title"></p>
+    <p><img src="http://test.host/url" alt="foo bar" title="title" data-canonical-src="/url"></p>
     <pre>[*foo* bar]: /url "title"</pre>
 06_08__inlines__images__015:
   canonical: |
@@ -6992,7 +6992,7 @@
   static: |-
     <p data-sourcepos="1:1-1:8" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="Foo" title="title"></p>
+    <p><img src="http://test.host/url" alt="Foo" title="title" data-canonical-src="/url"></p>
     <pre>[foo]: /url "title"</pre>
 06_08__inlines__images__016:
   canonical: |
@@ -7002,7 +7002,7 @@
     <p data-sourcepos="1:1-2:2" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a>
     []</p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo" title="title">
+    <p><img src="http://test.host/url" alt="foo" title="title" data-canonical-src="/url">
     []</p>
     <pre>[foo]: /url "title"</pre>
 06_08__inlines__images__017:
@@ -7011,7 +7011,7 @@
   static: |-
     <p data-sourcepos="1:1-1:6" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo" title="title"></p>
+    <p><img src="http://test.host/url" alt="foo" title="title" data-canonical-src="/url"></p>
     <pre>[foo]: /url "title"</pre>
 06_08__inlines__images__018:
   canonical: |
@@ -7019,7 +7019,7 @@
   static: |-
     <p data-sourcepos="1:1-1:12" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="foo bar" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="foo bar" title="title"></p>
+    <p><img src="http://test.host/url" alt="foo bar" title="title" data-canonical-src="/url"></p>
     <pre>[*foo* bar]: /url "title"</pre>
 06_08__inlines__images__019:
   canonical: |
@@ -7037,7 +7037,7 @@
   static: |-
     <p data-sourcepos="1:1-1:6" dir="auto"><a class="no-attachment-icon" href="/url" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Foo" title="title" decoding="async" class="lazy" data-src="/url"></a></p>
   wysiwyg: |-
-    <p><img src="/url" alt="Foo" title="title"></p>
+    <p><img src="http://test.host/url" alt="Foo" title="title" data-canonical-src="/url"></p>
     <pre>[foo]: /url "title"</pre>
 06_08__inlines__images__021:
   canonical: |
@@ -7053,7 +7053,7 @@
   static: |-
     <p data-sourcepos="1:1-1:27" dir="auto"><span>!</span><a href="/url" title="title">foo</a></p>
   wysiwyg: |-
-    <p>!<a target="_blank" rel="noopener noreferrer nofollow" href="/url" title="title">foo</a></p>
+    <p>!<a target="_blank" rel="noopener noreferrer nofollow" href="http://test.host/url" title="title" canonicalsrc="/url">foo</a></p>
     <pre>[foo]: /url "title"</pre>
 06_09__inlines__autolinks__001:
   canonical: |
@@ -7061,91 +7061,91 @@
   static: |-
     <p data-sourcepos="1:1-1:20" dir="auto"><a href="http://foo.bar.baz" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar.baz</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar.baz">http://foo.bar.baz</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar.baz/" canonicalsrc="http://foo.bar.baz">http://foo.bar.baz</a></p>
 06_09__inlines__autolinks__002:
   canonical: |
     <p><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
   static: |-
     <p data-sourcepos="1:1-1:47" dir="auto"><a href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean" canonicalsrc="http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean">http://foo.bar.baz/test?q=hello&amp;id=22&amp;boolean</a></p>
 06_09__inlines__autolinks__003:
   canonical: |
     <p><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
   static: |-
     <p data-sourcepos="1:1-1:24" dir="auto"><a href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="irc://foo.bar:2233/baz" canonicalsrc="irc://foo.bar:2233/baz">irc://foo.bar:2233/baz</a></p>
 06_09__inlines__autolinks__004:
   canonical: |
     <p><a href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
   static: |-
     <p data-sourcepos="1:1-1:20" dir="auto"><a href="mailto:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:FOO@BAR.BAZ" canonicalsrc="MAILTO:FOO@BAR.BAZ">MAILTO:FOO@BAR.BAZ</a></p>
 06_09__inlines__autolinks__005:
   canonical: |
     <p><a href="a+b+c:d">a+b+c:d</a></p>
   static: |-
     <p data-sourcepos="1:1-1:9" dir="auto"><a href="a+b+c:d">a+b+c:d</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="a+b+c:d">a+b+c:d</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="a+b+c:d" canonicalsrc="a+b+c:d">a+b+c:d</a></p>
 06_09__inlines__autolinks__006:
   canonical: |
     <p><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
   static: |-
     <p data-sourcepos="1:1-1:26" dir="auto"><a href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="made-up-scheme://foo,bar" canonicalsrc="made-up-scheme://foo,bar">made-up-scheme://foo,bar</a></p>
 06_09__inlines__autolinks__007:
   canonical: |
     <p><a href="http://../">http://../</a></p>
   static: |-
     <p data-sourcepos="1:1-1:12" dir="auto"><a href="http://../" rel="nofollow noreferrer noopener" target="_blank">http://../</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://../">http://../</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://../" canonicalsrc="http://../">http://../</a></p>
 06_09__inlines__autolinks__008:
   canonical: |
     <p><a href="localhost:5001/foo">localhost:5001/foo</a></p>
   static: |-
     <p data-sourcepos="1:1-1:20" dir="auto"><a href="localhost:5001/foo">localhost:5001/foo</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="localhost:5001/foo">localhost:5001/foo</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="localhost:5001/foo" canonicalsrc="localhost:5001/foo">localhost:5001/foo</a></p>
 06_09__inlines__autolinks__009:
   canonical: |
     <p>&lt;http://foo.bar/baz bim&gt;</p>
   static: |-
     <p data-sourcepos="1:1-1:24" dir="auto">&lt;<a href="http://foo.bar/baz" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar/baz</a> bim&gt;</p>
   wysiwyg: |-
-    <p>&lt;<a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/baz">http://foo.bar/baz</a> bim&gt;</p>
+    <p>&lt;<a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/baz" canonicalsrc="http://foo.bar/baz">http://foo.bar/baz</a> bim&gt;</p>
 06_09__inlines__autolinks__010:
   canonical: |
     <p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
   static: |-
     <p data-sourcepos="1:1-1:24" dir="auto"><a href="http://example.com/%5C%5B%5C" rel="nofollow noreferrer noopener" target="_blank">http://example.com/\[\</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/%5C%5B%5C" canonicalsrc="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
 06_09__inlines__autolinks__011:
   canonical: |
     <p><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
   static: |-
     <p data-sourcepos="1:1-1:21" dir="auto"><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo@bar.example.com" canonicalsrc="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
 06_09__inlines__autolinks__012:
   canonical: |
     <p><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
   static: |-
     <p data-sourcepos="1:1-1:30" dir="auto"><a href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo+special@Bar.baz-bar0.com" canonicalsrc="mailto:foo+special@Bar.baz-bar0.com">foo+special@Bar.baz-bar0.com</a></p>
 06_09__inlines__autolinks__013:
   canonical: |
     <p>&lt;foo+@bar.example.com&gt;</p>
   static: |-
     <p data-sourcepos="1:1-1:23" dir="auto">&lt;<a href="mailto:foo+@bar.example.com">foo+@bar.example.com</a>&gt;</p>
   wysiwyg: |-
-    <p>&lt;<a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo+@bar.example.com">foo+@bar.example.com</a>&gt;</p>
+    <p>&lt;<a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo+@bar.example.com" canonicalsrc="mailto:foo+@bar.example.com">foo+@bar.example.com</a>&gt;</p>
 06_09__inlines__autolinks__014:
   canonical: |
     <p>&lt;&gt;</p>
@@ -7159,7 +7159,7 @@
   static: |-
     <p data-sourcepos="1:1-1:18" dir="auto">&lt; <a href="http://foo.bar" rel="nofollow noreferrer noopener" target="_blank">http://foo.bar</a> &gt;</p>
   wysiwyg: |-
-    <p>&lt; <a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar">http://foo.bar</a> &gt;</p>
+    <p>&lt; <a target="_blank" rel="noopener noreferrer nofollow" href="http://foo.bar/" canonicalsrc="http://foo.bar">http://foo.bar</a> &gt;</p>
 06_09__inlines__autolinks__016:
   canonical: |
     <p>&lt;m:abc&gt;</p>
@@ -7180,28 +7180,28 @@
   static: |-
     <p data-sourcepos="1:1-1:18" dir="auto"><a href="http://example.com" rel="nofollow noreferrer noopener" target="_blank">http://example.com</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com">http://example.com</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://example.com/" canonicalsrc="http://example.com">http://example.com</a></p>
 06_09__inlines__autolinks__019:
   canonical: |
     <p>foo@bar.example.com</p>
   static: |-
     <p data-sourcepos="1:1-1:19" dir="auto"><a href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo@bar.example.com" canonicalsrc="mailto:foo@bar.example.com">foo@bar.example.com</a></p>
 06_10__inlines__autolinks_extension__001:
   canonical: |
     <p><a href="http://www.commonmark.org">www.commonmark.org</a></p>
   static: |-
     <p data-sourcepos="1:1-1:18" dir="auto"><a href="http://www.commonmark.org" rel="nofollow noreferrer noopener" target="_blank">www.commonmark.org</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org">www.commonmark.org</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/" canonicalsrc="http://www.commonmark.org">www.commonmark.org</a></p>
 06_10__inlines__autolinks_extension__002:
   canonical: |
     <p>Visit <a href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
   static: |-
     <p data-sourcepos="1:1-1:51" dir="auto">Visit <a href="http://www.commonmark.org/help" rel="nofollow noreferrer noopener" target="_blank">www.commonmark.org/help</a> for more information.</p>
   wysiwyg: |-
-    <p>Visit <a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
+    <p>Visit <a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/help" canonicalsrc="http://www.commonmark.org/help">www.commonmark.org/help</a> for more information.</p>
 06_10__inlines__autolinks_extension__003:
   canonical: |
     <p>Visit <a href="http://www.commonmark.org">www.commonmark.org</a>.</p>
@@ -7210,8 +7210,8 @@
     <p data-sourcepos="1:1-1:25" dir="auto">Visit <a href="http://www.commonmark.org" rel="nofollow noreferrer noopener" target="_blank">www.commonmark.org</a>.</p>
     <p data-sourcepos="3:1-3:29" dir="auto">Visit <a href="http://www.commonmark.org/a.b" rel="nofollow noreferrer noopener" target="_blank">www.commonmark.org/a.b</a>.</p>
   wysiwyg: |-
-    <p>Visit <a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org">www.commonmark.org</a>.</p>
-    <p>Visit <a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
+    <p>Visit <a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/" canonicalsrc="http://www.commonmark.org">www.commonmark.org</a>.</p>
+    <p>Visit <a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/a.b" canonicalsrc="http://www.commonmark.org/a.b">www.commonmark.org/a.b</a>.</p>
 06_10__inlines__autolinks_extension__004:
   canonical: |
     <p><a href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
@@ -7224,17 +7224,17 @@
     <p data-sourcepos="5:1-5:43" dir="auto">(<a href="http://www.google.com/search?q=Markup+(business)" rel="nofollow noreferrer noopener" target="_blank">www.google.com/search?q=Markup+(business)</a>)</p>
     <p data-sourcepos="7:1-7:42" dir="auto">(<a href="http://www.google.com/search?q=Markup+(business)" rel="nofollow noreferrer noopener" target="_blank">www.google.com/search?q=Markup+(business)</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
-    <p>(<a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
-    <p>(<a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)" canonicalsrc="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)" canonicalsrc="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>))</p>
+    <p>(<a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)" canonicalsrc="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a>)</p>
+    <p>(<a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=Markup+(business)" canonicalsrc="http://www.google.com/search?q=Markup+(business)">www.google.com/search?q=Markup+(business)</a></p>
 06_10__inlines__autolinks_extension__005:
   canonical: |
     <p><a href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
   static: |-
     <p data-sourcepos="1:1-1:38" dir="auto"><a href="http://www.google.com/search?q=(business))+ok" rel="nofollow noreferrer noopener" target="_blank">www.google.com/search?q=(business))+ok</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=(business))+ok" canonicalsrc="http://www.google.com/search?q=(business))+ok">www.google.com/search?q=(business))+ok</a></p>
 06_10__inlines__autolinks_extension__006:
   canonical: |
     <p><a href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
@@ -7243,15 +7243,15 @@
     <p data-sourcepos="1:1-1:40" dir="auto"><a href="http://www.google.com/search?q=commonmark&amp;hl=en" rel="nofollow noreferrer noopener" target="_blank">www.google.com/search?q=commonmark&amp;hl=en</a></p>
     <p data-sourcepos="3:1-3:38" dir="auto"><a href="http://www.google.com/search?q=commonmark" rel="nofollow noreferrer noopener" target="_blank">www.google.com/search?q=commonmark</a>&amp;hl;</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=commonmark&amp;hl=en" canonicalsrc="http://www.google.com/search?q=commonmark&amp;hl=en">www.google.com/search?q=commonmark&amp;hl=en</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.google.com/search?q=commonmark" canonicalsrc="http://www.google.com/search?q=commonmark">www.google.com/search?q=commonmark</a>&amp;hl;</p>
 06_10__inlines__autolinks_extension__007:
   canonical: |
     <p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
   static: |-
     <p data-sourcepos="1:1-1:24" dir="auto"><a href="http://www.commonmark.org/he" rel="nofollow noreferrer noopener" target="_blank">www.commonmark.org/he</a>&lt;lp</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://www.commonmark.org/he" canonicalsrc="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
 06_10__inlines__autolinks_extension__008:
   canonical: |
     <p><a href="http://commonmark.org">http://commonmark.org</a></p>
@@ -7262,8 +7262,8 @@
     <p data-sourcepos="3:1-3:63" dir="auto">(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)" rel="nofollow noreferrer noopener" target="_blank">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
     <p data-sourcepos="5:1-5:48" dir="auto">Anonymous FTP is available at <a href="ftp://foo.bar.baz/">ftp://foo.bar.baz</a>.</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://commonmark.org">http://commonmark.org</a></p>
-    <p>(Visit <a target="_blank" rel="noopener noreferrer nofollow" href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="http://commonmark.org/" canonicalsrc="http://commonmark.org">http://commonmark.org</a></p>
+    <p>(Visit <a target="_blank" rel="noopener noreferrer nofollow" href="https://encrypted.google.com/search?q=Markup+(business)" canonicalsrc="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
     <p>Anonymous FTP is available at ftp://foo.bar.baz.</p>
 06_10__inlines__autolinks_extension__009:
   canonical: |
@@ -7271,14 +7271,14 @@
   static: |-
     <p data-sourcepos="1:1-1:11" dir="auto"><a href="mailto:foo@bar.baz">foo@bar.baz</a></p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo@bar.baz">foo@bar.baz</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:foo@bar.baz" canonicalsrc="mailto:foo@bar.baz">foo@bar.baz</a></p>
 06_10__inlines__autolinks_extension__010:
   canonical: |
     <p>hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
   static: |-
     <p data-sourcepos="1:1-1:66" dir="auto">hello@mail+xyz.example isn't valid, but <a href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
   wysiwyg: |-
-    <p>hello@mail+xyz.example isn't valid, but <a target="_blank" rel="noopener noreferrer nofollow" href="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
+    <p>hello@mail+xyz.example isn't valid, but <a target="_blank" rel="noopener noreferrer nofollow" href="mailto:hello+xyz@mail.example" canonicalsrc="mailto:hello+xyz@mail.example">hello+xyz@mail.example</a> is.</p>
 06_10__inlines__autolinks_extension__011:
   canonical: |
     <p><a href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
@@ -7291,8 +7291,8 @@
     <p data-sourcepos="5:1-5:12" dir="auto">a.b-c_d@a.b-</p>
     <p data-sourcepos="7:1-7:12" dir="auto">a.b-c_d@a.b_</p>
   wysiwyg: |-
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
-    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:a.b-c_d@a.b" canonicalsrc="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a></p>
+    <p><a target="_blank" rel="noopener noreferrer nofollow" href="mailto:a.b-c_d@a.b" canonicalsrc="mailto:a.b-c_d@a.b">a.b-c_d@a.b</a>.</p>
     <p>a.b-c_d@a.b-</p>
     <p>a.b-c_d@a.b_</p>
 06_11__inlines__raw_html__001:
diff --git a/glfm_specification/example_snapshots/prosemirror_json.yml b/glfm_specification/example_snapshots/prosemirror_json.yml
index 7cb4757b368b9..73fcef4dbc09d 100644
--- a/glfm_specification/example_snapshots/prosemirror_json.yml
+++ b/glfm_specification/example_snapshots/prosemirror_json.yml
@@ -3145,11 +3145,11 @@
                   {
                     "type": "link",
                     "attrs": {
-                      "href": "bar",
+                      "href": "http://test.host/bar",
                       "target": "_blank",
                       "class": null,
                       "title": null,
-                      "canonicalSrc": null
+                      "canonicalSrc": "bar"
                     }
                   }
                 ],
@@ -3230,11 +3230,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo",
+                  "href": "http://test.host/foo",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo"
                 }
               }
             ],
@@ -3748,11 +3748,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "bar",
+                  "href": "http://test.host/bar",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "bar"
                 }
               }
             ],
@@ -3906,11 +3906,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -3947,11 +3947,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "the title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -3988,11 +3988,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "my_(url)",
+                  "href": "http://test.host/my_(url)",
                   "target": "_blank",
                   "class": null,
                   "title": "title (with parens)",
-                  "canonicalSrc": null
+                  "canonicalSrc": "my_(url)"
                 }
               }
             ],
@@ -4029,11 +4029,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "my%20url",
+                  "href": "http://test.host/my%20url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "my%20url"
                 }
               }
             ],
@@ -4070,11 +4070,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "\ntitle\nline1\nline2\n",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -4144,11 +4144,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -4213,7 +4213,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": ""
                 }
               }
             ],
@@ -4274,11 +4274,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url%5Cbar*baz",
+                  "href": "http://test.host/url%5Cbar*baz",
                   "target": "_blank",
                   "class": null,
                   "title": "foo\"bar\\baz",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url%5Cbar*baz"
                 }
               }
             ],
@@ -4301,11 +4301,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "url"
                 }
               }
             ],
@@ -4342,11 +4342,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "first",
+                  "href": "http://test.host/first",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "first"
                 }
               }
             ],
@@ -4411,11 +4411,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -4452,11 +4452,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/%CF%86%CE%BF%CF%85",
+                  "href": "http://test.host/%CF%86%CE%BF%CF%85",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/%CF%86%CE%BF%CF%85"
                 }
               }
             ],
@@ -4655,11 +4655,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -4739,11 +4739,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -4784,11 +4784,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -4853,11 +4853,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/foo-url",
+                  "href": "http://test.host/foo-url",
                   "target": "_blank",
                   "class": null,
                   "title": "foo",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/foo-url"
                 }
               }
             ],
@@ -4873,11 +4873,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/bar-url",
+                  "href": "http://test.host/bar-url",
                   "target": "_blank",
                   "class": null,
                   "title": "bar",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/bar-url"
                 }
               }
             ],
@@ -4893,11 +4893,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/baz-url",
+                  "href": "http://test.host/baz-url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/baz-url"
                 }
               }
             ],
@@ -4920,11 +4920,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -10683,11 +10683,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com?find=%5C*",
+                  "href": "http://example.com/?find=%5C*",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com?find=%5C*"
                 }
               }
             ],
@@ -10719,11 +10719,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/bar*",
+                  "href": "http://test.host/bar*",
                   "target": "_blank",
                   "class": null,
                   "title": "ti*tle",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/bar*"
                 }
               }
             ],
@@ -10746,11 +10746,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/bar*",
+                  "href": "http://test.host/bar*",
                   "target": "_blank",
                   "class": null,
                   "title": "ti*tle",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/bar*"
                 }
               }
             ],
@@ -10905,11 +10905,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/f%C3%B6%C3%B6",
+                  "href": "http://test.host/f%C3%B6%C3%B6",
                   "target": "_blank",
                   "class": null,
                   "title": "föö",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/f%C3%B6%C3%B6"
                 }
               }
             ],
@@ -10932,11 +10932,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/f%C3%B6%C3%B6",
+                  "href": "http://test.host/f%C3%B6%C3%B6",
                   "target": "_blank",
                   "class": null,
                   "title": "föö",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/f%C3%B6%C3%B6"
                 }
               }
             ],
@@ -11466,11 +11466,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "`",
+                  "href": "http://test.host/%60",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "`"
                 }
               }
             ],
@@ -11517,11 +11517,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar.%60baz",
+                  "href": "http://foo.bar.`baz/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar.%60baz"
                 }
               }
             ],
@@ -12673,11 +12673,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -13143,11 +13143,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -13212,11 +13212,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -13571,11 +13571,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -14477,11 +14477,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -14508,11 +14508,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -14536,11 +14536,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "foo",
+              "src": "http://test.host/foo",
               "alt": null,
               "title": "*",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "foo"
             }
           }
         ]
@@ -14662,7 +14662,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar/?q=**"
                 }
               }
             ],
@@ -14693,7 +14693,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar/?q=__"
                 }
               }
             ],
@@ -14764,11 +14764,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -14791,11 +14791,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -14822,7 +14822,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": ""
                 }
               }
             ],
@@ -14849,7 +14849,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": ""
                 }
               }
             ],
@@ -14887,11 +14887,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/my%20uri",
+                  "href": "http://test.host/my%20uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/my%20uri"
                 }
               }
             ],
@@ -14944,11 +14944,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "b)c",
+                  "href": "http://test.host/b)c",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "b)c"
                 }
               }
             ],
@@ -15010,11 +15010,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "(foo)",
+                  "href": "http://test.host/(foo)",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "(foo)"
                 }
               }
             ],
@@ -15037,11 +15037,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo(and(bar))",
+                  "href": "http://test.host/foo(and(bar))",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo(and(bar))"
                 }
               }
             ],
@@ -15064,11 +15064,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo(and(bar)",
+                  "href": "http://test.host/foo(and(bar)",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo(and(bar)"
                 }
               }
             ],
@@ -15091,11 +15091,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo(and(bar)",
+                  "href": "http://test.host/foo(and(bar)",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo(and(bar)"
                 }
               }
             ],
@@ -15118,11 +15118,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo):",
+                  "href": "http://test.host/foo):",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo):"
                 }
               }
             ],
@@ -15145,11 +15145,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "#fragment",
+                  "href": "http://test.host/#fragment",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "#fragment"
                 }
               }
             ],
@@ -15166,11 +15166,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com#fragment",
+                  "href": "http://example.com/#fragment",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com#fragment"
                 }
               }
             ],
@@ -15187,11 +15187,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com?foo=3#frag",
+                  "href": "http://example.com/?foo=3#frag",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com?foo=3#frag"
                 }
               }
             ],
@@ -15214,11 +15214,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo%5Cbar",
+                  "href": "http://test.host/foo%5Cbar",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo%5Cbar"
                 }
               }
             ],
@@ -15241,11 +15241,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "foo%20b%C3%A4",
+                  "href": "http://test.host/foo%20b%C3%A4",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "foo%20b%C3%A4"
                 }
               }
             ],
@@ -15268,11 +15268,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "%22title%22",
+                  "href": "http://test.host/%22title%22",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "%22title%22"
                 }
               }
             ],
@@ -15295,11 +15295,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -15322,11 +15322,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title \"\"",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -15349,11 +15349,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url%C2%A0%22title%22",
+                  "href": "http://test.host/url%C2%A0%22title%22",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url%C2%A0%22title%22"
                 }
               }
             ],
@@ -15391,11 +15391,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title \"and\" title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -15418,11 +15418,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15460,11 +15460,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15506,11 +15506,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15533,11 +15533,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15560,11 +15560,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15576,11 +15576,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -15595,11 +15595,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -15617,11 +15617,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -15650,21 +15650,21 @@
           {
             "type": "image",
             "attrs": {
-              "src": "moon.jpg",
+              "src": "http://test.host/moon.jpg",
               "alt": "moon",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "moon.jpg"
             },
             "marks": [
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ]
@@ -15690,11 +15690,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15734,11 +15734,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -15774,11 +15774,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "uri3",
+              "src": "http://test.host/uri3",
               "alt": "[foo](uri2)",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "uri3"
             }
           }
         ]
@@ -15802,11 +15802,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -15829,11 +15829,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "baz*",
+                  "href": "http://test.host/baz*",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "baz*"
                 }
               }
             ],
@@ -15927,7 +15927,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com/?search=%5D(uri)"
                 }
               }
             ],
@@ -15950,11 +15950,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -15991,11 +15991,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16032,11 +16032,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16073,11 +16073,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16089,11 +16089,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -16108,11 +16108,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -16130,11 +16130,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -16177,21 +16177,21 @@
           {
             "type": "image",
             "attrs": {
-              "src": "moon.jpg",
+              "src": "http://test.host/moon.jpg",
               "alt": "moon",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "moon.jpg"
             },
             "marks": [
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ]
@@ -16231,11 +16231,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16251,11 +16251,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16305,11 +16305,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               },
               {
@@ -16328,11 +16328,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16373,11 +16373,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16414,11 +16414,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16530,7 +16530,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com/?search=%5D%5Bref%5D"
                 }
               }
             ],
@@ -16567,11 +16567,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -16608,11 +16608,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -16667,11 +16667,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -16698,11 +16698,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -16743,11 +16743,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -16812,11 +16812,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
+                  "href": "http://test.host/url1",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url1"
                 }
               }
             ],
@@ -16940,11 +16940,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -16995,11 +16995,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/uri",
+                  "href": "http://test.host/uri",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/uri"
                 }
               }
             ],
@@ -17070,11 +17070,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17111,11 +17111,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -17130,11 +17130,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17171,11 +17171,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17212,11 +17212,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17257,11 +17257,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17298,11 +17298,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -17317,11 +17317,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17362,11 +17362,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               },
               {
@@ -17381,11 +17381,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17430,11 +17430,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17471,11 +17471,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17512,11 +17512,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17604,11 +17604,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17631,11 +17631,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url2",
+                  "href": "http://test.host/url2",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url2"
                 }
               }
             ],
@@ -17686,11 +17686,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
+                  "href": "http://test.host/url1",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url1"
                 }
               }
             ],
@@ -17731,7 +17731,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": ""
                 }
               }
             ],
@@ -17768,11 +17768,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
+                  "href": "http://test.host/url1",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url1"
                 }
               }
             ],
@@ -17817,11 +17817,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -17858,11 +17858,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url2",
+                  "href": "http://test.host/url2",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url2"
                 }
               }
             ],
@@ -17874,11 +17874,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
+                  "href": "http://test.host/url1",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url1"
                 }
               }
             ],
@@ -17933,11 +17933,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url1",
+                  "href": "http://test.host/url1",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url1"
                 }
               }
             ],
@@ -17985,11 +17985,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18006,11 +18006,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "train.jpg",
+              "src": "http://test.host/train.jpg",
               "alt": "foo bar",
               "title": "train & tracks",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "train.jpg"
             }
           }
         ]
@@ -18041,11 +18041,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url2",
+              "src": "http://test.host/url2",
               "alt": "foo bar",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url2"
             }
           }
         ]
@@ -18062,11 +18062,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url2",
+              "src": "http://test.host/url2",
               "alt": "foo bar",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url2"
             }
           }
         ]
@@ -18083,11 +18083,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "train.jpg",
+              "src": "http://test.host/train.jpg",
               "alt": "foo bar",
               "title": "train & tracks",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "train.jpg"
             }
           }
         ]
@@ -18118,11 +18118,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "train.jpg",
+              "src": "http://test.host/train.jpg",
               "alt": "foo bar",
               "title": "train & tracks",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "train.jpg"
             }
           }
         ]
@@ -18153,11 +18153,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "train.jpg",
+              "src": "http://test.host/train.jpg",
               "alt": "foo",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "train.jpg"
             }
           }
         ]
@@ -18178,11 +18178,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/path/to/train.jpg",
+              "src": "http://test.host/path/to/train.jpg",
               "alt": "foo bar",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/path/to/train.jpg"
             }
           }
         ]
@@ -18199,11 +18199,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "url"
             }
           }
         ]
@@ -18220,11 +18220,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18241,11 +18241,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18276,11 +18276,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": null,
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18311,11 +18311,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18346,11 +18346,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo bar",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18381,11 +18381,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "Foo",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18416,11 +18416,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           },
           {
@@ -18455,11 +18455,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18490,11 +18490,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "foo bar",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18549,11 +18549,11 @@
           {
             "type": "image",
             "attrs": {
-              "src": "/url",
+              "src": "http://test.host/url",
               "alt": "Foo",
               "title": "title",
               "uploading": false,
-              "canonicalSrc": null
+              "canonicalSrc": "/url"
             }
           }
         ]
@@ -18620,11 +18620,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "/url",
+                  "href": "http://test.host/url",
                   "target": "_blank",
                   "class": null,
                   "title": "title",
-                  "canonicalSrc": null
+                  "canonicalSrc": "/url"
                 }
               }
             ],
@@ -18661,11 +18661,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar.baz",
+                  "href": "http://foo.bar.baz/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar.baz"
                 }
               }
             ],
@@ -18692,7 +18692,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar.baz/test?q=hello&id=22&boolean"
                 }
               }
             ],
@@ -18719,7 +18719,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "irc://foo.bar:2233/baz"
                 }
               }
             ],
@@ -18742,11 +18742,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "MAILTO:FOO@BAR.BAZ",
+                  "href": "mailto:FOO@BAR.BAZ",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "MAILTO:FOO@BAR.BAZ"
                 }
               }
             ],
@@ -18773,7 +18773,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "a+b+c:d"
                 }
               }
             ],
@@ -18800,7 +18800,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "made-up-scheme://foo,bar"
                 }
               }
             ],
@@ -18827,7 +18827,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://../"
                 }
               }
             ],
@@ -18854,7 +18854,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "localhost:5001/foo"
                 }
               }
             ],
@@ -18885,7 +18885,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar/baz"
                 }
               }
             ],
@@ -18916,7 +18916,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com/%5C%5B%5C"
                 }
               }
             ],
@@ -18943,7 +18943,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:foo@bar.example.com"
                 }
               }
             ],
@@ -18970,7 +18970,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:foo+special@Bar.baz-bar0.com"
                 }
               }
             ],
@@ -19001,7 +19001,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:foo+@bar.example.com"
                 }
               }
             ],
@@ -19047,11 +19047,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://foo.bar",
+                  "href": "http://foo.bar/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://foo.bar"
                 }
               }
             ],
@@ -19108,11 +19108,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://example.com",
+                  "href": "http://example.com/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://example.com"
                 }
               }
             ],
@@ -19139,7 +19139,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:foo@bar.example.com"
                 }
               }
             ],
@@ -19162,11 +19162,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org",
+                  "href": "http://www.commonmark.org/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.commonmark.org"
                 }
               }
             ],
@@ -19197,7 +19197,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.commonmark.org/help"
                 }
               }
             ],
@@ -19228,11 +19228,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://www.commonmark.org",
+                  "href": "http://www.commonmark.org/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.commonmark.org"
                 }
               }
             ],
@@ -19261,7 +19261,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.commonmark.org/a.b"
                 }
               }
             ],
@@ -19292,7 +19292,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=Markup+(business)"
                 }
               }
             ],
@@ -19313,7 +19313,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=Markup+(business)"
                 }
               }
             ],
@@ -19342,7 +19342,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=Markup+(business)"
                 }
               }
             ],
@@ -19371,7 +19371,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=Markup+(business)"
                 }
               }
             ],
@@ -19398,7 +19398,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=(business))+ok"
                 }
               }
             ],
@@ -19425,7 +19425,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=commonmark&hl=en"
                 }
               }
             ],
@@ -19446,7 +19446,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.google.com/search?q=commonmark"
                 }
               }
             ],
@@ -19477,7 +19477,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://www.commonmark.org/he"
                 }
               }
             ],
@@ -19504,11 +19504,11 @@
               {
                 "type": "link",
                 "attrs": {
-                  "href": "http://commonmark.org",
+                  "href": "http://commonmark.org/",
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "http://commonmark.org"
                 }
               }
             ],
@@ -19533,7 +19533,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "https://encrypted.google.com/search?q=Markup+(business)"
                 }
               }
             ],
@@ -19573,7 +19573,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:foo@bar.baz"
                 }
               }
             ],
@@ -19604,7 +19604,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:hello+xyz@mail.example"
                 }
               }
             ],
@@ -19635,7 +19635,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:a.b-c_d@a.b"
                 }
               }
             ],
@@ -19656,7 +19656,7 @@
                   "target": "_blank",
                   "class": null,
                   "title": null,
-                  "canonicalSrc": null
+                  "canonicalSrc": "mailto:a.b-c_d@a.b"
                 }
               }
             ],
diff --git a/spec/frontend/content_editor/remark_markdown_processing_spec.js b/spec/frontend/content_editor/remark_markdown_processing_spec.js
index ddf49a4c18eb1..e1de2823726fe 100644
--- a/spec/frontend/content_editor/remark_markdown_processing_spec.js
+++ b/spec/frontend/content_editor/remark_markdown_processing_spec.js
@@ -257,7 +257,12 @@ describe('Client side Markdown processing', () => {
       expectedDoc: doc(
         paragraph(
           source('<img src="bar" alt="foo" />'),
-          image({ ...source('<img src="bar" alt="foo" />'), alt: 'foo', src: 'bar' }),
+          image({
+            ...source('<img src="bar" alt="foo" />'),
+            alt: 'foo',
+            canonicalSrc: 'bar',
+            src: 'http://test.host/bar',
+          }),
         ),
       ),
     },
@@ -275,7 +280,12 @@ describe('Client side Markdown processing', () => {
         ),
         paragraph(
           source('<img src="bar" alt="foo" />'),
-          image({ ...source('<img src="bar" alt="foo" />'), alt: 'foo', src: 'bar' }),
+          image({
+            ...source('<img src="bar" alt="foo" />'),
+            alt: 'foo',
+            src: 'http://test.host/bar',
+            canonicalSrc: 'bar',
+          }),
         ),
       ),
     },
@@ -287,7 +297,8 @@ describe('Client side Markdown processing', () => {
           link(
             {
               ...source('[GitLab](https://gitlab.com "Go to GitLab")'),
-              href: 'https://gitlab.com',
+              href: 'https://gitlab.com/',
+              canonicalSrc: 'https://gitlab.com',
               title: 'Go to GitLab',
             },
             'GitLab',
@@ -305,7 +316,8 @@ describe('Client side Markdown processing', () => {
             link(
               {
                 ...source('[GitLab](https://gitlab.com "Go to GitLab")'),
-                href: 'https://gitlab.com',
+                href: 'https://gitlab.com/',
+                canonicalSrc: 'https://gitlab.com',
                 title: 'Go to GitLab',
               },
               'GitLab',
@@ -322,7 +334,8 @@ describe('Client side Markdown processing', () => {
           link(
             {
               ...source('www.commonmark.org'),
-              href: 'http://www.commonmark.org',
+              canonicalSrc: 'http://www.commonmark.org',
+              href: 'http://www.commonmark.org/',
             },
             'www.commonmark.org',
           ),
@@ -338,6 +351,7 @@ describe('Client side Markdown processing', () => {
           link(
             {
               ...source('www.commonmark.org/help'),
+              canonicalSrc: 'http://www.commonmark.org/help',
               href: 'http://www.commonmark.org/help',
             },
             'www.commonmark.org/help',
@@ -355,6 +369,7 @@ describe('Client side Markdown processing', () => {
           link(
             {
               ...source('hello+xyz@mail.example'),
+              canonicalSrc: 'mailto:hello+xyz@mail.example',
               href: 'mailto:hello+xyz@mail.example',
             },
             'hello+xyz@mail.example',
@@ -373,7 +388,8 @@ describe('Client side Markdown processing', () => {
             {
               sourceMapKey: null,
               sourceMarkdown: null,
-              href: 'https://gitlab.com',
+              canonicalSrc: 'https://gitlab.com',
+              href: 'https://gitlab.com/',
             },
             'https://gitlab.com',
           ),
@@ -402,6 +418,7 @@ hard line break`,
           image({
             ...source('![GitLab Logo](https://gitlab.com/logo.png "GitLab Logo")'),
             alt: 'GitLab Logo',
+            canonicalSrc: 'https://gitlab.com/logo.png',
             src: 'https://gitlab.com/logo.png',
             title: 'GitLab Logo',
           }),
@@ -595,7 +612,12 @@ two
             paragraph(
               source('List item with an image ![bar](foo.png)'),
               'List item with an image',
-              image({ ...source('![bar](foo.png)'), alt: 'bar', src: 'foo.png' }),
+              image({
+                ...source('![bar](foo.png)'),
+                alt: 'bar',
+                canonicalSrc: 'foo.png',
+                src: 'http://test.host/foo.png',
+              }),
             ),
           ),
         ),
@@ -944,8 +966,17 @@ Paragraph
         paragraph(
           source('[![moon](moon.jpg)](/uri)'),
           link(
-            { ...source('[![moon](moon.jpg)](/uri)'), href: '/uri' },
-            image({ ...source('![moon](moon.jpg)'), src: 'moon.jpg', alt: 'moon' }),
+            {
+              ...source('[![moon](moon.jpg)](/uri)'),
+              canonicalSrc: '/uri',
+              href: 'http://test.host/uri',
+            },
+            image({
+              ...source('![moon](moon.jpg)'),
+              canonicalSrc: 'moon.jpg',
+              src: 'http://test.host/moon.jpg',
+              alt: 'moon',
+            }),
           ),
         ),
       ),
@@ -975,12 +1006,26 @@ Paragraph
           source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
           strike(
             source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
-            link({ ...source('[moon](moon.jpg)'), href: 'moon.jpg' }, 'moon'),
+            link(
+              {
+                ...source('[moon](moon.jpg)'),
+                canonicalSrc: 'moon.jpg',
+                href: 'http://test.host/moon.jpg',
+              },
+              'moon',
+            ),
           ),
           strike(source('~[moon](moon.jpg) and [sun](sun.jpg)~'), ' and '),
           strike(
             source('~[moon](moon.jpg) and [sun](sun.jpg)~'),
-            link({ ...source('[sun](sun.jpg)'), href: 'sun.jpg' }, 'sun'),
+            link(
+              {
+                ...source('[sun](sun.jpg)'),
+                href: 'http://test.host/sun.jpg',
+                canonicalSrc: 'sun.jpg',
+              },
+              'sun',
+            ),
           ),
         ),
       ),
@@ -1094,7 +1139,12 @@ _world_.
         paragraph(
           source('[GitLab][gitlab-url]'),
           link(
-            { ...source('[GitLab][gitlab-url]'), href: 'https://gitlab.com', title: 'GitLab' },
+            {
+              ...source('[GitLab][gitlab-url]'),
+              href: 'https://gitlab.com/',
+              canonicalSrc: 'https://gitlab.com',
+              title: 'GitLab',
+            },
             'GitLab',
           ),
         ),
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 422eb3f311b2f..d55e5fbadad1a 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -1213,42 +1213,47 @@ paragraph
   };
 
   it.each`
-    mark          | markdown                                   | modifiedMarkdown                                                              | editAction
-    ${'bold'}     | ${'**bold**'}                              | ${'**bold modified**'}                                                        | ${defaultEditAction}
-    ${'bold'}     | ${'__bold__'}                              | ${'__bold modified__'}                                                        | ${defaultEditAction}
-    ${'bold'}     | ${'<strong>bold</strong>'}                 | ${'<strong>bold modified</strong>'}                                           | ${defaultEditAction}
-    ${'bold'}     | ${'<b>bold</b>'}                           | ${'<b>bold modified</b>'}                                                     | ${defaultEditAction}
-    ${'italic'}   | ${'_italic_'}                              | ${'_italic modified_'}                                                        | ${defaultEditAction}
-    ${'italic'}   | ${'*italic*'}                              | ${'*italic modified*'}                                                        | ${defaultEditAction}
-    ${'italic'}   | ${'<em>italic</em>'}                       | ${'<em>italic modified</em>'}                                                 | ${defaultEditAction}
-    ${'italic'}   | ${'<i>italic</i>'}                         | ${'<i>italic modified</i>'}                                                   | ${defaultEditAction}
-    ${'link'}     | ${'[gitlab](https://gitlab.com)'}          | ${'[gitlab modified](https://gitlab.com)'}                                    | ${defaultEditAction}
-    ${'link'}     | ${'<a href="https://gitlab.com">link</a>'} | ${'<a href="https://gitlab.com">link modified</a>'}                           | ${defaultEditAction}
-    ${'link'}     | ${'link www.gitlab.com'}                   | ${'modified link www.gitlab.com'}                                             | ${prependContentEditAction}
-    ${'link'}     | ${'link https://www.gitlab.com'}           | ${'modified link https://www.gitlab.com'}                                     | ${prependContentEditAction}
-    ${'link'}     | ${'link(https://www.gitlab.com)'}          | ${'modified link(https://www.gitlab.com)'}                                    | ${prependContentEditAction}
-    ${'link'}     | ${'link(engineering@gitlab.com)'}          | ${'modified link(engineering@gitlab.com)'}                                    | ${prependContentEditAction}
-    ${'link'}     | ${'link <https://www.gitlab.com>'}         | ${'modified link <https://www.gitlab.com>'}                                   | ${prependContentEditAction}
-    ${'link'}     | ${'link [https://www.gitlab.com>'}         | ${'modified link \\[https://www.gitlab.com>'}                                 | ${prependContentEditAction}
-    ${'link'}     | ${'link <https://www.gitlab.com'}          | ${'modified link <https://www.gitlab.com'}                                    | ${prependContentEditAction}
-    ${'link'}     | ${'link https://www.gitlab.com>'}          | ${'modified link [https://www.gitlab.com>](https://www.gitlab.com%3E)'}       | ${prependContentEditAction}
-    ${'link'}     | ${'link **https://www.gitlab.com]**'}      | ${'modified link [**https://www.gitlab.com\\]**](https://www.gitlab.com%5D)'} | ${prependContentEditAction}
-    ${'code'}     | ${'`code`'}                                | ${'`code modified`'}                                                          | ${defaultEditAction}
-    ${'code'}     | ${'<code>code</code>'}                     | ${'<code>code modified</code>'}                                               | ${defaultEditAction}
-    ${'strike'}   | ${'~~striked~~'}                           | ${'~~striked modified~~'}                                                     | ${defaultEditAction}
-    ${'strike'}   | ${'<del>striked</del>'}                    | ${'<del>striked modified</del>'}                                              | ${defaultEditAction}
-    ${'strike'}   | ${'<strike>striked</strike>'}              | ${'<strike>striked modified</strike>'}                                        | ${defaultEditAction}
-    ${'strike'}   | ${'<s>striked</s>'}                        | ${'<s>striked modified</s>'}                                                  | ${defaultEditAction}
-    ${'list'}     | ${'- list item'}                           | ${'- list item modified'}                                                     | ${defaultEditAction}
-    ${'list'}     | ${'* list item'}                           | ${'* list item modified'}                                                     | ${defaultEditAction}
-    ${'list'}     | ${'+ list item'}                           | ${'+ list item modified'}                                                     | ${defaultEditAction}
-    ${'list'}     | ${'- list item 1\n- list item 2'}          | ${'- list item 1\n- list item 2 modified'}                                    | ${defaultEditAction}
-    ${'list'}     | ${'2) list item'}                          | ${'2) list item modified'}                                                    | ${defaultEditAction}
-    ${'list'}     | ${'1. list item'}                          | ${'1. list item modified'}                                                    | ${defaultEditAction}
-    ${'taskList'} | ${'2) [ ] task list item'}                 | ${'2) [ ] task list item modified'}                                           | ${defaultEditAction}
-    ${'taskList'} | ${'2) [x] task list item'}                 | ${'2) [x] task list item modified'}                                           | ${defaultEditAction}
+    mark          | markdown                                       | modifiedMarkdown                                                              | editAction
+    ${'bold'}     | ${'**bold**'}                                  | ${'**bold modified**'}                                                        | ${defaultEditAction}
+    ${'bold'}     | ${'__bold__'}                                  | ${'__bold modified__'}                                                        | ${defaultEditAction}
+    ${'bold'}     | ${'<strong>bold</strong>'}                     | ${'<strong>bold modified</strong>'}                                           | ${defaultEditAction}
+    ${'bold'}     | ${'<b>bold</b>'}                               | ${'<b>bold modified</b>'}                                                     | ${defaultEditAction}
+    ${'italic'}   | ${'_italic_'}                                  | ${'_italic modified_'}                                                        | ${defaultEditAction}
+    ${'italic'}   | ${'*italic*'}                                  | ${'*italic modified*'}                                                        | ${defaultEditAction}
+    ${'italic'}   | ${'<em>italic</em>'}                           | ${'<em>italic modified</em>'}                                                 | ${defaultEditAction}
+    ${'italic'}   | ${'<i>italic</i>'}                             | ${'<i>italic modified</i>'}                                                   | ${defaultEditAction}
+    ${'link'}     | ${'[gitlab](https://gitlab.com)'}              | ${'[gitlab modified](https://gitlab.com)'}                                    | ${defaultEditAction}
+    ${'link'}     | ${'<a href="https://gitlab.com">link</a>'}     | ${'<a href="https://gitlab.com/">link modified</a>'}                          | ${defaultEditAction}
+    ${'link'}     | ${'link www.gitlab.com'}                       | ${'modified link www.gitlab.com'}                                             | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com'}               | ${'modified link https://www.gitlab.com'}                                     | ${prependContentEditAction}
+    ${'link'}     | ${'link(https://www.gitlab.com)'}              | ${'modified link(https://www.gitlab.com)'}                                    | ${prependContentEditAction}
+    ${'link'}     | ${'link(engineering@gitlab.com)'}              | ${'modified link(engineering@gitlab.com)'}                                    | ${prependContentEditAction}
+    ${'link'}     | ${'link <https://www.gitlab.com>'}             | ${'modified link <https://www.gitlab.com>'}                                   | ${prependContentEditAction}
+    ${'link'}     | ${'link [https://www.gitlab.com>'}             | ${'modified link \\[https://www.gitlab.com>'}                                 | ${prependContentEditAction}
+    ${'link'}     | ${'link <https://www.gitlab.com'}              | ${'modified link <https://www.gitlab.com'}                                    | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com>'}              | ${'modified link [https://www.gitlab.com>](https://www.gitlab.com%3E)'}       | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com/path'}          | ${'modified link https://www.gitlab.com/path'}                                | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com?query=search'}  | ${'modified link https://www.gitlab.com?query=search'}                        | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com/#fragment'}     | ${'modified link https://www.gitlab.com/#fragment'}                           | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com/?query=search'} | ${'modified link https://www.gitlab.com/?query=search'}                       | ${prependContentEditAction}
+    ${'link'}     | ${'link https://www.gitlab.com#fragment'}      | ${'modified link https://www.gitlab.com#fragment'}                            | ${prependContentEditAction}
+    ${'link'}     | ${'link **https://www.gitlab.com]**'}          | ${'modified link [**https://www.gitlab.com\\]**](https://www.gitlab.com%5D)'} | ${prependContentEditAction}
+    ${'code'}     | ${'`code`'}                                    | ${'`code modified`'}                                                          | ${defaultEditAction}
+    ${'code'}     | ${'<code>code</code>'}                         | ${'<code>code modified</code>'}                                               | ${defaultEditAction}
+    ${'strike'}   | ${'~~striked~~'}                               | ${'~~striked modified~~'}                                                     | ${defaultEditAction}
+    ${'strike'}   | ${'<del>striked</del>'}                        | ${'<del>striked modified</del>'}                                              | ${defaultEditAction}
+    ${'strike'}   | ${'<strike>striked</strike>'}                  | ${'<strike>striked modified</strike>'}                                        | ${defaultEditAction}
+    ${'strike'}   | ${'<s>striked</s>'}                            | ${'<s>striked modified</s>'}                                                  | ${defaultEditAction}
+    ${'list'}     | ${'- list item'}                               | ${'- list item modified'}                                                     | ${defaultEditAction}
+    ${'list'}     | ${'* list item'}                               | ${'* list item modified'}                                                     | ${defaultEditAction}
+    ${'list'}     | ${'+ list item'}                               | ${'+ list item modified'}                                                     | ${defaultEditAction}
+    ${'list'}     | ${'- list item 1\n- list item 2'}              | ${'- list item 1\n- list item 2 modified'}                                    | ${defaultEditAction}
+    ${'list'}     | ${'2) list item'}                              | ${'2) list item modified'}                                                    | ${defaultEditAction}
+    ${'list'}     | ${'1. list item'}                              | ${'1. list item modified'}                                                    | ${defaultEditAction}
+    ${'taskList'} | ${'2) [ ] task list item'}                     | ${'2) [ ] task list item modified'}                                           | ${defaultEditAction}
+    ${'taskList'} | ${'2) [x] task list item'}                     | ${'2) [x] task list item modified'}                                           | ${defaultEditAction}
   `(
-    'preserves original $mark syntax when sourceMarkdown is available for $content',
+    'preserves original $mark syntax when sourceMarkdown is available for $markdown',
     async ({ markdown, modifiedMarkdown, editAction }) => {
       const { document } = await remarkMarkdownDeserializer().deserialize({
         schema: tiptapEditor.schema,
diff --git a/spec/frontend/lib/utils/url_utility_spec.js b/spec/frontend/lib/utils/url_utility_spec.js
index 766da7034d928..312e4f636c363 100644
--- a/spec/frontend/lib/utils/url_utility_spec.js
+++ b/spec/frontend/lib/utils/url_utility_spec.js
@@ -1062,4 +1062,28 @@ describe('URL utility', () => {
       expect(urlUtils.PROMO_URL).toBe(url);
     });
   });
+
+  describe('removeUrlProtocol', () => {
+    it.each`
+      input                   | output
+      ${'http://gitlab.com'}  | ${'gitlab.com'}
+      ${'https://gitlab.com'} | ${'gitlab.com'}
+      ${'foo:bar.com'}        | ${'bar.com'}
+      ${'gitlab.com'}         | ${'gitlab.com'}
+    `('transforms $input to $output', ({ input, output }) => {
+      expect(urlUtils.removeUrlProtocol(input)).toBe(output);
+    });
+  });
+
+  describe('removeLastSlashInUrlPath', () => {
+    it.each`
+      input                                     | output
+      ${'https://www.gitlab.com/path/'}         | ${'https://www.gitlab.com/path'}
+      ${'https://www.gitlab.com/?query=search'} | ${'https://www.gitlab.com?query=search'}
+      ${'https://www.gitlab.com/#fragment'}     | ${'https://www.gitlab.com#fragment'}
+      ${'https://www.gitlab.com/hello'}         | ${'https://www.gitlab.com/hello'}
+    `('transforms $input to $output', ({ input, output }) => {
+      expect(urlUtils.removeLastSlashInUrlPath(input)).toBe(output);
+    });
+  });
 });
-- 
GitLab