private sanitizeHtml()

in functions/src/content.ts [48:201]


  private sanitizeHtml(
    repoId: string,
    page: string,
    config: ProjectConfig,
    html: string,
    branch: string
  ): string {
    // Links
    // * Links to page content files should go to our page
    // * Links to source files should go to github
    //
    // Images
    // * Images and other things should be made into githubusercontent links
    // * Remove badges

    let pageDir = "";
    if (page) {
      const lastSlash = page.lastIndexOf("/");
      pageDir = page.substring(0, lastSlash);
      if (lastSlash >= 0) {
        pageDir = page.substring(0, lastSlash);
      }
    }

    const projectBaseUrl = this.getProjectBaseUrl(repoId);

    // TODO: Dynamic branch
    const renderedBaseUrl = this.getRenderedContentBaseUrl(repoId, branch);
    const rawBaseUrl = urljoin(
      Github.getRawContentBaseUrl(repoId, branch),
      pageDir
    );

    const $: CheerioStatic = cheerio.load(html);

    // Make all code sections prettyprinted
    $("pre > code").each((_: number, el: CheerioElement) => {
      $(el).addClass("prettyprint");
    });

    // Resolve all relative links to github
    const that = this;
    $("a").each((_: number, el: CheerioElement) => {
      const href = el.attribs["href"];
      if (!href) {
        return;
      }

      if (that._isGithubLink(href)) {
        // Convert github.com/org/foo links to firebaseopensource links
        const hrefUrl = url.parse(href);

        const pathSegments = hrefUrl.pathname
          .split("/")
          .filter((seg: string) => seg.trim().length > 0);

        if (pathSegments.length === 2) {
          const org = pathSegments[0];
          const repo = pathSegments[1];

          if (!that._isIncludedProject(org, repo)) {
            return;
          }

          const newLink = "/projects/" + pathSegments.join("/") + "/";

          Logger.debug(repoId, `Replacing ${href} with ${newLink}.`);
          el.attribs["href"] = newLink.toLowerCase();
        }
      }

      if (that._isRelativeLink(href)) {
        // Check if the link is to a page within the repo
        const repoRelative = path.join(pageDir, href);
        const pageKeys = config.pages
          ? config.pages.map(page => page.path)
          : [];

        Logger.debug(
          repoId,
          `Relative link on page ${page}: ${href} --> ${repoRelative}`
        );
        el.attribs["href"] = repoRelative;

        const repoRelativeWithoutHash =
          repoRelative.indexOf("#") >= 0
            ? repoRelative.substring(0, repoRelative.indexOf("#"))
            : repoRelative;

        const isProjectPage = pageKeys.indexOf(repoRelativeWithoutHash) >= 0;
        if (isProjectPage) {
          that.lowercaseLink(el);
          that.deMarkdownLink(el);
          that.sanitizeRelativeLink(el, "href", projectBaseUrl);
          Logger.debug(
            repoId,
            `Sanitizing relative project link ${repoRelative} --> ${
              el.attribs["href"]
            }`
          );
        } else {
          that.sanitizeRelativeLink(el, "href", renderedBaseUrl);
          Logger.debug(
            repoId,
            `Sanitizing relative GitHub link ${repoRelative} --> ${
              el.attribs["href"]
            }`
          );
        }
      }
    });

    // Resolve all relative images, add class to parent
    $("img").each((_: number, el: CheerioElement) => {
      const src = el.attribs["src"];
      if (!src) {
        return;
      }

      const badgePatterns = [
        "travis-ci.org",
        "shields.io",
        "coveralls.io",
        "badge.fury.io",
        "gitter.im",
        "circleci.com",
        "opencollective.com",
        "cirrus-ci.com",
        "sonarcloud.io",
        "codecov.io",
        "release-notes.com",
        /github\.com\/.*\/workflows\/.*\.svg/,
        "awesome.re"
      ];

      const isBadge = badgePatterns.some(pattern => {
        return !!src.match(pattern);
      });

      if (isBadge) {
        // Mark Badges
        $(el).addClass("img-badge");
      } else {
        // Add the image-parent class to the parent
        $(el)
          .parent()
          .addClass("img-parent");
      }

      that.sanitizeRelativeLink(el, "src", rawBaseUrl);
    });

    return $.html();
  }