pwaImage

tcmts.cli.web.pwaImage · #qnd7hujn · term · runs anywhere

An image of a web app manifest (an icon, a screenshot), as the pwa says it: its src a file of the codebase (an .svg's text, or a .png's, .jpg's, .webp's, .gif's or .ico's bytes), which the build keeps as an asset; the file's type, and a .png's size, read from it. A URL instead is left as it is.

export function pwaImage(
  src: unknown,
): { bytes: Uint8Array; ext: string; type: string; sizes?: string } | undefined {
  if (typeof src === "string") {
    return src.trimStart().startsWith("<")
      ? { bytes: new TextEncoder().encode(src), ext: ".svg", type: "image/svg+xml", sizes: "any" }
      : undefined;
  }
  if (!(src instanceof Uint8Array)) return undefined;
  const starts = (...b: number[]) => b.every((x, i) => src[i] === x);
  if (starts(0x89, 0x50, 0x4e, 0x47)) {
    const v = new DataView(src.buffer, src.byteOffset, src.byteLength);
    const sizes = src.length >= 24 ? `${v.getUint32(16)}x${v.getUint32(20)}` : undefined;
    return { bytes: src, ext: ".png", type: "image/png", ...(sizes ? { sizes } : {}) };
  }
  if (starts(0xff, 0xd8, 0xff)) return { bytes: src, ext: ".jpg", type: "image/jpeg" };
  if (starts(0x52, 0x49, 0x46, 0x46) && String.fromCharCode(...src.slice(8, 12)) === "WEBP")
    return { bytes: src, ext: ".webp", type: "image/webp" };
  if (starts(0x47, 0x49, 0x46, 0x38)) return { bytes: src, ext: ".gif", type: "image/gif" };
  if (starts(0, 0, 1, 0)) return { bytes: src, ext: ".ico", type: "image/x-icon" };
  return undefined;
}

used by