UNPKG

es-dev-server-rollup

Version:
185 lines (184 loc) 9.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.wrapRollupPlugin = void 0; const path_1 = __importDefault(require("path")); const whatwg_url_1 = __importDefault(require("whatwg-url")); const es_dev_server_1 = require("es-dev-server"); const dom5_fork_1 = require("@open-wc/building-utils/dom5-fork"); // @ts-ignore const building_utils_1 = require("@open-wc/building-utils"); const parse5_1 = require("parse5"); const utils_1 = require("./utils"); const PluginContext_1 = require("./PluginContext"); const NULL_BYTE_PARAM = 'es-dev-server-rollup-null-byte'; function wrapRollupPlugin(rollupPlugin, rollupOptions = {}) { const transformedFiles = new Set(); let transformedOptions; let fileWatcher; let config; let rootDir; const edsPlugin = { serverStart(args) { var _a, _b, _c; ({ fileWatcher, config } = args); ({ rootDir } = config); const rollupPluginContext = PluginContext_1.createPluginContext(fileWatcher, config, edsPlugin); // call the options and buildStart hooks transformedOptions = (_b = (_a = rollupPlugin.options) === null || _a === void 0 ? void 0 : _a.call(rollupPluginContext, rollupOptions)) !== null && _b !== void 0 ? _b : rollupOptions; (_c = rollupPlugin.buildStart) === null || _c === void 0 ? void 0 : _c.call(rollupPluginContext, transformedOptions); }, async resolveImport({ source, context }) { var _a; // if we just transformed this file and the import is an absolute file path // we need to rewrite it to a browser path const injectedFilePath = transformedFiles.has(context.path) && source.startsWith(rootDir); if (!injectedFilePath && !rollupPlugin.resolveId) { return; } if (!path_1.default.isAbsolute(source) && whatwg_url_1.default.parseURL(source) != null) { // don't resolve relative and valid urls return source; } const requestedFile = context.path.endsWith('/') ? `${context.path}index.html` : context.path; const filePath = path_1.default.join(rootDir, requestedFile); const rollupPluginContext = PluginContext_1.createPluginContext(fileWatcher, config, edsPlugin, context); // if the import was already a fully resolved file path, it was probably injected by a plugin. // in that case use that instead of resolving it through a plugin hook. this puts the resolved file // path through the regular logic to turn it into a relative browser import // otherwise call the resolveID hook on the plugin const result = injectedFilePath ? source : await ((_a = rollupPlugin.resolveId) === null || _a === void 0 ? void 0 : _a.call(rollupPluginContext, source, filePath)); let resolvedImportFilePath = undefined; if (typeof result === 'string') { resolvedImportFilePath = result; } else if (typeof result === 'object' && typeof (result === null || result === void 0 ? void 0 : result.id) === 'string') { resolvedImportFilePath = result.id; } if (!resolvedImportFilePath) { return undefined; } const hasNullByte = resolvedImportFilePath.includes('\0'); const withoutNullByte = hasNullByte ? resolvedImportFilePath.replace(new RegExp('\0', 'g'), '') : resolvedImportFilePath; if (withoutNullByte.startsWith(rootDir)) { const resolveRelativeTo = path_1.default.extname(filePath) ? path_1.default.dirname(filePath) : filePath; const relativeImportFilePath = path_1.default.relative(resolveRelativeTo, withoutNullByte); const resolvedImportPath = `${utils_1.toBrowserPath(relativeImportFilePath)}`; const prefixedImportPath = resolvedImportPath.startsWith('/') || resolvedImportPath.startsWith('.') ? resolvedImportPath : `./${resolvedImportPath}`; if (!hasNullByte) { return prefixedImportPath; } else { const suffix = `${NULL_BYTE_PARAM}=${encodeURIComponent(resolvedImportFilePath)}`; if (prefixedImportPath.includes('?')) { return `${prefixedImportPath}&${suffix}`; } return `${prefixedImportPath}?${suffix}`; } } // if the resolved import includes a null byte (\0) there is some special logic // these often are not valid file paths, so the browser cannot request them. // we rewrite them to a special URL which we deconstruct later when we load the file if (resolvedImportFilePath.includes('\0')) { return `${es_dev_server_1.virtualFilePrefix}?${NULL_BYTE_PARAM}=${encodeURIComponent(resolvedImportFilePath)}`; } return resolvedImportFilePath; }, async serve(context) { var _a; if (!rollupPlugin.load) { return; } let filePath; if (context.URL.searchParams.has(NULL_BYTE_PARAM)) { // if this was a special URL constructed in resolveImport to handle null bytes, // the file path is stored in the search paramter filePath = context.URL.searchParams.get(NULL_BYTE_PARAM); } else { filePath = path_1.default.join(rootDir, context.path); } const rollupPluginContext = PluginContext_1.createPluginContext(fileWatcher, config, edsPlugin, context); const result = await ((_a = rollupPlugin.load) === null || _a === void 0 ? void 0 : _a.call(rollupPluginContext, filePath)); if (typeof result === 'string') { return { body: result, type: 'js' }; } if (typeof (result === null || result === void 0 ? void 0 : result.code) === 'string') { return { body: result.code, type: 'js' }; } return undefined; }, async transform(context) { var _a, _b; if (!rollupPlugin.transform) { return; } if (context.response.is('js')) { const filePath = path_1.default.join(rootDir, context.path); const rollupPluginContext = PluginContext_1.createPluginContext(fileWatcher, config, edsPlugin, context); const result = await ((_a = rollupPlugin.transform) === null || _a === void 0 ? void 0 : _a.call(rollupPluginContext, context.body, filePath)); let transformedCode = undefined; if (typeof result === 'string') { transformedCode = result; } if (typeof result === 'object' && typeof (result === null || result === void 0 ? void 0 : result.code) === 'string') { transformedCode = result.code; } if (transformedCode) { transformedFiles.add(context.path); return { body: transformedCode }; } return; } if (context.response.is('html')) { const requestedFile = context.path.endsWith('/') ? `${context.path}index.html` : context.path; const filePath = path_1.default.join(rootDir, requestedFile); let changed = false; const documentAst = parse5_1.parse(context.body); const scriptNodes = building_utils_1.findJsScripts(documentAst, { jsScripts: true, jsModules: true, inlineJsScripts: true, }); for (const node of scriptNodes) { const code = dom5_fork_1.getTextContent(node); const rollupPluginContext = PluginContext_1.createPluginContext(fileWatcher, config, edsPlugin, context); const result = await ((_b = rollupPlugin.transform) === null || _b === void 0 ? void 0 : _b.call(rollupPluginContext, code, filePath)); let transformedCode; if (typeof result === 'string') { transformedCode = result; } else if (typeof result === 'object' && typeof (result === null || result === void 0 ? void 0 : result.code) === 'string') { transformedCode = result.code; } if (transformedCode) { changed = true; dom5_fork_1.setTextContent(node, transformedCode); } } if (changed) { transformedFiles.add(context.path); return { body: parse5_1.serialize(documentAst) }; } } }, }; return edsPlugin; } exports.wrapRollupPlugin = wrapRollupPlugin;