Ctrl K
ComunidadGuías…

build.mjs

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Build both browser targets with esbuild. No framework, no CSS pipeline:
// the extension has three pages and they load plain stylesheets.
import * as esbuild from "esbuild";
import { readFile, writeFile, mkdir, cp, rm } from "node:fs/promises";
import { existsSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

const root = path.dirname(fileURLToPath(import.meta.url));
const src = path.join(root, "src");
const watch = process.argv.includes("--watch");
const dist = process.argv.includes("--dist");
const outRoot = path.join(root, dist ? "dist" : "build");

const TARGETS = [
  { name: "chrome", manifest: "manifest.chrome.json" },
  { name: "firefox", manifest: "manifest.firefox.json" }
];

const ENTRIES = {
  background: "background/index.js",
  options: "options/index.js",
  popup: "popup/index.js",
  viewer: "viewer/index.js"
};

const PAGES = [
  { entry: "options", html: "options/index.html", out: "options.html", css: "options/styles.css" },
  { entry: "popup", html: "popup/index.html", out: "popup.html", css: "popup/styles.css" },
  { entry: "viewer", html: "viewer/index.html", out: "viewer.html", css: "viewer/styles.css" }
];

async function buildTarget({ name, manifest }) {
  const outdir = path.join(outRoot, name);
  await rm(outdir, { recursive: true, force: true });
  await mkdir(outdir, { recursive: true });

  const entryPoints = Object.fromEntries(
    Object.entries(ENTRIES)
      .filter(([, rel]) => existsSync(path.join(src, rel)))
      .map(([out, rel]) => [out, path.join(src, rel)])
  );

  const options = {
    entryPoints,
    outdir,
    bundle: true,
    format: "esm",
    target: ["chrome111", "firefox115"],
    sourcemap: dist ? false : "inline",
    minify: dist,
    logLevel: "warning",
    // Firefox MV3 background scripts are not modules in all versions; splitting
    // would emit bare imports the loader cannot resolve there.
    splitting: false
  };

  const ctx = watch ? await esbuild.context(options) : null;
  if (ctx) await ctx.watch();
  else await esbuild.build(options);

  await writeFile(
    path.join(outdir, "manifest.json"),
    await readFile(path.join(src, manifest), "utf8")
  );

  const common = path.join(src, "ui", "common.css");
  if (existsSync(common)) await cp(common, path.join(outdir, "common.css"));

  for (const page of PAGES) {
    const htmlPath = path.join(src, page.html);
    if (!existsSync(htmlPath)) continue;
    await writeFile(path.join(outdir, page.out), await readFile(htmlPath, "utf8"));
    const cssPath = path.join(src, page.css);
    if (existsSync(cssPath)) {
      await cp(cssPath, path.join(outdir, `${page.entry}.css`));
    }
  }

  if (existsSync(path.join(src, "icons"))) {
    await cp(path.join(src, "icons"), path.join(outdir, "icons"), { recursive: true });
  }

  return outdir;
}

for (const target of TARGETS) {
  const out = await buildTarget(target);
  console.log(`${target.name}: ${path.relative(root, out)}`);
}
if (watch) console.log("watching…");