<file-size> Web Component

by WebComponents

HTML

<h1>The minified &lt;file-size> element.js file:</h1>
<file-size gz></file-size>

<h1>https://file-size.github.io HTML file:</h1>
<file-size src="https://file-size.github.io"></file-size>

<h1>Lit.dev blocks with CORS:</h1>
<file-size src="https://lit.dev/js/lit.js"></file-size>
<h1>Skypack blocks <code>content-length</code></h1>
<file-size src="https://cdn.skypack.dev/-/[email protected]/dist=es2020,mode=imports/optimized/lit.js"></file-size>


<h1>Analyzing Lit (using copies):</h1>
<file-size src="https://file-size.github.io/baseclass/lit.js"></file-size>
<file-size src="https://file-size.github.io/baseclass/lit.nolicense.js"></file-size>

<h1>Analyzing other BaseClasses:</h1>
<file-size src="https://file-size.github.io/baseclass/ionic-site.min.js"></file-size>

<h1>Web Component files for my Pet Projects:</h1>
<file-size src="https://pie-meister.github.io/PieMeister.min.js"></file-size>
<file-size src="https://cardmeister.github.io/elements.cardmeister.min.js"></file-size>
<file-size src="https://chessmeister.github.io/elements.chessmeister.js"></file-size>
<file-size src="https://flagmeister.github.io/elements.flagmeister.min.js"></file-size>
<file-size src="https://cardmeister.github.io/elements.cardmeister.full.js"></file-size>

CSS

body{
  font:16px arial;
  background:khaki;
}
h1{
  font-size:19px;
  margin-bottom:0;
}

JavaScript

/* Full Source Code <file-size> Web Component */
customElements.define(
  "file-size",
  class extends HTMLElement {
    connectedCallback(
      // having fun with default parameters
      maxbytes = this.getAttribute("max") || 48e3, // 48 kByte, because my first TRS-80 had 48 kB RAM
      src = this.getAttribute("src") ||
      "https://file-size.github.io/element.js",
      length, // read content-length
      img, // loaded GZThermal IMG
      details, // to open/close <details>
      // and default functions, just because we can save bytes
      action = (txt) => this.querySelector("i").innerHTML = txt,
      gzthermal = () => { // call API , get IMG
        if (!img) {
          action("open gzthermal analysis");
          img = this.querySelector("img");
          img.onerror = (e) => action("file too large"); // larger files error out
          img.onload = (e) => {
            action("");
            img.onclick = (e) => {
              if (e.altKey) open(src, "_blank").focus(); // open sourcefile in tab
              else details.removeAttribute("open"); // close <details>
            }
          };
          img.src = "https://gzthermal.vercel.app/?url=" + src;
        }
      }
    ) {
      this.setAttribute("title", src); // so user can see full URI
      fetch(src, {
          mode: "cors",
        })
        .then(response => {
          length = ~~response.headers.get("content-length") || "no";
          this.innerHTML = `<details style=font:16px,arial;cursor:pointer><summary><b style=color:dark${
            length < maxbytes ? "green" : "red"
          };display:inline-block;width:4em;text-align:right>${length}</b> bytes ${src} <i/></summary><img style="max-width:98%"></details>`;
          details = this.querySelector("details");
          details.ontoggle = (e) => details.open && gzthermal();
          if (this.hasAttribute("gz")) details.setAttribute("open", "open");
        })
        .catch(e =>...