"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Infer: () => Infer, ScriptLoadError: () => ScriptLoadError, computeUrl: () => computeUrl, createElement: () => createElement, createScriptTag: () => createScriptTag, extractMap: () => extractMap, findFirstModuleScriptInHead: () => findFirstModuleScriptInHead, geRootPath: () => geRootPath, generateImportMap: () => generateImportMap, generateImportMapInferVersion: () => generateImportMapInferVersion, getWorkspace: () => getWorkspace, importAttributes: () => importAttributes, importMapRollupPlugin: () => importMapRollupPlugin, importMapVitePlugin: () => importMapVitePlugin, injectImportMap: () => injectImportMap, injectImportMapInDom: () => injectImportMapInDom, injectScript: () => injectScript, injectScriptTags: () => injectScriptTags, insertTextAtIndex: () => insertTextAtIndex, isLinkTypeGuard: () => isLinkTypeGuard, isScriptOrLinkAttributeTypeGuard: () => isScriptOrLinkAttributeTypeGuard, mergeImports: () => mergeImports, mergeMaps: () => mergeMaps, mergeScripts: () => mergeScripts, parseVersion: () => parseVersion, prettifyHtml: () => prettifyHtml, toImport: () => toImport, validateImportMap: () => validateImportMap }); module.exports = __toCommonJS(src_exports); // src/utils/html.utils.ts var import_chalk = __toESM(require("chalk"), 1); var import_prettier = require("prettier"); function insertTextAtIndex(originalString, insertionText, index) { if (!index || index < 0 || index > originalString.length) { throw new Error("[import-map-plugin]: Index out of range."); } return originalString.slice(0, index) + insertionText + originalString.slice(index); } var prettifyHtml = (html, { debug, original }) => { try { return (0, import_prettier.format)(html, { parser: "html" }); } catch (err) { if (debug) console.info("[import-map-plugin]:", import_chalk.default.blue("Generated Html"), { original, html }); console.warn("[import-map-plugin]:", import_chalk.default.yellow("Failed to prettify html"), err); } return html; }; var headRegex = /
]*>[\s\S]*?<\/head>/i; var firstScriptRegex = /(?]*>[\s\S]*?<\/script>(?!\s*-->)/i; var firstModuleScriptRegex = /(?]*)?type=["'`]?module["'`]?[\s\S]*?<\/script>(?!\s*-->)/i; function findFirstModuleScriptInHead(htmlString) { const head = htmlString.match(headRegex)?.at(0); if (!head) return; const headStartIndex = htmlString.indexOf(head); const moduleIndex = head.search(firstModuleScriptRegex); if (moduleIndex > -1) return headStartIndex + moduleIndex; const scriptIndex = head.search(firstScriptRegex); if (scriptIndex > -1) return headStartIndex + scriptIndex; const headCloseIndex = head.indexOf(""); if (headCloseIndex > -1) return headStartIndex + headCloseIndex; } var importMapRegex = /(?]*type=['"`]?importmap['"`]?[^>]*>([\s\S]*?)<\/script>(?!\s*-->)/gi; function extractMap(html) { const groups = Array.from(html.matchAll(importMapRegex)); if (groups.length > 1) { throw new Error("[import-map-plugin]: Invalid import map detected. An index file can only have one import map script."); } let rawMap; let parsedMap = { imports: {} }; if (groups.length) { rawMap = groups.at(0)?.at(1); if (rawMap) { try { parsedMap = JSON.parse(rawMap); } catch (err) { console.error("[import-map-plugin]:", import_chalk.default.red("Failed to parse"), rawMap); throw err; } } } return { rawMap, parsedMap }; } // src/utils/version.utils.ts var import_chalk3 = __toESM(require("chalk"), 1); // src/utils/import.utils.ts var import_node_fs = require("fs"); var import_node_path = require("path"); var import_chalk2 = __toESM(require("chalk"), 1); var import_globby = require("globby"); // src/models/import-map.models.ts var Infer = "infer"; var importAttributes = ["name", "version", "separator", "index", "domain", "src"]; // src/utils/import.utils.ts var toImport = (stringOrImport) => { const _import = typeof stringOrImport === "string" ? { version: stringOrImport } : { ...stringOrImport }; if (_import.version === Infer) delete _import.version; return _import; }; var mergeImports = (left, ...rights) => { const merged = { ...left }; rights?.forEach( (right) => Object.entries(right).forEach(([name, value]) => { const existing = merged[name]; merged[name] = existing ? { ...toImport(existing), ...toImport(value) } : value; }) ); return merged; }; var computeUrl = ({ name, base, src, version, domain, separator, index }, defaultSeparator = "@") => { if (src) return src; if (!version) throw new Error(`[import-map-plugin]: No version could be resolved for '${name}'`); if (!domain) throw new Error(`[import-map-plugin]: No domain could be resolved for '${name}'`); return new URL([domain, `${base ?? name}${separator ?? defaultSeparator}${version}`, index].filter(Boolean).join("/")).toString(); }; var workspace; var getWorkspace = ({ cwd = process.cwd(), gitignore = true, onlyFiles = true, ignore = ["node_modules", "**/node_modules/**"], debug = false, cache = true, ...options } = {}) => { if (!workspace || !cache) { const files = (0, import_globby.sync)("**/package.json", { ...options, gitignore, onlyFiles, ignore, cwd }); if (debug) { console.info("[import-map-plugin]:", import_chalk2.default.blue(`${workspace ? "Re-building" : "Building"} workspace cache`)); } workspace = files.reduce((versions, path) => { const resolvedPath = (0, import_node_path.resolve)(cwd.toString(), path); const { name, version } = JSON.parse((0, import_node_fs.readFileSync)(resolvedPath, { encoding: "utf-8" })); versions[name] = { name, version, path: resolvedPath }; versions[name] = { name, version, path: resolvedPath }; return versions; }, {}); } return workspace; }; var segmentRegex = /[^/]+/g; var geRootPath = (pkg) => pkg?.repository?.directory?.replace(segmentRegex, ".."); // src/utils/regex.utils.ts var semverRegex = /(\d+\.\d+\.\d+)/; var workspaceRegex = /workspace:?/; function extractAbsoluteVersion(semver) { if (!semver) return semver; return semver.match(semverRegex)?.at(1); } // src/utils/version.utils.ts var parseWorkspaceVersion = (name, { pkg, debug, cache }) => { const workspace2 = getWorkspace({ cwd: geRootPath(pkg), debug, cache }); const workspaceVersion = workspace2[name]?.version; if (workspaceVersion) return extractAbsoluteVersion(workspaceVersion) ?? workspaceVersion; console.warn("[import-map-plugin]:", import_chalk3.default.yellow("No workspace version found"), { name }); if (debug) console.warn("[import-map-plugin]:", import_chalk3.default.yellow("Generated workspace"), workspace2); }; var parseVersion = (name, { version, pkg, debug, cache }) => { if (version && workspaceRegex.test(version)) return parseWorkspaceVersion(name, { pkg, debug, cache }) ?? version; if (version) return version; const _version = pkg?.dependencies?.[name]; if (_version && workspaceRegex.test(_version)) return parseWorkspaceVersion(name, { pkg, debug, cache }) ?? _version; return extractAbsoluteVersion(_version) ?? _version; }; // src/utils/generate-import-map.utils.ts var mergeMaps = (left, ...rights) => { const merged = { ...left, imports: { ...left?.imports ?? {} }, scopes: { ...left?.scopes ?? {} } }; rights?.forEach((map) => { if (map.imports) merged.imports = { ...merged.imports, ...map.imports }; if (map.scopes) { Object.entries(map.scopes).forEach(([scope, _import]) => { merged.scopes[scope] = { ...merged.scopes[scope] ?? {}, ..._import }; }); } }); return merged; }; function generateImportMap(imports, map = { imports: {} }, { domain: fallbackDomain, pkg, debug, cache, versionHook }) { const pkgImports = pkg?.runtimeDependencies?.imports ?? {}; const _imports = { ...pkgImports, ...imports }; Object.entries(_imports).forEach(([name, entry]) => { const { version, domain = fallbackDomain, index = "index.js", ...options } = toImport(entry); map.imports[name] = computeUrl({ name, version: versionHook?.(name, { version, pkg, debug, cache, entry }) ?? version, domain, index, ...options }); }); return map; } var generateImportMapInferVersion = (imports, map, options) => generateImportMap(imports, map, { ...options, versionHook: parseVersion }); // src/models/inject-script.models.ts var isScriptOrLinkAttributeTypeGuard = (key) => ![...importAttributes, "group"].includes(key); var isLinkTypeGuard = (script) => "rel" in script || "href" in script; var ScriptLoadError = class _ScriptLoadError extends Error { constructor(script, message) { super(`${script} - ${message}`); Object.setPrototypeOf(this, _ScriptLoadError.prototype); Error.captureStackTrace(this, this.constructor); } }; // src/utils/inject-script.utils.ts var isHtmlLink = (element) => "rel" in element || "href" in element; var createElement = (scriptOrLink) => { const element = document.createElement(isLinkTypeGuard(scriptOrLink) ? "link" : "script"); Object.entries(scriptOrLink).forEach(([key, value]) => { if (value === void 0 || value === null) return; if (isScriptOrLinkAttributeTypeGuard(key)) { element[key] = value; } else if (["group", "name", "version"].includes(key)) { element.dataset[key] = String(value); } }); let path; if (isHtmlLink(element)) { if (!element.href) element.href = computeUrl(scriptOrLink); path = element.href; } else if (!isLinkTypeGuard(scriptOrLink) && !scriptOrLink.group) { if (!element.src) element.src = computeUrl(scriptOrLink); path = element.src; } return { name: scriptOrLink.name, path, element }; }; function injectScript(scriptOrLink) { return new Promise((resolve2, reject) => { const { name, path, element } = createElement(scriptOrLink); element.onload = () => { resolve2(true); }; element.onerror = (err) => { reject(new ScriptLoadError(name ?? path ?? JSON.stringify(scriptOrLink), err.toString())); }; document.head.appendChild(element); }); } // src/transform/inject-import-map.transform.ts var import_chalk4 = __toESM(require("chalk"), 1); // src/utils/write-json.utils.ts var import_promises = require("fs/promises"); var import_node_path2 = require("path"); async function writeFileJson(path, data, { debug, ...options } = {}) { const _data = typeof data === "string" ? data : JSON.stringify(data); if (path.includes("/")) { try { await (0, import_promises.mkdir)((0, import_node_path2.dirname)(path), { recursive: true }); } catch (err) { console.error(`Failed to create folder`, { path }); throw err; } } try { await (0, import_promises.writeFile)(path, _data, options); if (debug) console.info(`File written to '${`${process.cwd()}/${path}`}'.`); } catch (err) { console.error(`Failed to write file`, { path, options }); throw err; } } // src/transform/inject-import-map.transform.ts var validateImportMap = (map, { pkg, strict, debug, transform }) => { Object.entries(map.imports).forEach(([name, url]) => { let pkgVersion = pkg?.dependencies?.[name]; if (!pkgVersion) return; pkgVersion = extractAbsoluteVersion(pkgVersion); if (!pkgVersion) return; const importMapVersion = url.match(new RegExp(`${name}@(\\d+\\.\\d+\\.\\d+)`))?.at(1); if (importMapVersion && importMapVersion !== pkgVersion) { if (strict) { throw new Error( `[import-map-plugin]: Local '${pkgVersion}' and import map '${importMapVersion}' versions do not match for package '${name}'.` ); } else { console.warn("[import-map-plugin]:", import_chalk4.default.yellow("Local and import map versions do not match."), { name, pkgVersion, importMapVersion }); } } }); return transform?.(map, { pkg, strict, debug }) ?? map; }; function injectImportMap({ id = "import-map-plugin", imports = {}, map = { imports: {} }, domain, pkg, transformMap = (_map) => _map, debug = false, strict = true, prettier = true, write = false, cache = true }) { return (html) => { const { rawMap, parsedMap } = extractMap(html); if (debug && rawMap) console.info("[import-map-plugin]:", import_chalk4.default.blue("Existing import map found"), parsedMap); const pkgMap = pkg?.runtimeDependencies?.map; if (debug && pkgMap) console.info("[import-map-plugin]:", import_chalk4.default.blue("Package import map found"), pkgMap); const mergedMap = mergeMaps(parsedMap, pkgMap ?? {}, map); const generatedMap = generateImportMapInferVersion(imports, mergedMap, { domain, pkg, debug, cache }); if (debug) console.info("[import-map-plugin]:", import_chalk4.default.blue("Generated import map"), generatedMap); const postTransformMap = validateImportMap(generatedMap, { pkg, debug, strict, transform: transformMap }); if (write) { const path = typeof write === "string" ? write : "dist/import-map.json"; writeFileJson(path, postTransformMap, { debug }).catch((err) => { console.error("Failed to write import map to file.", { path, map: postTransformMap }); console.error(err); }); } const stringMap = ` ${JSON.stringify(postTransformMap, null, " ")} `; let mutatedHtml; if (rawMap) { if (debug) console.info("[import-map-plugin]:", import_chalk4.default.blue("Replacing existing map in index.html")); mutatedHtml = html.replace(rawMap, stringMap); } else { const index = findFirstModuleScriptInHead(html); if (debug) console.info("[import-map-plugin]:", import_chalk4.default.blue("Injecting map at index"), index); mutatedHtml = insertTextAtIndex(html, ` `, index); } if (prettier) prettifyHtml(mutatedHtml, { debug, original: html }); return mutatedHtml; }; } // src/transform/inject-scripts.transform.ts var import_chalk5 = __toESM(require("chalk"), 1); var createScriptTag = (scriptOrLink, { id }) => { const isLink = isLinkTypeGuard(scriptOrLink); const attributes = []; if (id) attributes.push(`data-id="${id}"`); const ignore = ["text"]; const data = ["group", "name", "version"]; Object.entries(scriptOrLink).forEach(([key, value]) => { if (value === void 0 || value === null) return; if (isScriptOrLinkAttributeTypeGuard(key) && !ignore.includes(key)) { attributes.push(`${key}="${value}"`); } else if (data.includes(key)) { attributes.push(`data-${key}="${value}"`); } }); if (isLink || !scriptOrLink.group) { const path = (isLink ? scriptOrLink.href : scriptOrLink.src) ?? computeUrl(scriptOrLink, "/"); if (path) attributes.push(`${isLink ? "href" : "src"}="${path}"`); } if (isLink) return ``; return ``; }; var mergeScripts = (scripts) => { const mergedGroups = []; const map = /* @__PURE__ */ new Map(); scripts.forEach((script) => { if (isLinkTypeGuard(script) || !script.group) { mergedGroups.push(script); } else { map.set(script.group, [...map.get(script.group) ?? [], script]); } }); map.forEach((values) => { let mergeGroup; values.forEach((_script, index) => { if (index === 0) { mergeGroup = { ..._script, text: `import "${computeUrl(_script, "/")}"` }; delete mergeGroup.name; delete mergeGroup.src; delete mergeGroup.version; delete mergeGroup.index; delete mergeGroup.separator; delete mergeGroup.domain; } else if (mergeGroup) { mergeGroup.text = [mergeGroup.text, `import "${computeUrl(_script, "/")}"`].join("\n"); } }); if (mergeGroup) mergedGroups.push(mergeGroup); }); return mergedGroups; }; function injectScriptTags({ id = "import-map-plugin", scripts = [], domain, pkg, transformScripts = (_script) => _script, debug = false, prettier = true }) { return (html) => { const pkgScripts = pkg?.runtimeDependencies?.scripts ?? []; if (pkgScripts?.length && debug) { console.info("[import-map-plugin]:", import_chalk5.default.blue("Package scripts found"), pkgScripts); } const transformedScripts = mergeScripts( transformScripts([...pkgScripts, ...scripts]).map((_script) => { if (!_script.domain) _script.domain = domain; return _script; }) ); if (!transformedScripts?.length) { if (debug) console.warn("[import-map-plugin]:", import_chalk5.default.yellow("No scripts found"), transformedScripts); return html; } const scriptTags = transformedScripts.map((script) => createScriptTag(script, { id })); if (!scriptTags?.length) { if (debug) console.warn("[import-map-plugin]:", import_chalk5.default.yellow("No script tags generated"), scriptTags); return html; } if (debug) console.info("[import-map-plugin]:", import_chalk5.default.blue("Injecting scripts"), scriptTags); const index = html.indexOf(""); if (debug) console.info("[import-map-plugin]:", import_chalk5.default.blue("Injecting scripts at index"), index); const mutatedHtml = insertTextAtIndex(html, ` ${scriptTags.join("\n")} `, index); if (prettier) return prettifyHtml(mutatedHtml, { debug, original: html }); return mutatedHtml; }; } // src/plugins/rollup.plugin.ts var import_rollup_plugin_html = require("@web/rollup-plugin-html"); function importMapRollupPlugin({ input, id, imports, map, transformMap, scripts, transformScripts, domain, pkg, debug, strict, prettier, write, cache }, htmlOptions = {}) { const { map: mapDomain, scripts: scriptsDomain } = domain && typeof domain !== "string" ? domain : { map: domain, scripts: domain }; const transformHtml = []; if (imports || map || pkg?.runtimeDependencies?.map || pkg?.runtimeDependencies?.imports) { transformHtml.push( injectImportMap({ id: id ? `${id}-import-map` : id, imports, map, domain: mapDomain, pkg, transformMap, debug, strict, prettier, write, cache }) ); } if (scripts || pkg?.runtimeDependencies?.scripts) { transformHtml.push( injectScriptTags({ id: id ? `${id}-scripts` : id, scripts, transformScripts, domain: scriptsDomain, pkg, debug, prettier }) ); } if (htmlOptions.transformHtml) { transformHtml.push(...Array.isArray(htmlOptions.transformHtml) ? htmlOptions.transformHtml : [htmlOptions.transformHtml]); } return (0, import_rollup_plugin_html.rollupPluginHTML)({ ...htmlOptions, input, transformHtml }); } // src/plugins/vite.plugin.ts function importMapVitePlugin({ id, imports, map, transformMap, scripts, transformScripts, domain, pkg, debug, strict, prettier, write, cache }, plugin = {}) { const { map: mapDomain, scripts: scriptsDomain } = domain && typeof domain !== "string" ? domain : { map: domain, scripts: domain }; return { ...plugin, name: "import-map-vite-plugin", transformIndexHtml: (html) => { let mutatedHtml = html; if (imports || map || pkg?.runtimeDependencies?.map || pkg?.runtimeDependencies?.imports) { mutatedHtml = injectImportMap({ id: id ? `${id}-import-map` : id, imports, map, transformMap, domain: mapDomain, pkg, debug, strict, prettier, write, cache })(mutatedHtml); } if (scripts || pkg?.runtimeDependencies?.scripts) { mutatedHtml = injectScriptTags({ id: id ? `${id}-scripts` : id, scripts, transformScripts, domain: scriptsDomain, pkg, debug, prettier })(mutatedHtml); } return mutatedHtml; } }; } // src/entry/import-map.entry.ts function createImportMapDomScript(map, { onload, onerror } = {}) { const mapScript = document.createElement("script"); mapScript.type = "importmap"; mapScript.text = JSON.stringify(map); if (onload) mapScript.onload = onload; if (onerror) mapScript.onerror = onerror; return mapScript; } function insertNode(selector, node, debug = false) { const script = document.head.querySelector(selector); if (script?.parentNode) { if (debug) console.info(`Module '${selector}' found, injecting map...`, { map: node, sibling: script }); script.parentNode.insertBefore(node, script); return script; } return null; } var injectImportMapInDom = (map, { debug = false, ...options }) => { if (debug) console.info("Injecting map", map); const mapScript = createImportMapDomScript(map, options); if (document.head.children.length) { const firstModuleScript = insertNode('script[type="module"]', mapScript, debug); if (firstModuleScript) return { map, mapScript }; const firstScript = insertNode("script", mapScript, debug); if (firstScript) return { map, mapScript }; } if (debug) console.info("No script found in head, injecting map...", { map: mapScript, parent: document.head }); document.head.appendChild(mapScript); return { map, mapScript }; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Infer, ScriptLoadError, computeUrl, createElement, createScriptTag, extractMap, findFirstModuleScriptInHead, geRootPath, generateImportMap, generateImportMapInferVersion, getWorkspace, importAttributes, importMapRollupPlugin, importMapVitePlugin, injectImportMap, injectImportMapInDom, injectScript, injectScriptTags, insertTextAtIndex, isLinkTypeGuard, isScriptOrLinkAttributeTypeGuard, mergeImports, mergeMaps, mergeScripts, parseVersion, prettifyHtml, toImport, validateImportMap });