Loading
Get Your Head in Order

Get your <head> in order

How you order elements in the <head> can have an effect on the (perceived) performance of the page.

This snippet code is from capo.js (opens in a new tab) the Rick Viscomi (opens in a new tab) script

Snippet

(() => {
  function $parcel$export(e, n, v, s) {
    Object.defineProperty(e, n, {
      get: v,
      set: s,
      enumerable: true,
      configurable: true,
    });
  }
  const $eb5be8077a65b10b$var$Hues = {
    PINK: 320,
    BLUE: 200,
  };
  function $eb5be8077a65b10b$export$921514c0345db5eb(hue) {
    return [
      `oklch(5% .1 ${hue})`,
      `oklch(13% .2 ${hue})`,
      `oklch(25% .2 ${hue})`,
      `oklch(35% .25 ${hue})`,
      `oklch(50% .27 ${hue})`,
      `oklch(67% .31 ${hue})`,
      `oklch(72% .25 ${hue})`,
      `oklch(80% .2 ${hue})`,
      `oklch(90% .1 ${hue})`,
      `oklch(99% .05 ${hue})`,
      "#ccc",
    ];
  }
  const $eb5be8077a65b10b$export$e6952b12ade67489 = [
    "#9e0142",
    "#d53e4f",
    "#f46d43",
    "#fdae61",
    "#fee08b",
    "#e6f598",
    "#abdda4",
    "#66c2a5",
    "#3288bd",
    "#5e4fa2",
    "#cccccc",
  ];
  const $eb5be8077a65b10b$export$d68d0fda4a10dbc2 =
    $eb5be8077a65b10b$export$921514c0345db5eb($eb5be8077a65b10b$var$Hues.PINK);
  const $eb5be8077a65b10b$export$738c3b9a44c87ecc =
    $eb5be8077a65b10b$export$921514c0345db5eb($eb5be8077a65b10b$var$Hues.BLUE);
  const $eb5be8077a65b10b$export$9a82c28ef488e918 = {
    DEFAULT: $eb5be8077a65b10b$export$e6952b12ade67489,
    PINK: $eb5be8077a65b10b$export$d68d0fda4a10dbc2,
    BLUE: $eb5be8077a65b10b$export$738c3b9a44c87ecc,
  };
  function $eb5be8077a65b10b$export$18c940335d915715(elementColor) {
    let invalidColor = "#cccccc";
    if (elementColor == invalidColor) invalidColor = "red";
    return `repeating-linear-gradient(45deg, ${elementColor}, ${elementColor} 3px, ${invalidColor} 3px, ${invalidColor} 6px)`;
  }
 
  var $d410929ede0a2ee4$exports = {};
 
  $parcel$export(
    $d410929ede0a2ee4$exports,
    "IO",
    () => $d410929ede0a2ee4$export$8f8422ac5947a789,
  );
 
  class $d410929ede0a2ee4$export$8f8422ac5947a789 {
    constructor(document1, options, output = window.console) {
      this.document = document1;
      this.options = options;
      this.console = output;
      this.isStaticHead = false;
      this.head = null;
    }
    async init() {
      if (this.head) return;
      if (this.options.prefersDynamicAssessment()) {
        this.head = this.document.querySelector("head");
        return;
      }
      try {
        let html = await this.getStaticHTML();
        html = html.replace(/(\<\/?)(head)/gi, "$1static-head");
        const staticDoc =
          this.document.implementation.createHTMLDocument("New Document");
        staticDoc.documentElement.innerHTML = html;
        this.head = staticDoc.querySelector("static-head");
        if (this.head) this.isStaticHead = true;
        else this.head = this.document.head;
      } catch (e) {
        this.console.error(
          `${this.options.loggingPrefix}An exception occurred while getting the static <head>:`,
          e,
        );
        this.head = this.document.head;
      }
      if (!this.isStaticHead)
        this.console.warn(
          `${this.options.loggingPrefix}Unable to parse the static (server-rendered) <head>. Falling back to document.head`,
          this.head,
        );
    }
    async getStaticHTML() {
      const url = this.document.location.href;
      const response = await fetch(url);
      return await response.text();
    }
    getHead() {
      return this.head;
    }
    stringifyElement(element) {
      return element.getAttributeNames().reduce((id, attr) => {
        return (id += `[${CSS.escape(attr)}=${JSON.stringify(
          element.getAttribute(attr),
        )}]`);
      }, element.nodeName);
    }
    getLoggableElement(element) {
      if (!this.isStaticHead) return element;
      const selector = this.stringifyElement(element);
      const candidates = Array.from(
        this.document.head.querySelectorAll(selector),
      );
      if (candidates.length == 0) return element;
      if (candidates.length == 1) return candidates[0];
      // The way the static elements are parsed makes their innerHTML different.
      // Recreate the element in DOM and compare its innerHTML with those of the candidates.
      // This ensures a consistent parsing and positive string matches.
      const candidateWrapper = this.document.createElement("div");
      const elementWrapper = this.document.createElement("div");
      elementWrapper.innerHTML = element.innerHTML;
      const candidate = candidates.find((c) => {
        candidateWrapper.innerHTML = c.innerHTML;
        return candidateWrapper.innerHTML == elementWrapper.innerHTML;
      });
      if (candidate) return candidate;
      return element;
    }
    // Note: AI-generated function.
    createElementFromSelector(selector) {
      // Extract the tag name from the selector
      const tagName = selector.match(/^[A-Za-z]+/)[0];
      if (!tagName) return;
      // Create the new element
      const element = document.createElement(tagName);
      // Extract the attribute key-value pairs from the selector
      const attributes = selector.match(/\[([A-Za-z-]+)="([^"]+)"\]/g) || [];
      // Set the attributes on the new element
      attributes.forEach((attribute) => {
        const [key, value] = attribute
          .replace("[", "")
          .replace("]", "")
          .split("=");
        element.setAttribute(key, value.slice(1, -1));
      });
      return element;
    }
    logElementFromSelector({
      weight: weight,
      selector: selector,
      innerHTML: innerHTML,
      isValid: isValid,
      customValidations: customValidations = {},
    }) {
      weight = +weight;
      const viz = this.getElementVisualization(weight);
      let element = this.createElementFromSelector(selector);
      element.innerHTML = innerHTML;
      element = this.getLoggableElement(element);
      this.logElement({
        viz: viz,
        weight: weight,
        element: element,
        isValid: isValid,
        customValidations: customValidations,
      });
    }
    logElement({
      viz: viz,
      weight: weight,
      element: element,
      isValid: isValid,
      customValidations: customValidations,
      omitPrefix: omitPrefix = false,
    }) {
      if (!omitPrefix)
        viz.visual = `${this.options.loggingPrefix}${viz.visual}`;
      let loggingLevel = "log";
      const args = [viz.visual, viz.style, weight + 1, element];
      if (!this.options.isValidationEnabled()) {
        this.console[loggingLevel](...args);
        return;
      }
      const { payload: payload, warnings: warnings } = customValidations;
      if (payload) args.push(payload);
      if (warnings?.length) {
        // Element-specific warnings.
        loggingLevel = "warn";
        warnings.forEach((warning) => args.push(`❌ ${warning}`));
      } else if (
        !isValid &&
        (this.options.prefersDynamicAssessment() || this.isStaticHead)
      ) {
        // General warnings.
        loggingLevel = "warn";
        args.push(`❌ invalid element (${element.tagName})`);
      }
      this.console[loggingLevel](...args);
    }
    logValidationWarnings(warnings) {
      if (!this.options.isValidationEnabled()) return;
      warnings.forEach(
        ({ warning: warning, elements: elements = [], element: element }) => {
          elements = elements.map(this.getLoggableElement.bind(this));
          this.console.warn(
            `${this.options.loggingPrefix}${warning}`,
            ...elements,
            element || "",
          );
        },
      );
    }
    getColor(weight) {
      return this.options.palette[10 - weight];
    }
    getHeadVisualization(elements) {
      let visual = "";
      const styles = [];
      elements.forEach(({ weight: weight, isValid: isValid }) => {
        visual += "%c ";
        const color = this.getColor(weight);
        let style = `padding: 5px; margin: 0 -1px; `;
        if (isValid) style += `background-color: ${color};`;
        else
          style += `background-image: ${(0,
          $eb5be8077a65b10b$export$18c940335d915715)(color)}`;
        styles.push(style);
      });
      return {
        visual: visual,
        styles: styles,
      };
    }
    getElementVisualization(weight) {
      const visual = `%c${new Array(weight + 1).fill("█").join("")}`;
      const color = this.getColor(weight);
      const style = `color: ${color}`;
      return {
        visual: visual,
        style: style,
      };
    }
    visualizeHead(groupName, headElement, headWeights) {
      const headViz = this.getHeadVisualization(headWeights);
      this.console.groupCollapsed(
        `${this.options.loggingPrefix}${groupName} %chead%c order\n${headViz.visual}`,
        "font-family: monospace",
        "font-family: inherit",
        ...headViz.styles,
      );
      headWeights.forEach(
        ({
          weight: weight,
          element: element,
          isValid: isValid,
          customValidations: customValidations,
        }) => {
          const viz = this.getElementVisualization(weight);
          this.logElement({
            viz: viz,
            weight: weight,
            element: element,
            isValid: isValid,
            customValidations: customValidations,
            omitPrefix: true,
          });
        },
      );
      this.console.log(
        `${groupName} %chead%c element`,
        "font-family: monospace",
        "font-family: inherit",
        headElement,
      );
      this.console.groupEnd();
    }
  }
 
  var $5b739339de321a37$exports = {};
 
  $parcel$export(
    $5b739339de321a37$exports,
    "Options",
    () => $5b739339de321a37$export$c019608e5b5bb4cb,
  );
 
  class $5b739339de321a37$export$c019608e5b5bb4cb {
    constructor({
      preferredAssessmentMode:
        preferredAssessmentMode = $5b739339de321a37$export$c019608e5b5bb4cb
          .AssessmentMode.STATIC,
      validation: validation = true,
      palette: palette = $eb5be8077a65b10b$export$e6952b12ade67489,
      loggingPrefix: loggingPrefix = "Capo: ",
    } = {}) {
      this.setPreferredAssessmentMode(preferredAssessmentMode);
      this.setValidation(validation);
      this.setPalette(palette);
      this.setLoggingPrefix(loggingPrefix);
    }
    static get AssessmentMode() {
      return {
        STATIC: "static",
        DYNAMIC: "dynamic",
      };
    }
    static get Palettes() {
      return $eb5be8077a65b10b$export$9a82c28ef488e918;
    }
    prefersStaticAssessment() {
      return (
        this.preferredAssessmentMode ===
        $5b739339de321a37$export$c019608e5b5bb4cb.AssessmentMode.STATIC
      );
    }
    prefersDynamicAssessment() {
      return (
        this.preferredAssessmentMode ===
        $5b739339de321a37$export$c019608e5b5bb4cb.AssessmentMode.DYNAMIC
      );
    }
    isValidationEnabled() {
      return this.validation;
    }
    setPreferredAssessmentMode(preferredAssessmentMode) {
      if (!this.isValidAssessmentMode(preferredAssessmentMode))
        throw new Error(
          `Invalid option: preferred assessment mode, expected AssessmentMode.STATIC or AssessmentMode.DYNAMIC, got "${preferredAssessmentMode}".`,
        );
      this.preferredAssessmentMode = preferredAssessmentMode;
    }
    setPreferredAssessmentModeToStatic(prefersStatic) {
      let mode =
        $5b739339de321a37$export$c019608e5b5bb4cb.AssessmentMode.STATIC;
      if (!prefersStatic)
        mode = $5b739339de321a37$export$c019608e5b5bb4cb.AssessmentMode.DYNAMIC;
      this.setPreferredAssessmentMode(mode);
    }
    setValidation(validation) {
      if (!this.isValidValidation(validation))
        throw new Error(
          `Invalid option: validation, expected boolean, got "${validation}".`,
        );
      this.validation = validation;
    }
    setPalette(palette) {
      if (!this.isValidPalette(palette))
        throw new Error(
          `Invalid option: palette, expected [${Object.keys(
            $eb5be8077a65b10b$export$9a82c28ef488e918,
          ).join("|")}] or an array of colors, got "${palette}".`,
        );
      if (typeof palette === "string") {
        this.palette = $eb5be8077a65b10b$export$9a82c28ef488e918[palette];
        return;
      }
      this.palette = palette;
    }
    setLoggingPrefix(loggingPrefix) {
      if (!this.isValidLoggingPrefix(loggingPrefix))
        throw new Error(
          `Invalid option: logging prefix, expected string, got "${loggingPrefix}".`,
        );
      this.loggingPrefix = loggingPrefix;
    }
    isValidAssessmentMode(assessmentMode) {
      return Object.values(
        $5b739339de321a37$export$c019608e5b5bb4cb.AssessmentMode,
      ).includes(assessmentMode);
    }
    isValidValidation(validation) {
      return typeof validation === "boolean";
    }
    isValidPalette(palette) {
      if (typeof palette === "string")
        return Object.keys($eb5be8077a65b10b$export$9a82c28ef488e918).includes(
          palette,
        );
      if (!Array.isArray(palette)) return false;
      return (
        palette.length === 11 &&
        palette.every((color) => typeof color === "string")
      );
    }
    isValidLoggingPrefix(loggingPrefix) {
      return typeof loggingPrefix === "string";
    }
    isPreferredPalette(palette) {
      return JSON.stringify(this.palette) == JSON.stringify(palette);
    }
    valueOf() {
      return {
        preferredAssessmentMode: this.preferredAssessmentMode,
        validation: this.validation,
        palette: this.palette,
        loggingPrefix: this.loggingPrefix,
      };
    }
  }
 
  var $9c3989fcb9437829$exports = {};
 
  $parcel$export(
    $9c3989fcb9437829$exports,
    "ElementWeights",
    () => $9c3989fcb9437829$export$881088883fcab450,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "ElementDetectors",
    () => $9c3989fcb9437829$export$6ade8bb3620eb74b,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isMeta",
    () => $9c3989fcb9437829$export$daeb0db0c224decd,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isTitle",
    () => $9c3989fcb9437829$export$e55aad21605f020a,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isPreconnect",
    () => $9c3989fcb9437829$export$a3316bd0a640eb8b,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isAsyncScript",
    () => $9c3989fcb9437829$export$20e2051ffd813ee3,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isImportStyles",
    () => $9c3989fcb9437829$export$be443fc6335656f0,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isSyncScript",
    () => $9c3989fcb9437829$export$65983fc0a5543400,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isSyncStyles",
    () => $9c3989fcb9437829$export$9d6cdbffb13bee21,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isPreload",
    () => $9c3989fcb9437829$export$226ad5ba23be83f0,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isDeferScript",
    () => $9c3989fcb9437829$export$3d269f86e8bd1d24,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isPrefetchPrerender",
    () => $9c3989fcb9437829$export$4d2ed086e1fec499,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "META_HTTP_EQUIV_KEYWORDS",
    () => $9c3989fcb9437829$export$b7417cf4a2235f73,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isOriginTrial",
    () => $9c3989fcb9437829$export$38a04d482ec50f88,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "isMetaCSP",
    () => $9c3989fcb9437829$export$14b1a2f64a600585,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "getWeight",
    () => $9c3989fcb9437829$export$de32fe5d64aee40c,
  );
  $parcel$export(
    $9c3989fcb9437829$exports,
    "getHeadWeights",
    () => $9c3989fcb9437829$export$5cc4a311ddbe699c,
  );
  const $9c3989fcb9437829$export$881088883fcab450 = {
    META: 10,
    TITLE: 9,
    PRECONNECT: 8,
    ASYNC_SCRIPT: 7,
    IMPORT_STYLES: 6,
    SYNC_SCRIPT: 5,
    SYNC_STYLES: 4,
    PRELOAD: 3,
    DEFER_SCRIPT: 2,
    PREFETCH_PRERENDER: 1,
    OTHER: 0,
  };
  const $9c3989fcb9437829$export$6ade8bb3620eb74b = {
    META: $9c3989fcb9437829$export$daeb0db0c224decd,
    TITLE: $9c3989fcb9437829$export$e55aad21605f020a,
    PRECONNECT: $9c3989fcb9437829$export$a3316bd0a640eb8b,
    ASYNC_SCRIPT: $9c3989fcb9437829$export$20e2051ffd813ee3,
    IMPORT_STYLES: $9c3989fcb9437829$export$be443fc6335656f0,
    SYNC_SCRIPT: $9c3989fcb9437829$export$65983fc0a5543400,
    SYNC_STYLES: $9c3989fcb9437829$export$9d6cdbffb13bee21,
    PRELOAD: $9c3989fcb9437829$export$226ad5ba23be83f0,
    DEFER_SCRIPT: $9c3989fcb9437829$export$3d269f86e8bd1d24,
    PREFETCH_PRERENDER: $9c3989fcb9437829$export$4d2ed086e1fec499,
  };
  const $9c3989fcb9437829$export$b7417cf4a2235f73 = [
    "accept-ch",
    "content-security-policy",
    "content-type",
    "default-style",
    "delegate-ch",
    "origin-trial",
    "x-dns-prefetch-control",
  ];
  function $9c3989fcb9437829$export$daeb0db0c224decd(element) {
    const httpEquivSelector = $9c3989fcb9437829$export$b7417cf4a2235f73
      .map((keyword) => {
        return `[http-equiv="${keyword}" i]`;
      })
      .join(", ");
    return element.matches(
      `meta:is([charset], ${httpEquivSelector}, [name=viewport]), base`,
    );
  }
  function $9c3989fcb9437829$export$e55aad21605f020a(element) {
    return element.matches("title");
  }
  function $9c3989fcb9437829$export$a3316bd0a640eb8b(element) {
    return element.matches("link[rel=preconnect]");
  }
  function $9c3989fcb9437829$export$20e2051ffd813ee3(element) {
    return element.matches("script[src][async]");
  }
  function $9c3989fcb9437829$export$be443fc6335656f0(element) {
    const importRe = /@import/;
    if (element.matches("style")) return importRe.test(element.textContent);
    /* TODO: Support external stylesheets.
  if (element.matches('link[rel=stylesheet][href]')) {
    let response = fetch(element.href);
    response = response.text();
    return importRe.test(response);
  } */ return false;
  }
  function $9c3989fcb9437829$export$65983fc0a5543400(element) {
    return element.matches(
      "script:not([src][defer],[src][type=module],[src][async],[type*=json])",
    );
  }
  function $9c3989fcb9437829$export$9d6cdbffb13bee21(element) {
    return element.matches("link[rel=stylesheet],style");
  }
  function $9c3989fcb9437829$export$226ad5ba23be83f0(element) {
    return element.matches("link:is([rel=preload], [rel=modulepreload])");
  }
  function $9c3989fcb9437829$export$3d269f86e8bd1d24(element) {
    return element.matches(
      "script[src][defer], script:not([src][async])[src][type=module]",
    );
  }
  function $9c3989fcb9437829$export$4d2ed086e1fec499(element) {
    return element.matches(
      "link:is([rel=prefetch], [rel=dns-prefetch], [rel=prerender])",
    );
  }
  function $9c3989fcb9437829$export$38a04d482ec50f88(element) {
    return element.matches('meta[http-equiv="origin-trial"i]');
  }
  function $9c3989fcb9437829$export$14b1a2f64a600585(element) {
    return element.matches(
      'meta[http-equiv="Content-Security-Policy" i], meta[http-equiv="Content-Security-Policy-Report-Only" i]',
    );
  }
  function $9c3989fcb9437829$export$de32fe5d64aee40c(element) {
    for (let [id, detector] of Object.entries(
      $9c3989fcb9437829$export$6ade8bb3620eb74b,
    )) {
      if (detector(element))
        return $9c3989fcb9437829$export$881088883fcab450[id];
    }
    return $9c3989fcb9437829$export$881088883fcab450.OTHER;
  }
  function $9c3989fcb9437829$export$5cc4a311ddbe699c(head) {
    const headChildren = Array.from(head.children);
    return headChildren.map((element) => {
      return {
        element: element,
        weight: $9c3989fcb9437829$export$de32fe5d64aee40c(element),
      };
    });
  }
 
  var $580f7ed6bc170ae8$exports = {};
 
  $parcel$export(
    $580f7ed6bc170ae8$exports,
    "VALID_HEAD_ELEMENTS",
    () => $580f7ed6bc170ae8$export$79e124b7caef7aa9,
  );
  $parcel$export(
    $580f7ed6bc170ae8$exports,
    "PRELOAD_SELECTOR",
    () => $580f7ed6bc170ae8$export$5540ac2a18901364,
  );
  $parcel$export(
    $580f7ed6bc170ae8$exports,
    "isValidElement",
    () => $580f7ed6bc170ae8$export$a8257692ac88316c,
  );
  $parcel$export(
    $580f7ed6bc170ae8$exports,
    "hasValidationWarning",
    () => $580f7ed6bc170ae8$export$eeefd08c3a6f8db7,
  );
  $parcel$export(
    $580f7ed6bc170ae8$exports,
    "getValidationWarnings",
    () => $580f7ed6bc170ae8$export$b01ab94d0cd042a0,
  );
  $parcel$export(
    $580f7ed6bc170ae8$exports,
    "getCustomValidations",
    () => $580f7ed6bc170ae8$export$6c93e2175c028eeb,
  );
 
  const $580f7ed6bc170ae8$export$79e124b7caef7aa9 = new Set([
    "base",
    "link",
    "meta",
    "noscript",
    "script",
    "style",
    "template",
    "title",
  ]);
  const $580f7ed6bc170ae8$export$5540ac2a18901364 =
    'link:is([rel="preload" i], [rel="modulepreload" i])';
  function $580f7ed6bc170ae8$export$a8257692ac88316c(element) {
    return $580f7ed6bc170ae8$export$79e124b7caef7aa9.has(
      element.tagName.toLowerCase(),
    );
  }
  function $580f7ed6bc170ae8$export$eeefd08c3a6f8db7(element) {
    // Element itself is not valid.
    if (!$580f7ed6bc170ae8$export$a8257692ac88316c(element)) return true;
    // Children are not valid.
    if (
      element.matches(
        `:has(:not(${Array.from($580f7ed6bc170ae8$export$79e124b7caef7aa9).join(
          ", ",
        )}))`,
      )
    )
      return true;
    // <title> is not the first of its type.
    if (element.matches("title:is(:nth-of-type(n+2))")) return true;
    // <base> is not the first of its type.
    if (element.matches("base:has(~ base), base ~ base")) return true;
    // CSP meta tag anywhere.
    if ((0, $9c3989fcb9437829$export$14b1a2f64a600585)(element)) return true;
    // Origin trial expired or cross-origin.
    if ($580f7ed6bc170ae8$var$isInvalidOriginTrial(element)) return true;
    // Preload is unnecessary.
    if ($580f7ed6bc170ae8$var$isUnnecessaryPreload(element)) return true;
    return false;
  }
  function $580f7ed6bc170ae8$export$b01ab94d0cd042a0(head) {
    const validationWarnings = [];
    const titleElements = Array.from(head.querySelectorAll("title"));
    const titleElementCount = titleElements.length;
    if (titleElementCount != 1)
      validationWarnings.push({
        warning: `Expected exactly 1 <title> element, found ${titleElementCount}`,
        elements: titleElements,
      });
    const baseElements = Array.from(head.querySelectorAll("base"));
    const baseElementCount = baseElements.length;
    if (baseElementCount > 1)
      validationWarnings.push({
        warning: `Expected at most 1 <base> element, found ${baseElementCount}`,
        elements: baseElements,
      });
    const metaCSP = head.querySelector(
      'meta[http-equiv="Content-Security-Policy" i]',
    );
    if (metaCSP)
      validationWarnings.push({
        warning:
          "CSP meta tags disable the preload scanner due to a bug in Chrome. Use the CSP header instead. Learn more: https://crbug.com/1458493",
        element: metaCSP,
      });
    head.querySelectorAll("*").forEach((element) => {
      if ($580f7ed6bc170ae8$export$a8257692ac88316c(element)) return;
      let root = element;
      while (root.parentElement != head) root = root.parentElement;
      validationWarnings.push({
        warning: `${element.tagName} elements are not allowed in the <head>`,
        element: root,
      });
    });
    const originTrials = Array.from(
      head.querySelectorAll('meta[http-equiv="Origin-Trial" i]'),
    );
    originTrials.forEach((element) => {
      const metadata = $580f7ed6bc170ae8$var$validateOriginTrial(element);
      if (metadata.warnings.length == 0) return;
      validationWarnings.push({
        warning: `Invalid origin trial token: ${metadata.warnings.join(", ")}`,
        elements: [element],
        element: metadata.payload,
      });
    });
    return validationWarnings;
  }
  function $580f7ed6bc170ae8$export$6c93e2175c028eeb(element) {
    if ((0, $9c3989fcb9437829$export$38a04d482ec50f88)(element))
      return $580f7ed6bc170ae8$var$validateOriginTrial(element);
    if ((0, $9c3989fcb9437829$export$14b1a2f64a600585)(element))
      return $580f7ed6bc170ae8$var$validateCSP(element);
    if ($580f7ed6bc170ae8$var$isUnnecessaryPreload(element))
      return $580f7ed6bc170ae8$var$validateUnnecessaryPreload(element);
    return {};
  }
  function $580f7ed6bc170ae8$var$validateCSP(element) {
    const warnings = [];
    if (
      element.matches(
        'meta[http-equiv="Content-Security-Policy-Report-Only" i]',
      )
    )
      //https://w3c.github.io/webappsec-csp/#meta-element
      warnings.push("CSP Report-Only is forbidden in meta tags");
    else if (element.matches('meta[http-equiv="Content-Security-Policy" i]'))
      warnings.push("meta CSP discouraged. See https://crbug.com/1458493.");
    return {
      warnings: warnings,
    };
  }
  function $580f7ed6bc170ae8$var$isInvalidOriginTrial(element) {
    if (!(0, $9c3989fcb9437829$export$38a04d482ec50f88)(element)) return false;
    const { warnings: warnings } =
      $580f7ed6bc170ae8$var$validateOriginTrial(element);
    return warnings.length > 0;
  }
  function $580f7ed6bc170ae8$var$validateOriginTrial(element) {
    const metadata = {
      payload: null,
      warnings: [],
    };
    const token = element.getAttribute("content");
    try {
      metadata.payload = $580f7ed6bc170ae8$var$decodeOriginTrialToken(token);
      if (metadata.payload.expiry < new Date())
        metadata.warnings.push("expired");
      if (
        !metadata.payload.isThirdParty &&
        !$580f7ed6bc170ae8$var$isSameOrigin(
          metadata.payload.origin,
          document.location.href,
        )
      )
        metadata.warnings.push("invalid origin");
    } catch {
      metadata.warnings.push("invalid token");
    }
    return metadata;
  }
  // Adapted from https://glitch.com/~ot-decode.
  function $580f7ed6bc170ae8$var$decodeOriginTrialToken(token) {
    const buffer = new Uint8Array([...atob(token)].map((a) => a.charCodeAt(0)));
    const view = new DataView(buffer.buffer);
    const length = view.getUint32(65, false);
    const payload = JSON.parse(
      new TextDecoder().decode(buffer.slice(69, 69 + length)),
    );
    payload.expiry = new Date(payload.expiry * 1000);
    return payload;
  }
  function $580f7ed6bc170ae8$var$isSameOrigin(a, b) {
    return new URL(a).origin === new URL(b).origin;
  }
  function $580f7ed6bc170ae8$var$isUnnecessaryPreload(element) {
    if (!element.matches($580f7ed6bc170ae8$export$5540ac2a18901364))
      return false;
    const href = element.getAttribute("href");
    if (!href) return false;
    const preloadedUrl = $580f7ed6bc170ae8$var$absolutifyUrl(href);
    return (
      $580f7ed6bc170ae8$var$findElementWithSource(
        element.parentElement,
        preloadedUrl,
      ) != null
    );
  }
  function $580f7ed6bc170ae8$var$findElementWithSource(root, sourceUrl) {
    const linksAndScripts = Array.from(
      root.querySelectorAll(
        `link:not(${$580f7ed6bc170ae8$export$5540ac2a18901364}), script`,
      ),
    );
    return linksAndScripts.find((e) => {
      const src = e.getAttribute("href") || e.getAttribute("src");
      if (!src) return false;
      return sourceUrl == $580f7ed6bc170ae8$var$absolutifyUrl(src);
    });
  }
  function $580f7ed6bc170ae8$var$absolutifyUrl(href) {
    return new URL(href, document.baseURI).href;
  }
  function $580f7ed6bc170ae8$var$validateUnnecessaryPreload(element) {
    const href = element.getAttribute("href");
    const preloadedUrl = $580f7ed6bc170ae8$var$absolutifyUrl(href);
    const preloadedElement = $580f7ed6bc170ae8$var$findElementWithSource(
      element.parentElement,
      preloadedUrl,
    );
    if (!preloadedElement)
      throw new Error("Expected an invalid preload, but none found.");
    return {
      warnings: [
        `This preload has little to no effect. ${href} is already discoverable by another ${preloadedElement.tagName} element.`,
      ],
    };
  }
 
  function $0eec6c831ab0f90a$export$8679af897d1c058e(io, validation) {
    const validationWarnings = validation.getValidationWarnings(io.getHead());
    io.logValidationWarnings(validationWarnings);
  }
  function $0eec6c831ab0f90a$export$b65597cffe09aebc(io, validation, rules) {
    const headElement = io.getHead();
    const headWeights = rules
      .getHeadWeights(headElement)
      .map(({ element: element, weight: weight }) => {
        return {
          weight: weight,
          element: io.getLoggableElement(element),
          isValid: !validation.hasValidationWarning(element),
          customValidations: validation.getCustomValidations(element),
        };
      });
    io.visualizeHead("Actual", headElement, headWeights);
    const sortedWeights = Array.from(headWeights).sort(
      (a, b) => b.weight - a.weight,
    );
    const sortedHead = document.createElement("head");
    sortedWeights.forEach(({ element: element }) => {
      sortedHead.appendChild(element.cloneNode(true));
    });
    io.visualizeHead("Sorted", sortedHead, sortedWeights);
    return headWeights;
  }
 
  const $fd3091053c5dfffc$var$CAPO_GLOBAL = "__CAPO__";
  async function $fd3091053c5dfffc$var$run() {
    const options = new $5b739339de321a37$exports.Options(
      self[$fd3091053c5dfffc$var$CAPO_GLOBAL],
    );
    const io = new $d410929ede0a2ee4$exports.IO(document, options);
    await io.init();
    $0eec6c831ab0f90a$export$8679af897d1c058e(io, $580f7ed6bc170ae8$exports);
    $0eec6c831ab0f90a$export$b65597cffe09aebc(
      io,
      $580f7ed6bc170ae8$exports,
      $9c3989fcb9437829$exports,
    );
  }
  $fd3091053c5dfffc$var$run();
})();