Browse Source

Add back autolink support

Thibault Derousseaux 5 years ago
parent
commit
1c176edec3

+ 23 - 1
packages/rendermime/src/renderers.ts

@@ -467,6 +467,28 @@ export namespace renderSVG {
   }
 }
 
+/**
+ * Replace URLs with links.
+ *
+ * @param content - The plain text content.
+ *
+ * @returns The content where all URLs have been replaced with corresponding links.
+ */
+function autolink(content: string): string {
+  return content.replace(
+    // Same pattern as in classic notebook with word boundaries (\b).
+    /\b((https?|ftp)(:[^'"<>\s]+))\b/g,
+    url => {
+      const a = document.createElement('a');
+      a.href = url;
+      a.innerHTML = url;
+      a.rel = 'noopener';
+      a.target = '_blank';
+      return a.outerHTML;
+    }
+  );
+}
+
 /**
  * Render text into a host node.
  *
@@ -485,7 +507,7 @@ export function renderText(options: renderText.IRenderOptions): Promise<void> {
 
   // Set the sanitized content for the host node.
   const pre = document.createElement('pre');
-  pre.innerHTML = content;
+  pre.innerHTML = autolink(content);
   host.appendChild(pre);
 
   // Return the rendered promise.

+ 13 - 0
packages/rendermime/style/base.css

@@ -25,6 +25,19 @@
   line-height: normal;
 }
 
+.jp-RenderedText pre a:link {
+  text-decoration: none;
+  color: var(--jp-content-link-color);
+}
+.jp-RenderedText pre a:hover {
+  text-decoration: underline;
+  color: var(--jp-content-link-color);
+}
+.jp-RenderedText pre a:visited {
+  text-decoration: none;
+  color: var(--jp-content-link-color);
+}
+
 /* console foregrounds and backgrounds */
 .jp-RenderedText pre .ansi-black-fg {
   color: #3e424d;

+ 21 - 0
tests/test-rendermime/src/factories.spec.ts

@@ -100,6 +100,27 @@ describe('rendermime/factories', () => {
           '<pre>There is no text &lt;script&gt;window.x=1&lt;/script&gt; but <span class="ansi-green-intense-fg ansi-red-bg ansi-bold">text</span>.\nWoo.</pre>'
         );
       });
+
+      it('should autolink URLs', async () => {
+        const f = textRendererFactory;
+        const urls = [
+          'https://example.com#anchor',
+          'http://localhost:9090/app',
+          'http://127.0.0.1/test?query=string'
+        ];
+        await Promise.all(
+          urls.map(async url => {
+            const source = `Here is some text with an URL such as ${url} inside.`;
+            const mimeType = 'text/plain';
+            const model = createModel(mimeType, source);
+            const w = f.createRenderer({ mimeType, ...defaultOptions });
+            await w.renderModel(model);
+            expect(w.node.innerHTML).to.equal(
+              `<pre>Here is some text with an URL such as <a href="${url}" rel="noopener" target="_blank">${url}</a> inside.</pre>`
+            );
+          })
+        );
+      });
     });
   });