nuxt-purgecss
Version:
Drop superfluous CSS! A neat PurgeCSS wrapper for Nuxt.js
184 lines (178 loc) • 4.89 kB
JavaScript
import { defineNuxtModule } from '@nuxt/kit';
import consola from 'consola';
function normalizeWindowsPath(input = "") {
if (!input || !input.includes("\\")) {
return input;
}
return input.replace(/\\/g, "/");
}
const _UNC_REGEX = /^[\\/]{2}/;
const _IS_ABSOLUTE_RE = /^[\\/](?![\\/])|^[\\/]{2}(?!\.)|^[a-zA-Z]:[\\/]/;
const _DRIVE_LETTER_RE = /^[a-zA-Z]:$/;
const normalize = function(path) {
if (path.length === 0) {
return ".";
}
path = normalizeWindowsPath(path);
const isUNCPath = path.match(_UNC_REGEX);
const isPathAbsolute = isAbsolute(path);
const trailingSeparator = path[path.length - 1] === "/";
path = normalizeString(path, !isPathAbsolute);
if (path.length === 0) {
if (isPathAbsolute) {
return "/";
}
return trailingSeparator ? "./" : ".";
}
if (trailingSeparator) {
path += "/";
}
if (_DRIVE_LETTER_RE.test(path)) {
path += "/";
}
if (isUNCPath) {
if (!isPathAbsolute) {
return `//./${path}`;
}
return `//${path}`;
}
return isPathAbsolute && !isAbsolute(path) ? `/${path}` : path;
};
const join = function(...args) {
if (args.length === 0) {
return ".";
}
let joined;
for (let i = 0; i < args.length; ++i) {
const arg = args[i];
if (arg && arg.length > 0) {
if (joined === void 0) {
joined = arg;
} else {
joined += `/${arg}`;
}
}
}
if (joined === void 0) {
return ".";
}
return normalize(joined.replace(/\/\/+/g, "/"));
};
function normalizeString(path, allowAboveRoot) {
let res = "";
let lastSegmentLength = 0;
let lastSlash = -1;
let dots = 0;
let char = null;
for (let i = 0; i <= path.length; ++i) {
if (i < path.length) {
char = path[i];
} else if (char === "/") {
break;
} else {
char = "/";
}
if (char === "/") {
if (lastSlash === i - 1 || dots === 1) ; else if (dots === 2) {
if (res.length < 2 || lastSegmentLength !== 2 || res[res.length - 1] !== "." || res[res.length - 2] !== ".") {
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 !== 0) {
res = "";
lastSegmentLength = 0;
lastSlash = i;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
res += res.length > 0 ? "/.." : "..";
lastSegmentLength = 2;
}
} 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 (char === "." && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return res;
}
const isAbsolute = function(p) {
return _IS_ABSOLUTE_RE.test(p);
};
const DEFAULTS = {
content: [
"components/**/*.{vue,jsx?,tsx?}",
"layouts/**/*.{vue,jsx?,tsx?}",
"pages/**/*.{vue,jsx?,tsx?}",
"composables/**/*.{vue,jsx?,tsx?}",
"App.{vue,jsx?,tsx?}",
"app.{vue,jsx?,tsx?}",
"plugins/**/*.{js,ts}",
"nuxt.config.{js,ts}"
],
defaultExtractor: (content) => {
const contentWithoutStyleBlocks = content.replace(/<style[^]+?<\/style>/gi, "");
return contentWithoutStyleBlocks.match(/[\w-.:/]+(?<!:)/g) || [];
},
safelist: [
"body",
"html",
"nuxt-progress",
"__nuxt",
/-(leave|enter|appear)(|-(to|from|active))$/,
/^nuxt-link(|-exact)-active$/,
/^(?!cursor-move).+-move$/,
/.*data-v-.*/,
/:slotted/,
/:deep/,
/:global/
]
};
const logger = consola.withScope("nuxt:tailwindcss");
const module = defineNuxtModule({
meta: {
name: "nuxt-purgecss",
configKey: "purgecss",
compatibility: {
nuxt: "^3.0.0-rc.11"
}
},
defaults: (nuxt) => {
const enabled = !nuxt.options.dev;
return { ...DEFAULTS, enabled };
},
setup({ enabled, ...purgecssOptions }, nuxt) {
if (!enabled) {
const msg = `Purgecss is not enabled!${nuxt.options.dev ? " Likely because you are in dev mode" : ""}`;
logger.info(msg);
return;
}
purgecssOptions.content = purgecssOptions.content?.map((p) => isAbsolute(p) ? p : join(nuxt.options.srcDir, p));
if (!nuxt.options.postcss.plugins || !Object.keys(nuxt.options.postcss.plugins).length) {
nuxt.options.postcss.plugins = {};
}
nuxt.options.postcss.plugins["@fullhuman/postcss-purgecss"] = purgecssOptions;
}
});
export { module as default };