UNPKG

vite-plugin-head

Version:

Modify, add, delete Metadata in the head element.

139 lines (138 loc) 3.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const parse5_1 = require("parse5"); const traverse = (root, options) => { const visit = (node, parent) => { let res; if (!node) { return; } if (options && options.pre) { res = options.pre(node, parent); } if (options) { for (const key in options) { if (key !== "pre" && key !== "post" && node.nodeName === key) { const call = options[key]; call && call(node, parent); } } } let { childNodes } = node; if (node.content && Array.isArray(node.content.childNodes)) { ({ childNodes } = node.content); } if (res !== false && Array.isArray(childNodes) && childNodes.length >= 0) { childNodes.forEach((child) => { visit(child, node); }); } if (options && options.post) { options.post(node, parent); } }; visit(root, null); }; /** * get attrs * @param node element * @param keys default all */ function getAttrs(node, keys) { const obj = {}; for (let index = 0; index < node.attrs?.length; index++) { const attr = node.attrs[index]; if (!keys) { if (attr?.name) { obj[attr.name] = attr.value; } continue; } if (attr?.name && keys.includes(attr.name)) { obj[attr.name] = attr.value; } } return obj; } function handleCssPreload(node) { let attrRel = null; let attrHref = null; if (!node?.attrs) { return; } for (let index = 0; index < node.attrs?.length; index++) { const attr = node.attrs[index]; if (attr?.name === "rel") { attrRel = attr; } if (attr?.name === "href") { attrHref = attr; } } if (attrRel && attrHref && /(.css)$/.test(attrHref.value)) { attrRel.value = "preload"; } } function handleTitle(node, title) { traverse(node, { "#text": (tNode) => { tNode.value = title; }, }); } function handleTransformLink(node, transformLink) { const attrs = getAttrs(node); const newAttrs = transformLink(attrs, attrs["href"]); const attrList = []; for (const key in newAttrs) { if (newAttrs[key]) { attrList.push({ name: key, value: newAttrs[key], }); } } node.attrs = attrList; } function headTransform(html, option) { const htmlAst = (0, parse5_1.parse)(html, { sourceCodeLocationInfo: true, }); let hasTitle = false; let headNode = null; traverse(htmlAst, { head(node) { headNode = node; }, link(node) { if (option?.cssPreload) { handleCssPreload(node); } if (option?.transformLink) { handleTransformLink(node, option.transformLink); } }, title(node) { hasTitle = true; if (option?.title) { handleTitle(node, option.title); } }, }); if (!hasTitle && headNode) { const titleNode = (0, parse5_1.parseFragment)(`<title>${option.title}</title>`) .childNodes[0]; headNode.childNodes.unshift(titleNode); titleNode.parentNode = headNode; } const resHtml = (0, parse5_1.serialize)(htmlAst); return resHtml; } exports.default = (option) => ({ name: "vite-plugin-head", enforce: "post", transformIndexHtml(html) { return headTransform(html, option); }, });