var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
import parse5 from "parse5";
import srcsetParse from "srcset-parse";
import * as npath from "path";
import { promises as fs } from "fs";
import { getAttribute, hasAttribute, getTagName, insertBefore, remove, createScript, createElement, setAttribute } from "@web/parse5-utils";
import { addRollupInput } from "./add-rollup-input.js";
import { findAssets, findExternalScripts, findInlineScripts, findInlineStyles, getTextContent, isStylesheetLink } from "./extract-assets.js";
import { render as ssrRender } from "../core/ssr/index.js";
import { getAstroStyleId, getAstroPageStyleId } from "../vite-plugin-build-css/index.js";
const matchSrcset = srcsetParse.default;
const PLUGIN_NAME = "@astro/rollup-plugin-build";
const ASTRO_PAGE_PREFIX = "@astro-page";
const ASTRO_SCRIPT_PREFIX = "@astro-script";
const ASTRO_EMPTY = "@astro-empty";
const tagsWithSrcSet = new Set(["img", "source"]);
const isAstroInjectedLink = (node) => isStylesheetLink(node) && getAttribute(node, "data-astro-injected") === "";
const isBuildableLink = (node, srcRoot) => {
  if (isAstroInjectedLink(node))
    return true;
  const href = getAttribute(node, "href");
  if (typeof href !== "string" || !href.length)
    return false;
  return href.startsWith(srcRoot) || `/${href}`.startsWith(srcRoot);
};
const isBuildableImage = (node, srcRoot) => {
  var _a;
  return getTagName(node) === "img" && ((_a = getAttribute(node, "src")) == null ? void 0 : _a.startsWith(srcRoot));
};
const hasSrcSet = (node) => tagsWithSrcSet.has(getTagName(node)) && !!getAttribute(node, "srcset");
const isHoistedScript = (node) => getTagName(node) === "script" && hasAttribute(node, "hoist");
function rollupPluginAstroBuildHTML(options) {
  const { astroConfig, astroStyleMap, astroPageStyleMap, chunkToReferenceIdMap, pureCSSChunks, logging, origin, allPages, routeCache, viteServer, pageNames } = options;
  const srcRoot = astroConfig.src.pathname;
  const renderedPageMap = new Map();
  const astroScriptMap = new Map();
  const astroPageMap = new Map();
  const astroAssetMap = new Map();
  const cssChunkMap = new Map();
  return {
    name: PLUGIN_NAME,
    enforce: "pre",
    async options(inputOptions) {
      const htmlInput = new Set();
      const assetInput = new Set();
      const jsInput = new Set();
      for (const [component, pageData] of Object.entries(allPages)) {
        const [renderers, mod] = pageData.preload;
        for (const path of mod.$$metadata.getAllHydratedComponentPaths()) {
          jsInput.add(path);
        }
        for (const pathname of pageData.paths) {
          pageNames.push(pathname.replace(/\/?$/, "/index.html").replace(/^\//, ""));
          const id = ASTRO_PAGE_PREFIX + pathname;
          const html = await ssrRender(renderers, mod, {
            astroConfig,
            filePath: new URL(`./${component}`, astroConfig.projectRoot),
            logging,
            mode: "production",
            origin,
            pathname,
            route: pageData.route,
            routeCache,
            viteServer
          });
          renderedPageMap.set(id, html);
          const document = parse5.parse(html, {
            sourceCodeLocationInfo: true
          });
          const frontEndImports = [];
          for (const script of findInlineScripts(document)) {
            const astroScript = getAttribute(script, "astro-script");
            if (astroScript) {
              const js = getTextContent(script);
              const scriptId = ASTRO_SCRIPT_PREFIX + astroScript;
              frontEndImports.push(scriptId);
              astroScriptMap.set(scriptId, js);
            }
          }
          for (const script of findExternalScripts(document)) {
            if (isHoistedScript(script)) {
              debugger;
              const astroScript = getAttribute(script, "astro-script");
              const src = getAttribute(script, "src");
              if (astroScript) {
                const js = `import '${src}';`;
                const scriptId = ASTRO_SCRIPT_PREFIX + astroScript;
                frontEndImports.push(scriptId);
                astroScriptMap.set(scriptId, js);
              }
            }
          }
          let styles = "";
          for (const node of findInlineStyles(document)) {
            if (hasAttribute(node, "astro-style")) {
              styles += getTextContent(node);
            }
          }
          const assetImports = [];
          for (let node of findAssets(document)) {
            if (isBuildableLink(node, srcRoot)) {
              const href = getAttribute(node, "href");
              assetImports.push(href);
            }
            if (isBuildableImage(node, srcRoot)) {
              const src = getAttribute(node, "src");
              if ((src == null ? void 0 : src.startsWith(srcRoot)) && !astroAssetMap.has(src)) {
                astroAssetMap.set(src, fs.readFile(new URL(`file://${src}`)));
              }
            }
            if (hasSrcSet(node)) {
              const candidates = matchSrcset(getAttribute(node, "srcset"));
              for (const { url } of candidates) {
                if (url.startsWith(srcRoot) && !astroAssetMap.has(url)) {
                  astroAssetMap.set(url, fs.readFile(new URL(`file://${url}`)));
                }
              }
            }
          }
          if (styles) {
            const styleId = getAstroStyleId(pathname);
            astroStyleMap.set(styleId, styles);
            assetImports.unshift(styleId);
          }
          if (frontEndImports.length) {
            htmlInput.add(id);
            const jsSource = frontEndImports.map((sid) => `import '${sid}';`).join("\n");
            astroPageMap.set(id, jsSource);
          }
          if (assetImports.length) {
            const pageStyleId = getAstroPageStyleId(pathname);
            const jsSource = assetImports.map((sid) => `import '${sid}';`).join("\n");
            astroPageStyleMap.set(pageStyleId, jsSource);
            assetInput.add(pageStyleId);
          }
        }
      }
      const allInputs = new Set([...jsInput, ...htmlInput, ...assetInput]);
      if (!allInputs.size) {
        allInputs.add(ASTRO_EMPTY);
      }
      const outOptions = addRollupInput(inputOptions, Array.from(allInputs));
      return outOptions;
    },
    async resolveId(id) {
      switch (true) {
        case astroScriptMap.has(id):
        case astroPageMap.has(id):
        case id === ASTRO_EMPTY: {
          return id;
        }
      }
      return void 0;
    },
    async load(id) {
      if (astroPageMap.has(id)) {
        return astroPageMap.get(id);
      }
      if (astroScriptMap.has(id)) {
        return astroScriptMap.get(id);
      }
      if (id === ASTRO_EMPTY) {
        return 'console.log("empty");';
      }
      return null;
    },
    outputOptions(outputOptions) {
      Object.assign(outputOptions, {
        entryFileNames(chunk) {
          if (chunk.name.startsWith(ASTRO_PAGE_PREFIX)) {
            let pageName = chunk.name.substr(ASTRO_PAGE_PREFIX.length + 1);
            if (!pageName) {
              pageName = "index";
            }
            return `assets/${pageName}.[hash].js`;
          }
          return "assets/[name].[hash].js";
        }
      });
      return outputOptions;
    },
    async generateBundle(_options, bundle) {
      const facadeIdMap = new Map();
      for (const [chunkId, output] of Object.entries(bundle)) {
        if (output.type === "chunk") {
          const chunk = output;
          const id = chunk.facadeModuleId;
          if (id === ASTRO_EMPTY) {
            delete bundle[chunkId];
          } else if (id) {
            facadeIdMap.set(id, chunk.fileName);
          }
        }
      }
      const assetIdMap = new Map();
      for (const [assetPath, dataPromise] of astroAssetMap) {
        const referenceId = this.emitFile({
          type: "asset",
          name: npath.basename(assetPath),
          source: await dataPromise
        });
        assetIdMap.set(assetPath, referenceId);
      }
      for (const chunk of pureCSSChunks) {
        const referenceId = chunkToReferenceIdMap.get(chunk.fileName);
        const chunkReferenceIds = [referenceId];
        for (const imp of chunk.imports) {
          if (chunkToReferenceIdMap.has(imp)) {
            chunkReferenceIds.push(chunkToReferenceIdMap.get(imp));
          }
        }
        for (const [id] of Object.entries(chunk.modules)) {
          cssChunkMap.set(id, chunkReferenceIds);
        }
      }
      const linkChunksAdded = new Set();
      const appendStyleChunksBefore = (ref, pathname, referenceIds, attrs = {}) => {
        let added = false;
        if (referenceIds) {
          const lastNode = ref;
          for (const referenceId of referenceIds) {
            const chunkFileName = this.getFileName(referenceId);
            const relPath = npath.posix.relative(pathname, "/" + chunkFileName);
            const key = pathname + relPath + attrs.rel || "stylesheet";
            if (!linkChunksAdded.has(key)) {
              linkChunksAdded.add(key);
              insertBefore(lastNode.parentNode, createElement("link", __spreadProps(__spreadValues({
                rel: "stylesheet"
              }, attrs), {
                href: relPath
              })), lastNode);
              added = true;
            }
          }
        }
        return added;
      };
      for (const [id, html] of renderedPageMap) {
        const pathname = id.substr(ASTRO_PAGE_PREFIX.length);
        const document = parse5.parse(html, {
          sourceCodeLocationInfo: true
        });
        if (facadeIdMap.has(id)) {
          const bundleId = facadeIdMap.get(id);
          const bundlePath = "/" + bundleId;
          let pageBundleAdded = false;
          for (let script of findInlineScripts(document)) {
            if (getAttribute(script, "astro-script")) {
              if (!pageBundleAdded) {
                pageBundleAdded = true;
                const relPath = npath.posix.relative(pathname, bundlePath);
                insertBefore(script.parentNode, createScript({
                  type: "module",
                  src: relPath
                }), script);
              }
              remove(script);
            }
          }
          for (let script of findExternalScripts(document)) {
            if (getAttribute(script, "astro-script")) {
              if (!pageBundleAdded) {
                pageBundleAdded = true;
                const relPath = npath.posix.relative(pathname, bundlePath);
                insertBefore(script.parentNode, createScript({
                  type: "module",
                  src: relPath
                }), script);
              }
              remove(script);
            }
          }
        }
        const styleId = getAstroPageStyleId(pathname);
        let pageCSSAdded = false;
        for (const node of findAssets(document)) {
          if (isBuildableLink(node, srcRoot)) {
            const rel = getAttribute(node, "rel");
            switch (rel) {
              case "stylesheet": {
                if (!pageCSSAdded) {
                  const attrs = Object.fromEntries(node.attrs.map((attr) => [attr.name, attr.value]));
                  delete attrs["data-astro-injected"];
                  pageCSSAdded = appendStyleChunksBefore(node, pathname, cssChunkMap.get(styleId), attrs);
                }
                remove(node);
                break;
              }
              case "preload": {
                if (getAttribute(node, "as") === "style") {
                  const attrs = Object.fromEntries(node.attrs.map((attr) => [attr.name, attr.value]));
                  appendStyleChunksBefore(node, pathname, cssChunkMap.get(styleId), attrs);
                  remove(node);
                }
              }
            }
          }
          if (isBuildableImage(node, srcRoot)) {
            const src = getAttribute(node, "src");
            const referenceId = assetIdMap.get(src);
            if (referenceId) {
              const fileName = this.getFileName(referenceId);
              const relPath = npath.posix.relative(pathname, "/" + fileName);
              setAttribute(node, "src", relPath);
            }
          }
          if (hasSrcSet(node)) {
            const srcset = getAttribute(node, "srcset");
            let changedSrcset = srcset;
            const urls = matchSrcset(srcset).map((c) => c.url);
            for (const url of urls) {
              if (assetIdMap.has(url)) {
                const referenceId = assetIdMap.get(url);
                const fileName = this.getFileName(referenceId);
                const relPath = npath.posix.relative(pathname, "/" + fileName);
                changedSrcset = changedSrcset.replace(url, relPath);
              }
            }
            if (changedSrcset !== srcset) {
              setAttribute(node, "srcset", changedSrcset);
            }
          }
        }
        for (const style of findInlineStyles(document)) {
          if (hasAttribute(style, "astro-style")) {
            if (!pageCSSAdded) {
              pageCSSAdded = appendStyleChunksBefore(style, pathname, cssChunkMap.get(styleId));
            }
            remove(style);
          }
        }
        const outHTML = parse5.serialize(document);
        const outPath = npath.posix.join(pathname.substr(1), "index.html");
        this.emitFile({
          fileName: outPath,
          source: outHTML,
          type: "asset"
        });
      }
    }
  };
}
export {
  rollupPluginAstroBuildHTML
};
//# sourceMappingURL=data:application/json;base64, 
