vite-plugin-public-path
Version:
Vite's equivalent of `__webpack_public_path__` in Webpack. Works for `index.html` and modern/legacy build.
120 lines (119 loc) • 5.92 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processHtml = void 0;
const pluginutils_1 = require("@rollup/pluginutils");
const node_html_parser_1 = require("node-html-parser");
const serialize_javascript_1 = __importDefault(require("serialize-javascript"));
function processHtml(config, options, _fileName, html) {
// Just load from a static base
if (typeof options.html === "string") {
return html.split(config.base).join(options.html);
}
// Disable HTML processing and pass-through the HTML with base placeholder for manual processing
if (!options.html) {
return html;
}
const document = (0, node_html_parser_1.parse)(html, { comment: true });
// For simple substitution, firstly inject placeholders and required code
const htmlOptions = typeof options.html === "object"
? options.html
: {
functionNameAddLinkTag: "__vitePluginPublicPath_addLinkTag",
addLinkTagsPlaceholder: `__add_link_tags_${Math.random()}__`,
functionNameAddScriptTag: "__vitePluginPublicPath_addScriptTag",
addScriptTagsPlaceholder: `__add_script_tags_${Math.random()}__`
};
if (typeof options.html !== "object") {
// Ignore
const lastScriptInHead = document.querySelectorAll("head > script:not([type=module])").pop();
/* istanbul ignore next */
if (!lastScriptInHead) {
throw new Error(`Couldn't find any <script> tags in your <head>. Please initialize your public path expression (${options.publicPathExpression}) in a <script> in your <head>.`);
}
lastScriptInHead.insertAdjacentHTML("afterend", "\n" +
"<script>\n" +
" (function () {\n" +
` function ${htmlOptions.functionNameAddLinkTag}(rel, href, integrity) {\n` +
' var link = document.createElement("link");\n' +
" link.rel = rel;\n" +
" link.href = href;\n" +
" if (integrity) { link.integrity = integrity; };\n" +
" document.head.appendChild(link);\n" +
" }\n" +
` ${htmlOptions.addLinkTagsPlaceholder}\n` +
" })();\n" +
"</script>\n");
document
.querySelector("body")
.insertAdjacentHTML("beforeend", "\n" +
"<script>\n" +
" (function () {\n" +
` function ${htmlOptions.functionNameAddScriptTag}(attributes, inlineScriptCode) {\n` +
' var script = document.createElement("script");\n' +
" if (attributes) for (var key in attributes) script.setAttribute(key, attributes[key]);\n" +
" script.async = false;\n" +
' if (inlineScriptCode) script.src = "data:text/javascript," + inlineScriptCode;\n' +
" document.body.appendChild(script);\n" +
" }\n" +
` ${htmlOptions.addScriptTagsPlaceholder}\n` +
" })();\n" +
"</script>\n");
}
const urlPrefix = config.base;
const normalizeUrl = (url) => {
if (url.startsWith(urlPrefix))
url = url.slice(urlPrefix.length);
return url;
};
const urlToExpression = (url) => {
url = normalizeUrl(url);
// Check absolute URLs
if (["//", "http://", "https://", "data:"].some(prefix => url.toLowerCase().startsWith(prefix))) {
return (0, serialize_javascript_1.default)(url);
}
return `${options.publicPathExpression} + ${(0, serialize_javascript_1.default)(url)}`;
};
const linkTags = document
.querySelectorAll("link[rel]")
.filter(link => link.getAttribute("href").startsWith(urlPrefix));
const addLinkTagsCode = linkTags
.map(tag => {
const href = tag.getAttribute("href");
const rel = tag.getAttribute("rel");
const integrity = tag.getAttribute("integrity");
return `${htmlOptions.functionNameAddLinkTag}(${(0, serialize_javascript_1.default)(rel)}, ${urlToExpression(href)}, ${(0, serialize_javascript_1.default)(integrity)})`;
})
.join(";");
const patchAttributes = ["src", "data-src"];
const excludeScriptsFilter = options.excludeScripts ? (0, pluginutils_1.createFilter)(options.excludeScripts) : () => false;
const scriptTags = document.querySelectorAll("script[src], script[nomodule]").filter(tag => {
var _a;
if (!patchAttributes.some(attr => tag.hasAttribute(attr))) {
// script tag has no src or data-src, keep tag for rewrite.
return true;
}
const src = (_a = tag.getAttribute("src")) !== null && _a !== void 0 ? _a : tag.getAttribute("data-src");
return !excludeScriptsFilter(src);
});
const addScriptTagsCode = scriptTags
.map(tag => {
const args = [
"{ " +
Object.entries(tag.attributes)
.map(([key, value]) => (0, serialize_javascript_1.default)(key) + ": " + (patchAttributes.includes(key) ? urlToExpression(value) : (0, serialize_javascript_1.default)(value)))
.join(", ") +
" }",
tag.innerHTML.trim() ? (0, serialize_javascript_1.default)(tag.innerHTML.trim()) : null
];
return `${htmlOptions.functionNameAddScriptTag}(${args.filter(arg => arg != null).join(", ")})`;
})
.join(";");
[...linkTags, ...scriptTags].map(tag => tag.parentNode.removeChild(tag));
return document.outerHTML
.replace(htmlOptions.addLinkTagsPlaceholder, addLinkTagsCode)
.replace(htmlOptions.addScriptTagsPlaceholder, addScriptTagsCode);
}
exports.processHtml = processHtml;