function addError (pagePath, str, message) {
  if (!errors[pagePath]) { errors[pagePath] = []; }
  errors[pagePath].push({
    message: message,
    str: str
  });
  errorCount++;
}
/*.md');
pages.forEach(function checkPage (pagePath) {
  var match;
  var referencedMatch;
  var referencingMatch;
  var referencingRegex;
  var urlRegex;

  let content = fs.readFileSync(pagePath, 'utf-8');

  // Check prose with `write-good`.
  checkProse(pagePath, content);

  // Inline links: `[link](../page.md)`
  let inlineLinkRegex = /\[.*?\]\((.*?)\)/g;
  match = inlineLinkRegex.exec(content);
  while (match !== null) {
    if (!checkLink(pagePath, match[1])) {
      addError(pagePath, match[0], 'Page does not exist');
    }
    match = inlineLinkRegex.exec(content);
  }

  // Referenced links: `[link][page] -> [page]: ../page.md`
  let referencedLinkRegex = /\[.*?\]\[(.*?)\]/g;
  match = referencedLinkRegex.exec(content);
  while (match !== null) {
    urlRegex = new RegExp(`\\[${match[1]}\\]: \(\.\*\)`, 'g');
    referencedMatch = urlRegex.exec(content);

    if (referencedMatch) {
      if (!checkLink(pagePath, referencedMatch[1])) {
        addError(pagePath, referencedMatch[0], 'Page does not exist');
      }
    } else {
      addError(pagePath, match[0], 'Link definition does not exist');
    }

    match = referencedLinkRegex.exec(content);
  }

  // Unused defined links: `[page]: ../page.md -> [*][page]`
  let referenceRegex = new RegExp('\\[\(\.\*\)\?\\]: \.\*', 'g');
  match = referenceRegex.exec(content);
  while (match !== null) {
    referencingRegex = new RegExp(`\\[${match[1]}\\]`, 'g');
    referencingMatch = referencingRegex.exec(content);
    if (!referencingMatch) {
      addError(pagePath, match[1], 'Link definition not being used');
    }
    match = referenceRegex.exec(content);
  }
});

function checkLink (pagePath, url) {
  var absPath;
  var content;
  var hash;
  var headingMatch;
  var headingRegex;
  var headingIds;
  var urlPath;

  // Relative path.
  if (url.indexOf('.') === 0) {
    // Check page exists.
    urlPath = url.split('#')[0];
    absPath = path.resolve(pagePath, `../${urlPath}`);
    if (!fs.existsSync(absPath)) { return false; }
    if (url.indexOf('#') === -1) { return true; }

    // Check hash / anchor heading.
    headingIds = [];
    hash = url.split('#')[1];
    headingRegex = /#+\s+(.*?)\n/g;
    content = fs.readFileSync(absPath, 'utf-8');
    headingMatch = headingRegex.exec(content);
    while (headingMatch !== null) {
      headingIds.push(convertHeading(headingMatch[1]));
      headingMatch = headingRegex.exec(content);
    }
    return headingIds.indexOf(hash) !== -1;
  }

  return true;
}

function convertHeading (heading) {
  return heading
    .replace(/#+\s+/, '')
    .toLowerCase()
    .replace(/`\./g, '')  // Remove leading dot.
    .replace(/[`*\(\),]/g, '')  // Remove special characters.
    .replace(/[^\w]+/g, '-')
    .replace(/-$/g, '');
}

function checkProse (pagePath, content) {
  content = content.replace(/^---[\s\S]*?---/g, '');  // Remove metadata.
  content = content.replace(/(\|.*\|)+/g, '');  // Remove tables.
  content = content.replace(/```[\s\S]*?```/g, '');  // Remove code blocks.
  content = content.replace(/`[\s\S]*?`/g, '');  // Remove inline code.
  content = content.replace(/\n#+.