static collectCanonicalURLs(linkElements) {
    /** @type {Set<string>} */
    const uniqueCanonicalURLs = new Set();
    /** @type {Set<string>} */
    const hreflangURLs = new Set();

    /** @type {LH.Artifacts.LinkElement|undefined} */
    let invalidCanonicalLink;
    /** @type {LH.Artifacts.LinkElement|undefined} */
    let relativeCanonicallink;
    for (const link of linkElements) {
      // Links in the body aren't canonical references for SEO, skip them
      /** @see https://html.spec.whatwg.org/multipage/links.html#body-ok */
      if (link.source === 'body') continue;

      if (link.rel === 'canonical') {
        // Links that don't have an href aren't canonical references for SEO, skip them
        if (!link.hrefRaw) continue;

        // Links that had an hrefRaw but didn't have a valid href were invalid, flag them
        if (!link.href) invalidCanonicalLink = link;
        // Links that had a valid href but didn't have a valid hrefRaw must have been relatively resolved, flag them
        else if (!UrlUtils.isValid(link.hrefRaw)) relativeCanonicallink = link;
        // Otherwise, it was a valid canonical URL
        else uniqueCanonicalURLs.add(link.href);
      } else if (link.rel === 'alternate') {
        if (link.href && link.hreflang) hreflangURLs.add(link.href);
      }
    }

    return {uniqueCanonicalURLs, hreflangURLs, invalidCanonicalLink, relativeCanonicallink};
  }
@param {LH.Artifacts.LinkElement[]} linkElements
@return {CanonicalURLData}