'use strict'; var cdnResolve = require('cdn-resolve'); var resolve_exports = require('resolve.exports'); // src/index.ts // src/builtin-modules.ts var builtinModules = [ "assert", "assert/strict", "async_hooks", "buffer", "child_process", "cluster", "console", "constants", "crypto", "dgram", "diagnostics_channel", "dns", "dns/promises", "domain", "events", "fs", "fs/promises", "http", "http2", "https", "inspector", "module", "net", "os", "path", "path/posix", "path/win32", "perf_hooks", "process", "punycode", "querystring", "readline", "readline/promises", "repl", "stream", "stream/consumers", "stream/promises", "stream/web", "string_decoder", "sys", "timers", "timers/promises", "tls", "trace_events", "tty", "url", "util", "util/types", "v8", "vm", "wasi", "worker_threads", "zlib", "node:assert", "node:assert/strict", "node:async_hooks", "node:buffer", "node:child_process", "node:cluster", "node:console", "node:constants", "node:crypto", "node:dgram", "node:diagnostics_channel", "node:dns", "node:dns/promises", "node:domain", "node:events", "node:fs", "node:fs/promises", "node:http", "node:http2", "node:https", "node:inspector", "node:module", "node:net", "node:os", "node:path", "node:path/posix", "node:path/win32", "node:perf_hooks", "node:process", "node:punycode", "node:querystring", "node:readline", "node:readline/promises", "node:repl", "node:stream", "node:stream/consumers", "node:stream/promises", "node:stream/web", "node:string_decoder", "node:sys", "node:timers", "node:timers/promises", "node:tls", "node:trace_events", "node:tty", "node:url", "node:util", "node:util/types", "node:v8", "node:vm", "node:wasi", "node:worker_threads", "node:zlib" ]; // src/path.ts var CHAR_DOT = 46; var CHAR_FORWARD_SLASH = 47; function assertPath(path) { if (typeof path !== "string") { throw new TypeError( `Path must be a string. Received ${JSON.stringify(path)}` ); } } function join(...paths) { if (paths.length === 0) return "."; let joined; for (let i = 0, len = paths.length; i < len; ++i) { const path = paths[i]; if (path && path.length > 0) { if (!joined) { joined = path; } else { joined += `/${path}`; } } } if (!joined) return "."; return normalizeString(joined); } function extname(path) { assertPath(path); let startDot = -1; let startPart = 0; let end = -1; let matchedSlash = true; let preDotState = 0; for (let i = path.length - 1; i >= 0; --i) { const code = path.charCodeAt(i); if (code === 47) { if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { matchedSlash = false; end = i + 1; } if (code === 46) { if (startDot === -1) { startDot = i; } else if (preDotState !== 1) { preDotState = 1; } } else if (startDot !== -1) { preDotState = -1; } } if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { return ""; } return path.slice(startDot, end); } function normalizeString(path, allowAboveRoot) { let res = ""; let lastSegmentLength = 0; let lastSlash = -1; let dots = 0; let code; for (let i = 0, len = path.length; i <= len; ++i) { if (i < len) { code = path.charCodeAt(i); } else if (code === CHAR_FORWARD_SLASH) { break; } else { code = CHAR_FORWARD_SLASH; } if (code === CHAR_FORWARD_SLASH) { if (lastSlash === i - 1 || dots === 1) ; else if (lastSlash !== i - 1 && dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) { if (res.length > 2) { const lastSlashIndex = res.lastIndexOf("/"); if (lastSlashIndex === -1) { res = ""; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); lastSegmentLength = res.length - 1 - res.lastIndexOf("/"); } lastSlash = i; dots = 0; continue; } else if (res.length === 2 || res.length === 1) { res = ""; lastSegmentLength = 0; lastSlash = i; dots = 0; continue; } } } else { if (res.length > 0) { res += `/${path.slice(lastSlash + 1, i)}`; } else { res = path.slice(lastSlash + 1, i); } lastSegmentLength = i - lastSlash - 1; } lastSlash = i; dots = 0; } else if (code === CHAR_DOT && dots !== -1) { ++dots; } else { dots = -1; } } return res; } // src/index.ts function resolveOptions(options) { return { cdn: options?.cdn ?? "esm", exclude: options?.exclude || [], versions: options?.versions || {}, defaultLoader: options?.defaultLoader || "js", relativeImportsHandler: options?.relativeImportsHandler }; } var RESOLVE_EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".json"]; function isExternal(module, external) { if (!Array.isArray(external)) { throw new TypeError("external must be an array"); } return external.find((it) => it === module || it.startsWith(`${it}/`)); } var URL_RE = /^https?:\/\//; function CDNImports(options) { const resolvedOptions = resolveOptions(options); return { name: "esbuild-cdn-imports", setup(build) { const externals = [ ...build.initialOptions.external || [], ...builtinModules ]; build.onResolve({ filter: URL_RE }, (args) => ({ path: args.path, namespace: "cdn-imports" })); build.onResolve({ filter: /.*/, namespace: "cdn-imports" }, (args) => { if (isExternal(args.path, externals)) { return { external: true, path: args.path }; } if (!args.path.startsWith(".")) { return { path: cdnResolve.normalizeCdnUrl(resolvedOptions.cdn, args.path), namespace: "cdn-imports" }; } const url = new URL(args.pluginData.url); const isFile = extname(url.pathname) !== ""; const isLocalPath = args.path.startsWith("./"); if (resolvedOptions.cdn === "jsdelivr" && isLocalPath) { if (isFile) { url.pathname = url.pathname.replace(/\/[^/]+$/, ""); } url.pathname = join(url.pathname, args.path.slice(1)); } else { url.pathname = join(url.pathname, "../", args.path); } return { path: url.toString(), namespace: "cdn-imports" }; }); build.onResolve({ filter: /.*/ }, async (args) => { if (args.kind === "entry-point") { return null; } if (args.path.startsWith(".")) { if (resolvedOptions.relativeImportsHandler) { return resolvedOptions.relativeImportsHandler(args, build); } return null; } const parsed = cdnResolve.parsePackage(args.path); if (resolvedOptions.exclude.includes(parsed.name)) { return null; } if (isExternal(args.path, externals)) { return { external: true, path: args.path }; } if (resolvedOptions.versions[parsed.name]) { parsed.version = resolvedOptions.versions[parsed.name]; } let subpath = parsed.path; if (!subpath) { const pkg = await fetch(cdnResolve.normalizeCdnUrl( resolvedOptions.cdn, `${parsed.name}@${parsed.version}/package.json` )).then((res) => res.json()); const resolvedExport = resolve_exports.resolve(pkg, ".", { require: args.kind === "require-call" || args.kind === "require-resolve" }) || resolve_exports.legacy(pkg); if (typeof resolvedExport === "string") { subpath = resolvedExport.replace(/^\.?\/?/, "/"); } else if (Array.isArray(resolvedExport) && resolvedExport.length > 0) { subpath = resolvedExport[0].replace(/^\.?\/?/, "/"); } } if (subpath && subpath[0] !== "/") { subpath = `/${subpath}`; } return { path: cdnResolve.normalizeCdnUrl( resolvedOptions.cdn, `${parsed.name}@${parsed.version}${subpath}` ), namespace: "cdn-imports" }; }); build.onLoad( { filter: /.*/, namespace: "cdn-imports" }, async (args) => { const res = await fetch(args.path); if (!res.ok) { throw new Error(`failed to load ${res.url}: ${res.status}`); } let loader = resolvedOptions.defaultLoader; const ext = extname(res.url); if (RESOLVE_EXTENSIONS.includes(ext)) { loader = ext.slice(1); } else if (ext === ".mjs" || ext === ".cjs") { loader = "js"; } return { contents: new Uint8Array(await res.arrayBuffer()), loader, pluginData: { url: res.url } }; } ); } }; } exports.CDNImports = CDNImports;