diff --git a/static_src/autolink.js b/static_src/autolink.js
new file mode 100644
index 0000000..5419d9c
--- /dev/null
+++ b/static_src/autolink.js
@@ -0,0 +1,440 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+import {prpcClient} from 'prpc-client-instance.js';
+
+/* eslint-disable max-len */
+// When crbug links don't specify a project, the default project is Chromium.
+const CRBUG_DEFAULT_PROJECT = 'chromium';
+const CRBUG_LINK_RE = /(\b(https?:\/\/)?crbug\.com\/)((\b[-a-z0-9]+)(\/))?(\d+)\b(\#c[0-9]+)?/gi;
+const CRBUG_LINK_RE_PROJECT_GROUP = 4;
+const CRBUG_LINK_RE_ID_GROUP = 6;
+const CRBUG_LINK_RE_COMMENT_GROUP = 7;
+const ISSUE_TRACKER_RE = /(\b(issues?|bugs?)[ \t]*(:|=|\b)|\bfixed[ \t]*:)([ \t]*((\b[-a-z0-9]+)[:\#])?(\#?)(\d+)\b(,?[ \t]*(and|or)?)?)+/gi;
+const PROJECT_LOCALID_RE = /((\b(issue|bug)[ \t]*(:|=)?[ \t]*|\bfixed[ \t]*:[ \t]*)?((\b[-a-z0-9]+)[:\#])?(\#?)(\d+))/gi;
+const PROJECT_COMMENT_BUG_RE = /(((\b(issue|bug)[ \t]*(:|=)?[ \t]*)(\#?)(\d+)[ \t*])?((\b((comment)[ \t]*(:|=)?[ \t]*(\#?))|(\B((\#))(c)))(\d+)))/gi;
+const PROJECT_LOCALID_RE_PROJECT_GROUP = 6;
+const PROJECT_LOCALID_RE_ID_GROUP = 8;
+const IMPLIED_EMAIL_RE = /\b[a-z]((-|\.)?[a-z0-9])+@[a-z]((-|\.)?[a-z0-9])+\.(com|net|org|edu|dev)\b/gi;
+// TODO(zhangtiff): Replace (^|[^-/._]) with (?<![-/._]) on the 3 Regexes below
+// once Firefox supports lookaheads.
+const SHORT_LINK_RE = /(^|[^-\/._])\b(https?:\/\/|ftp:\/\/|mailto:)?(go|g|shortn|who|teams)\/([^\s<]+)/gi;
+const NUMERIC_SHORT_LINK_RE = /(^|[^-\/._])\b(https?:\/\/|ftp:\/\/)?(b|t|o|omg|cl|cr|fxr|fxrev|fxb|tqr)\/([0-9]+)/gi;
+const IMPLIED_LINK_RE = /(^|[^-\/._])\b[a-z]((-|\.)?[a-z0-9])+\.(com|net|org|edu|dev)\b(\/[^\s<]*)?/gi;
+const IS_LINK_RE = /()\b(https?:\/\/|ftp:\/\/|mailto:)([^\s<]+)/gi;
+const GIT_HASH_RE = /\b(r(evision\s+#?)?)?([a-f0-9]{40})\b/gi;
+const SVN_REF_RE = /\b(r(evision\s+#?)?)([0-9]{4,7})\b/gi;
+const NEW_LINE_REGEX = /^(\r\n?|\n)$/;
+const NEW_LINE_OR_BOLD_REGEX = /(<b>[^<\n]+<\/b>)|(\r\n?|\n)/;
+// The revNum is in the same position for the above two Regexes. The
+// extraction function uses this similar format to allow switching out
+// Regexes easily, so be careful about changing GIT_HASH_RE and SVN_HASH_RE.
+const REV_NUM_GROUP = 3;
+const LINK_TRAILING_CHARS = [
+  [null, ':'],
+  [null, '.'],
+  [null, ','],
+  [null, '>'],
+  ['(', ')'],
+  ['[', ']'],
+  ['{', '}'],
+  ['\'', '\''],
+  ['"', '"'],
+];
+const GOOG_SHORT_LINK_RE = /^(b|t|o|omg|cl|cr|go|g|shortn|who|teams|fxr|fxrev|fxb|tqr)\/.*/gi;
+/* eslint-enable max-len */
+
+const Components = new Map();
+// TODO(zosha): Combine functions of Component 00 with 01 so that
+// user can only reference valid issues in the issue/comment linking.
+// Allow user to reference multiple comments on the same issue.
+// Additionally, allow for the user to reference this on a specific project.
+// Note: the order of the components is important for proper autolinking.
+Components.set(
+    '00-commentbug',
+    {
+      lookup: null,
+      extractRefs: null,
+      refRegs: [PROJECT_COMMENT_BUG_RE],
+      replacer: ReplaceCommentBugRef,
+    },
+);
+Components.set(
+    '01-tracker-crbug',
+    {
+      lookup: LookupReferencedIssues,
+      extractRefs: ExtractCrbugProjectAndIssueIds,
+      refRegs: [CRBUG_LINK_RE],
+      replacer: ReplaceCrbugIssueRef,
+
+    },
+);
+Components.set(
+    '02-full-urls',
+    {
+      lookup: null,
+      extractRefs: (match, _currentProjectName) => {
+        return [match[0]];
+      },
+      refRegs: [IS_LINK_RE],
+      replacer: ReplaceLinkRef,
+    },
+);
+Components.set(
+    '03-user-emails',
+    {
+      lookup: LookupReferencedUsers,
+      extractRefs: (match, _currentProjectName) => {
+        return [match[0]];
+      },
+      refRegs: [IMPLIED_EMAIL_RE],
+      replacer: ReplaceUserRef,
+    },
+);
+Components.set(
+    '04-tracker-regular',
+    {
+      lookup: LookupReferencedIssues,
+      extractRefs: ExtractTrackerProjectAndIssueIds,
+      refRegs: [ISSUE_TRACKER_RE],
+      replacer: ReplaceTrackerIssueRef,
+    },
+);
+Components.set(
+    '05-linkify-shorthand',
+    {
+      lookup: null,
+      extractRefs: (match, _currentProjectName) => {
+        return [match[0]];
+      },
+      refRegs: [
+        SHORT_LINK_RE,
+        NUMERIC_SHORT_LINK_RE,
+        IMPLIED_LINK_RE,
+      ],
+      replacer: ReplaceLinkRef,
+    },
+);
+Components.set(
+    '06-versioncontrol',
+    {
+      lookup: null,
+      extractRefs: (match, _currentProjectName) => {
+        return [match[0]];
+      },
+      refRegs: [GIT_HASH_RE, SVN_REF_RE],
+      replacer: ReplaceRevisionRef,
+    },
+);
+
+// Lookup referenced artifacts functions.
+function LookupReferencedIssues(issueRefs, componentName) {
+  return new Promise((resolve, reject) => {
+    issueRefs = issueRefs.filter(
+        ({projectName, localId}) => projectName && parseInt(localId));
+    const listReferencedIssues = prpcClient.call(
+        'monorail.Issues', 'ListReferencedIssues', {issueRefs});
+    return listReferencedIssues.then((response) => {
+      resolve({'componentName': componentName, 'existingRefs': response});
+    });
+  });
+}
+
+function LookupReferencedUsers(emails, componentName) {
+  return new Promise((resolve, reject) => {
+    const userRefs = emails.map((displayName) => {
+      return {displayName};
+    });
+    const listReferencedUsers = prpcClient.call(
+        'monorail.Users', 'ListReferencedUsers', {userRefs});
+    return listReferencedUsers.then((response) => {
+      resolve({'componentName': componentName, 'existingRefs': response});
+    });
+  });
+}
+
+// Extract referenced artifacts info functions.
+function ExtractCrbugProjectAndIssueIds(match, _currentProjectName) {
+  // When crbug links don't specify a project, the default project is Chromium.
+  const projectName = match[CRBUG_LINK_RE_PROJECT_GROUP] ||
+    CRBUG_DEFAULT_PROJECT;
+  const localId = match[CRBUG_LINK_RE_ID_GROUP];
+  return [{projectName: projectName, localId: localId}];
+}
+
+function ExtractTrackerProjectAndIssueIds(match, currentProjectName) {
+  const issueRefRE = PROJECT_LOCALID_RE;
+  let refMatch;
+  const refs = [];
+  while ((refMatch = issueRefRE.exec(match[0])) !== null) {
+    if (refMatch[PROJECT_LOCALID_RE_PROJECT_GROUP]) {
+      currentProjectName = refMatch[PROJECT_LOCALID_RE_PROJECT_GROUP];
+    }
+    refs.push({
+      projectName: currentProjectName,
+      localId: refMatch[PROJECT_LOCALID_RE_ID_GROUP],
+    });
+  }
+  return refs;
+}
+
+// Replace plain text references with links functions.
+function ReplaceIssueRef(stringMatch, projectName, localId, components,
+    commentId) {
+  if (components.openRefs && components.openRefs.length) {
+    const openRef = components.openRefs.find((ref) => {
+      return ref.localId && ref.projectName && (ref.localId == localId) &&
+          (ref.projectName.toLowerCase() === projectName.toLowerCase());
+    });
+    if (openRef) {
+      return createIssueRefRun(
+          projectName, localId, openRef.summary, false, stringMatch, commentId);
+    }
+  }
+  if (components.closedRefs && components.closedRefs.length) {
+    const closedRef = components.closedRefs.find((ref) => {
+      return ref.localId && ref.projectName && (ref.localId == localId) &&
+          (ref.projectName.toLowerCase() === projectName.toLowerCase());
+    });
+    if (closedRef) {
+      return createIssueRefRun(
+          projectName, localId, closedRef.summary, true, stringMatch,
+          commentId);
+    }
+  }
+  return {content: stringMatch};
+}
+
+function ReplaceCrbugIssueRef(match, components, _currentProjectName) {
+  components = components || {};
+  // When crbug links don't specify a project, the default project is Chromium.
+  const projectName =
+    match[CRBUG_LINK_RE_PROJECT_GROUP] || CRBUG_DEFAULT_PROJECT;
+  const localId = match[CRBUG_LINK_RE_ID_GROUP];
+  let commentId = '';
+  if (match[CRBUG_LINK_RE_COMMENT_GROUP] !== undefined) {
+    commentId = match[CRBUG_LINK_RE_COMMENT_GROUP];
+  }
+  return [ReplaceIssueRef(match[0], projectName, localId, components,
+      commentId)];
+}
+
+function ReplaceTrackerIssueRef(match, components, currentProjectName) {
+  components = components || {};
+  const issueRefRE = PROJECT_LOCALID_RE;
+  const commentId = '';
+  const textRuns = [];
+  let refMatch;
+  let pos = 0;
+  while ((refMatch = issueRefRE.exec(match[0])) !== null) {
+    if (refMatch.index > pos) {
+      // Create textrun for content between previous and current match.
+      textRuns.push({content: match[0].slice(pos, refMatch.index)});
+    }
+    if (refMatch[PROJECT_LOCALID_RE_PROJECT_GROUP]) {
+      currentProjectName = refMatch[PROJECT_LOCALID_RE_PROJECT_GROUP];
+    }
+    textRuns.push(ReplaceIssueRef(
+        refMatch[0], currentProjectName,
+        refMatch[PROJECT_LOCALID_RE_ID_GROUP], components, commentId));
+    pos = refMatch.index + refMatch[0].length;
+  }
+  if (match[0].slice(pos) !== '') {
+    textRuns.push({content: match[0].slice(pos)});
+  }
+  return textRuns;
+}
+
+function ReplaceUserRef(match, components, _currentProjectName) {
+  components = components || {};
+  const textRun = {content: match[0], tag: 'a'};
+  if (components.users && components.users.length) {
+    const existingUser = components.users.find((user) => {
+      return user.displayName.toLowerCase() === match[0].toLowerCase();
+    });
+    if (existingUser) {
+      textRun.href = `/u/${match[0]}`;
+      return [textRun];
+    }
+  }
+  textRun.href = `mailto:${match[0]}`;
+  return [textRun];
+}
+
+function ReplaceCommentBugRef(match) {
+  let textRun;
+  const issueNum = match[7];
+  const commentNum = match[18];
+  if (issueNum && commentNum) {
+    textRun = {content: match[0], tag: 'a', href: `?id=${issueNum}#c${commentNum}`};
+  } else if (commentNum) {
+    textRun = {content: match[0], tag: 'a', href: `#c${commentNum}`};
+  } else {
+    textRun = {content: match[0]};
+  }
+  return [textRun];
+}
+
+function ReplaceLinkRef(match, _components, _currentProjectName) {
+  const textRuns = [];
+  let content = match[0];
+  let trailing = '';
+  if (match[1]) {
+    textRuns.push({content: match[1]});
+    content = content.slice(match[1].length);
+  }
+  LINK_TRAILING_CHARS.forEach(([begin, end]) => {
+    if (content.endsWith(end)) {
+      if (!begin || !content.slice(0, -end.length).includes(begin)) {
+        trailing = end + trailing;
+        content = content.slice(0, -end.length);
+      }
+    }
+  });
+  let href = content;
+  const lowerHref = href.toLowerCase();
+  if (!lowerHref.startsWith('http') && !lowerHref.startsWith('ftp') &&
+      !lowerHref.startsWith('mailto')) {
+    // Prepend google-internal short links with http to
+    // prevent HTTPS error interstitial.
+    // SHORT_LINK_RE should not be used here as it might be
+    // in the middle of another match() process in an outer loop.
+    if (GOOG_SHORT_LINK_RE.test(lowerHref)) {
+      href = 'http://' + href;
+    } else {
+      href = 'https://' + href;
+    }
+    GOOG_SHORT_LINK_RE.lastIndex = 0;
+  }
+  textRuns.push({content: content, tag: 'a', href: href});
+  if (trailing.length) {
+    textRuns.push({content: trailing});
+  }
+  return textRuns;
+}
+
+function ReplaceRevisionRef(
+    match, _components, _currentProjectName, revisionUrlFormat) {
+  const content = match[0];
+  const href = revisionUrlFormat.replace('{revnum}', match[REV_NUM_GROUP]);
+  return [{content: content, tag: 'a', href: href}];
+}
+
+// Create custom textrun functions.
+function createIssueRefRun(projectName, localId, summary, isClosed, content,
+    commentId) {
+  return {
+    tag: 'a',
+    css: isClosed ? 'strike-through' : '',
+    href: `/p/${projectName}/issues/detail?id=${localId}${commentId}`,
+    title: summary || '',
+    content: content,
+  };
+}
+
+/**
+ * @typedef {Object} CommentReference
+ * @property {string} componentName A key identifying the kind of autolinking
+ *   text the reference matches.
+ * @property {Array<any>} existingRefs Array of full data for referenced
+ *   Objects. Each entry in this Array could be any kind of data depending
+ *   on what the text references. For example, the Array could contain Issue
+ *   or User Objects.
+ */
+
+/**
+ * Iterates through a list of comments, requests data for referenced objects
+ * in those comments, and returns all fetched data.
+ * @param {Array<IssueComment>} comments Array of comments to check.
+ * @param {string} currentProjectName Project these comments exist in the
+ *   context of.
+ * @return {Promise<Array<CommentReference>>}
+ */
+function getReferencedArtifacts(comments, currentProjectName) {
+  return new Promise((resolve, reject) => {
+    const fetchPromises = [];
+    Components.forEach(({lookup, extractRefs, refRegs}, componentName) => {
+      if (lookup !== null) {
+        const refs = [];
+        refRegs.forEach((re) => {
+          let match;
+          comments.forEach((comment) => {
+            while ((match = re.exec(comment.content)) !== null) {
+              refs.push(...extractRefs(match, currentProjectName));
+            };
+          });
+        });
+        if (refs.length) {
+          fetchPromises.push(lookup(refs, componentName));
+        }
+      }
+    });
+    resolve(Promise.all(fetchPromises));
+  });
+}
+
+function markupAutolinks(
+    plainString, componentRefs, currentProjectName, revisionUrlFormat) {
+  plainString = plainString || '';
+  const chunks = plainString.trim().split(NEW_LINE_OR_BOLD_REGEX);
+  const textRuns = [];
+  chunks.filter(Boolean).forEach((chunk) => {
+    if (chunk.match(NEW_LINE_REGEX)) {
+      textRuns.push({tag: 'br'});
+    } else if (chunk.startsWith('<b>') && chunk.endsWith('</b>')) {
+      textRuns.push({content: chunk.slice(3, -4), tag: 'b'});
+    } else {
+      textRuns.push(
+          ...autolinkChunk(
+              chunk, componentRefs, currentProjectName, revisionUrlFormat));
+    }
+  });
+  return textRuns;
+}
+
+function autolinkChunk(
+    chunk, componentRefs, currentProjectName, revisionUrlFormat) {
+  let textRuns = [{content: chunk}];
+  Components.forEach(({refRegs, replacer}, componentName) => {
+    refRegs.forEach((re) => {
+      textRuns = applyLinks(
+          textRuns, replacer, re, componentRefs.get(componentName),
+          currentProjectName, revisionUrlFormat);
+    });
+  });
+  return textRuns;
+}
+
+function applyLinks(
+    textRuns, replacer, re, existingRefs, currentProjectName,
+    revisionUrlFormat) {
+  const resultRuns = [];
+  textRuns.forEach((textRun) => {
+    if (textRun.tag) {
+      resultRuns.push(textRun);
+    } else {
+      const content = textRun.content;
+      let pos = 0;
+      let match;
+      while ((match = re.exec(content)) !== null) {
+        if (match.index > pos) {
+          // Create textrun for content between previous and current match.
+          resultRuns.push({content: content.slice(pos, match.index)});
+        }
+        resultRuns.push(
+            ...replacer(
+                match, existingRefs, currentProjectName, revisionUrlFormat));
+        pos = match.index + match[0].length;
+      }
+      if (content.slice(pos) !== '') {
+        resultRuns.push({content: content.slice(pos)});
+      }
+    }
+  });
+  return resultRuns;
+}
+
+
+export const autolink = {Components, getReferencedArtifacts, markupAutolinks};
