From 48ce28fa10cb4bd72385f2ac0b25303f67c581be Mon Sep 17 00:00:00 2001 From: Ffloriel Date: Sun, 10 Jan 2021 13:24:33 +0000 Subject: [PATCH] feat(postcss-purgecss): remove compatibility with postcss 7 #488 fix #540 BREAKING CHANGE: dropping support for postcss 7 --- .../postcss-purgecss/__tests__/index.test.ts | 9 +- packages/postcss-purgecss/src/index.ts | 87 +++++++++++++- .../postcss-purgecss/src/postCSSPurgeCSS.ts | 113 ------------------ packages/postcss-purgecss/src/types/index.ts | 8 -- 4 files changed, 88 insertions(+), 129 deletions(-) delete mode 100644 packages/postcss-purgecss/src/postCSSPurgeCSS.ts diff --git a/packages/postcss-purgecss/__tests__/index.test.ts b/packages/postcss-purgecss/__tests__/index.test.ts index 8c503fa5..39af8816 100644 --- a/packages/postcss-purgecss/__tests__/index.test.ts +++ b/packages/postcss-purgecss/__tests__/index.test.ts @@ -1,6 +1,5 @@ import fs from "fs"; -import { UserDefinedOptions } from "../src/types"; -import postcss, { PluginCreator } from "postcss"; +import postcss from "postcss"; import purgeCSSPlugin from "../src/"; @@ -16,7 +15,7 @@ describe("Purgecss postcss plugin", () => { .readFileSync(`${__dirname}/fixtures/expected/${file}.css`) .toString(); const result = await postcss([ - (purgeCSSPlugin as PluginCreator)({ + purgeCSSPlugin({ content: [`${__dirname}/fixtures/src/${file}/${file}.html`], fontFace: true, keyframes: true, @@ -43,7 +42,7 @@ describe("Purgecss postcss plugin", () => { .mockReturnValue([`${__dirname}/fixtures/src/${file}/${file}.html`]); postcss([ - (purgeCSSPlugin as PluginCreator)({ + purgeCSSPlugin({ contentFunction, fontFace: true, keyframes: true, @@ -68,7 +67,7 @@ describe("Purgecss postcss plugin", () => { .readFileSync(`${__dirname}/fixtures/expected/simple.css`) .toString(); postcss([ - (purgeCSSPlugin as PluginCreator)({ + purgeCSSPlugin({ content: [`${__dirname}/fixtures/src/simple/simple.html`], rejected: true, }), diff --git a/packages/postcss-purgecss/src/index.ts b/packages/postcss-purgecss/src/index.ts index 97e7539c..6926a291 100644 --- a/packages/postcss-purgecss/src/index.ts +++ b/packages/postcss-purgecss/src/index.ts @@ -1,4 +1,85 @@ -import postcss from "postcss"; -import { createPurgeCSSPlugin } from "./postCSSPurgeCSS"; +import { Helpers, PluginCreator, Root } from "postcss"; -export default createPurgeCSSPlugin(postcss); +import PurgeCSS, { + defaultOptions, + mergeExtractorSelectors, + standardizeSafelist, +} from "purgecss"; + +import { RawContent, UserDefinedOptions } from "./types"; + +const PLUGIN_NAME = "postcss-purgecss"; + +async function purgeCSS( + opts: UserDefinedOptions, + root: Root, + { result }: Helpers +): Promise { + const purgeCSS = new PurgeCSS(); + const options = { + ...defaultOptions, + ...opts, + safelist: standardizeSafelist(opts?.safelist), + }; + + if (opts && typeof opts.contentFunction === "function") { + options.content = opts.contentFunction( + (root.source && root.source.input.file) || "" + ); + } + + purgeCSS.options = options; + + const { content, extractors } = options; + + const fileFormatContents = content.filter( + (o) => typeof o === "string" + ) as string[]; + const rawFormatContents = content.filter( + (o) => typeof o === "object" + ) as RawContent[]; + + const cssFileSelectors = await purgeCSS.extractSelectorsFromFiles( + fileFormatContents, + extractors + ); + const cssRawSelectors = await purgeCSS.extractSelectorsFromString( + rawFormatContents, + extractors + ); + + const selectors = mergeExtractorSelectors(cssFileSelectors, cssRawSelectors); + + //purge unused selectors + purgeCSS.walkThroughCSS(root, selectors); + + if (purgeCSS.options.fontFace) purgeCSS.removeUnusedFontFaces(); + if (purgeCSS.options.keyframes) purgeCSS.removeUnusedKeyframes(); + if (purgeCSS.options.variables) purgeCSS.removeUnusedCSSVariables(); + + if (purgeCSS.options.rejected && purgeCSS.selectorsRemoved.size > 0) { + result.messages.push({ + type: "purgecss", + plugin: "postcss-purgecss", + text: `purging ${purgeCSS.selectorsRemoved.size} selectors: + ${Array.from(purgeCSS.selectorsRemoved) + .map((selector) => selector.trim()) + .join("\n ")}`, + }); + purgeCSS.selectorsRemoved.clear(); + } +} + +const purgeCSSPlugin: PluginCreator = function (opts) { + if (typeof opts === "undefined") + throw new Error("PurgeCSS plugin does not have the correct options"); + return { + postcssPlugin: PLUGIN_NAME, + Once(root, helpers) { + return purgeCSS(opts, root, helpers); + }, + }; +}; +purgeCSSPlugin.postcss = true; + +export default purgeCSSPlugin; diff --git a/packages/postcss-purgecss/src/postCSSPurgeCSS.ts b/packages/postcss-purgecss/src/postCSSPurgeCSS.ts deleted file mode 100644 index 411c1237..00000000 --- a/packages/postcss-purgecss/src/postCSSPurgeCSS.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Helpers, PluginCreator, Root } from "postcss"; - -import PurgeCSS, { - defaultOptions, - mergeExtractorSelectors, - standardizeSafelist, -} from "purgecss"; - -import { - PostCSSv7, - PostCSSv8, - PostCSSVersions, - RawContent, - UserDefinedOptions, -} from "./types"; - -const PLUGIN_NAME = "postcss-purgecss"; - -function isPostCSSv8(postcss: PostCSSVersions): postcss is PostCSSv8 { - return typeof (postcss as PostCSSv8).Root !== "undefined"; -} - -async function purgeCSS( - opts: UserDefinedOptions, - root: Root, - { result }: Helpers -): Promise { - const purgeCSS = new PurgeCSS(); - const options = { - ...defaultOptions, - ...opts, - safelist: standardizeSafelist(opts?.safelist), - }; - - if (opts && typeof opts.contentFunction === "function") { - options.content = opts.contentFunction( - (root.source && root.source.input.file) || "" - ); - } - - purgeCSS.options = options; - - const { content, extractors } = options; - - const fileFormatContents = content.filter( - (o) => typeof o === "string" - ) as string[]; - const rawFormatContents = content.filter( - (o) => typeof o === "object" - ) as RawContent[]; - - const cssFileSelectors = await purgeCSS.extractSelectorsFromFiles( - fileFormatContents, - extractors - ); - const cssRawSelectors = await purgeCSS.extractSelectorsFromString( - rawFormatContents, - extractors - ); - - const selectors = mergeExtractorSelectors(cssFileSelectors, cssRawSelectors); - - //purge unused selectors - purgeCSS.walkThroughCSS(root, selectors); - - if (purgeCSS.options.fontFace) purgeCSS.removeUnusedFontFaces(); - if (purgeCSS.options.keyframes) purgeCSS.removeUnusedKeyframes(); - if (purgeCSS.options.variables) purgeCSS.removeUnusedCSSVariables(); - - if (purgeCSS.options.rejected && purgeCSS.selectorsRemoved.size > 0) { - result.messages.push({ - type: "purgecss", - plugin: "postcss-purgecss", - text: `purging ${purgeCSS.selectorsRemoved.size} selectors: - ${Array.from(purgeCSS.selectorsRemoved) - .map((selector) => selector.trim()) - .join("\n ")}`, - }); - purgeCSS.selectorsRemoved.clear(); - } -} - -const purgeCSSPlugin: PluginCreator = function (opts) { - if (typeof opts === "undefined") - throw new Error("PurgeCSS plugin does not have the correct options"); - return { - postcssPlugin: PLUGIN_NAME, - Once(root, helpers) { - return purgeCSS(opts, root, helpers); - }, - }; -}; -purgeCSSPlugin.postcss = true; - -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export function createPurgeCSSPlugin(postCSS: PostCSSVersions) { - if (isPostCSSv8(postCSS)) { - return purgeCSSPlugin; - } - - return (postCSS as PostCSSv7).plugin( - "postcss-purgecss", - (opts?: UserDefinedOptions) => { - if (typeof opts === "undefined") - throw new Error("PurgeCSS plugin does not have the correct options"); - return async function (root, helpers): Promise { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return purgeCSS(opts, root, helpers); - }; - } - ); -} diff --git a/packages/postcss-purgecss/src/types/index.ts b/packages/postcss-purgecss/src/types/index.ts index 403eda40..20a5352b 100644 --- a/packages/postcss-purgecss/src/types/index.ts +++ b/packages/postcss-purgecss/src/types/index.ts @@ -3,9 +3,6 @@ import { StringRegExpArray, } from "../../../purgecss/src/types/index"; -import postCSS7 from "postcss7"; -import * as postCSS8 from "postcss"; - export interface RawContent { extension: string; raw: T; @@ -34,8 +31,3 @@ export interface UserDefinedOptions { safelist?: UserDefinedSafelist; blocklist?: StringRegExpArray; } - -export type PostCSSv7 = typeof postCSS7; -export type PostCSSv8 = typeof postCSS8.default; - -export type PostCSSVersions = PostCSSv8 | PostCSSv7;