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, insertBefore, remove, createScript, createElement, setAttribute } from "@web/parse5-utils";
import { addRollupInput } from "./add-rollup-input.js";
import { findAssets, findExternalScripts, findInlineScripts, findInlineStyles, getTextContent, getAttributes } from "./extract-assets.js";
import { isBuildableImage, isBuildableLink, isHoistedScript, isInSrcDirectory, hasSrcSet } from "./util.js";
import { render as ssrRender } from "../core/ssr/index.js";
import { getAstroStyleId, getAstroPageStyleId } from "../vite-plugin-build-css/index.js";
import { prependDotSlash, removeEndingForwardSlash } from "../core/path.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 STATUS_CODE_RE = /^404$/;
function relativePath(from, to) {
  const rel = npath.posix.relative(from, to);
  return prependDotSlash(rel);
}
function rollupPluginAstroBuildHTML(options) {
  const { astroConfig, internals, logging, origin, allPages, routeCache, viteServer, pageNames } = options;
  const srcRoot = astroConfig.src.pathname;
  const srcRootWeb = srcRoot.substr(astroConfig.projectRoot.pathname.length - 1);
  const renderedPageMap = new Map();
  const astroScriptMap = new Map();
  const astroPageMap = new Map();
  const astroAssetMap = new Map();
  const cssChunkMap = new Map();
  const pageStyleImportOrder = [];
  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.hydratedComponentPaths()) {
          jsInput.add(path);
        }
        for (const pathname of pageData.paths) {
          pageNames.push(pathname.replace(/\/?$/, "/").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)) {
              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);
              }
            } else if (isInSrcDirectory(script, "src", srcRoot, srcRootWeb)) {
              const src = getAttribute(script, "src");
              if (src)
                jsInput.add(src);
            }
          }
          const assetImports = [];
          const styleId = getAstroStyleId(pathname);
          let styles = 0;
          for (const node of findInlineStyles(document)) {
            if (hasAttribute(node, "astro-style")) {
              const style = getTextContent(node) || " ";
              const thisStyleId = `${styleId}/${++styles}.css`;
              internals.astroStyleMap.set(thisStyleId, style);
              assetImports.push(thisStyleId);
            }
          }
          for (let node of findAssets(document)) {
            if (isBuildableLink(node, srcRoot, srcRootWeb)) {
              const href = getAttribute(node, "href");
              assetImports.push(href);
            }
            if (isBuildableImage(node, srcRoot, srcRootWeb)) {
              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}`)));
              } else if ((src == null ? void 0 : src.startsWith(srcRootWeb)) && !astroAssetMap.has(src)) {
                const resolved = new URL("." + src, astroConfig.projectRoot);
                astroAssetMap.set(src, fs.readFile(resolved));
              }
            }
            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}`)));
                } else if (url.startsWith(srcRootWeb) && !astroAssetMap.has(url)) {
                  const resolved = new URL("." + url, astroConfig.projectRoot);
                  astroAssetMap.set(url, fs.readFile(resolved));
                }
              }
            }
          }
          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");
            internals.astroPageStyleMap.set(pageStyleId, jsSource);
            assetInput.add(pageStyleId);
            for (const assetHref of assetImports) {
              if (!pageStyleImportOrder.includes(assetHref))
                pageStyleImportOrder.push(assetHref);
            }
          }
        }
      }
      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);
      }
      const sortedCSSChunks = [...internals.pureCSSChunks];
      sortedCSSChunks.sort((a, b) => {
        let aIndex = Math.min(...Object.keys(a.modules).map((id) => {
          const i = pageStyleImportOrder.findIndex((url) => id.endsWith(url));
          return i >= 0 ? i : Infinity;
        }));
        let bIndex = Math.min(...Object.keys(b.modules).map((id) => {
          const i = pageStyleImportOrder.findIndex((url) => id.endsWith(url));
          return i >= 0 ? i : Infinity;
        }));
        return aIndex - bIndex;
      });
      const sortedChunkNames = sortedCSSChunks.map(({ fileName }) => fileName);
      for (const chunk of sortedCSSChunks) {
        const chunkModules = [chunk.fileName, ...chunk.imports];
        chunkModules.sort((a, b) => sortedChunkNames.indexOf(a) - sortedChunkNames.indexOf(b));
        const referenceIDs = [];
        for (const chunkID of chunkModules) {
          const referenceID = internals.chunkToReferenceIdMap.get(chunkID);
          if (referenceID)
            referenceIDs.push(referenceID);
        }
        for (const id of Object.keys(chunk.modules)) {
          cssChunkMap.set(id, referenceIDs);
        }
      }
      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 = relativePath(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
        });
        const pageAssetId = facadeIdMap.get(id);
        const bundlePath = "/" + pageAssetId;
        let pageBundleAdded = false;
        for (let script of findInlineScripts(document)) {
          if (getAttribute(script, "astro-script") && typeof pageAssetId === "string") {
            if (!pageBundleAdded) {
              pageBundleAdded = true;
              const relPath = relativePath(pathname, bundlePath);
              insertBefore(script.parentNode, createScript({
                type: "module",
                src: relPath
              }), script);
            }
            remove(script);
          }
        }
        for (let script of findExternalScripts(document)) {
          if (getAttribute(script, "astro-script") && typeof pageAssetId === "string") {
            if (!pageBundleAdded) {
              pageBundleAdded = true;
              const relPath = relativePath(pathname, bundlePath);
              insertBefore(script.parentNode, createScript({
                type: "module",
                src: relPath
              }), script);
            }
            remove(script);
          } else if (isInSrcDirectory(script, "src", srcRoot, srcRootWeb)) {
            let src = getAttribute(script, "src");
            if (src == null ? void 0 : src.startsWith(srcRootWeb)) {
              src = new URL("." + src, astroConfig.projectRoot).pathname;
            }
            if (src && (facadeIdMap.has(src) || facadeIdMap.has(src.substr(1)))) {
              const assetRootPath = "/" + (facadeIdMap.get(src) || facadeIdMap.get(src.substr(1)));
              const relPath = relativePath(pathname, assetRootPath);
              const attrs = getAttributes(script);
              insertBefore(script.parentNode, createScript(__spreadProps(__spreadValues({}, attrs), {
                src: relPath
              })), script);
              remove(script);
            }
          }
        }
        const styleId = getAstroPageStyleId(pathname);
        let pageCSSAdded = false;
        for (const node of findAssets(document)) {
          if (isBuildableLink(node, srcRoot, srcRootWeb)) {
            const rel = getAttribute(node, "rel");
            switch (rel) {
              case "stylesheet": {
                if (!pageCSSAdded) {
                  const attrs = getAttributes(node);
                  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 = getAttributes(node);
                  appendStyleChunksBefore(node, pathname, cssChunkMap.get(styleId), attrs);
                  remove(node);
                }
              }
            }
          }
          if (isBuildableImage(node, srcRoot, srcRootWeb)) {
            const src = getAttribute(node, "src");
            const referenceId = assetIdMap.get(src);
            if (referenceId) {
              const fileName = this.getFileName(referenceId);
              const relPath = relativePath(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 = relativePath(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 name = pathname.substr(1);
        let outPath;
        if (name.match(STATUS_CODE_RE) || astroConfig.buildOptions.pageUrlFormat === "file") {
          outPath = `${removeEndingForwardSlash(name || "index")}.html`;
        } else {
          outPath = npath.posix.join(name, "index.html");
        }
        this.emitFile({
          fileName: outPath,
          source: outHTML,
          type: "asset"
        });
      }
    }
  };
}
export {
  rollupPluginAstroBuildHTML
};
//# sourceMappingURL=data:application/json;base64, 
