astro-purgecss 5.4.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -253,6 +253,47 @@ export default defineConfig({
|
|
|
253
253
|
});
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
## ⚠️ Advanced: Overriding Content Sources (`__unsafeContent`)
|
|
257
|
+
|
|
258
|
+
> **WARNING**: This is an advanced option that should only be used as a last resort for performance issues on extremely large sites.
|
|
259
|
+
|
|
260
|
+
By default, `astro-purgecss` scans all HTML and JavaScript files in your build output to determine which CSS classes are in use:
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
// Default content sources (added automatically):
|
|
264
|
+
[`${outDir}/**/*.html`, `${outDir}/**/*.js`];
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
For very large sites (e.g., 120,000+ pages), these globs can cause "Maximum call stack size exceeded" errors or severe performance degradation, see [`#1001`](https://github.com/codiume/orbit/issues/1001).
|
|
268
|
+
|
|
269
|
+
The `__unsafeContent` option allows you to **completely override** the default content sources with your own custom array. When this option is provided, the default globs are **completely ignored**.
|
|
270
|
+
|
|
271
|
+
### Usage Example
|
|
272
|
+
|
|
273
|
+
```js
|
|
274
|
+
export default defineConfig({
|
|
275
|
+
integrations: [
|
|
276
|
+
purgecss({
|
|
277
|
+
// ⚠️ WARNING: This completely bypasses default content scanning!
|
|
278
|
+
// Only use if the default globs cause performance issues.
|
|
279
|
+
// Ensure you include ALL files that contain CSS class references.
|
|
280
|
+
__unsafeContent: [
|
|
281
|
+
// Scan only JS files from the build output (skip HTML files)
|
|
282
|
+
process.cwd() + '/dist/**/*.js',
|
|
283
|
+
// Scan source files to catch SSR-rendered classes
|
|
284
|
+
process.cwd() + '/src/**/*.{astro,vue,jsx,tsx}'
|
|
285
|
+
]
|
|
286
|
+
})
|
|
287
|
+
]
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### ⚠️ Important Warnings
|
|
292
|
+
|
|
293
|
+
1. **Complete Override**: When `__unsafeContent` is provided, the default globs (`${outDir}/**/*.html` and `${outDir}/**/*.js`) are **completely ignored**. Make sure your custom content array includes all necessary sources.
|
|
294
|
+
|
|
295
|
+
2. **Risk of Over-Purging**: If your content array doesn't include all files that reference CSS classes, those classes will be incorrectly removed from your final CSS bundle, breaking your site's styling.
|
|
296
|
+
|
|
256
297
|
## 📝 Changelog
|
|
257
298
|
|
|
258
299
|
Please see the [Changelog](CHANGELOG.md) for more information on what has changed recently.
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var fs=require('fs'),path=require('path'),crypto=require('crypto'),purgecss=require('purgecss'),promises=require('fs/promises'),url=require('url');var F,O,
|
|
2
|
-
`+
|
|
1
|
+
'use strict';var fs=require('fs'),path=require('path'),crypto=require('crypto'),purgecss=require('purgecss'),promises=require('fs/promises'),url=require('url');var F,O,P,E,A=true;typeof process<"u"&&({FORCE_COLOR:F,NODE_DISABLE_COLORS:O,NO_COLOR:P,TERM:E}=process.env||{},A=process.stdout&&process.stdout.isTTY);var M={enabled:!O&&P==null&&E!=="dumb"&&(F!=null&&F!=="0"||A)};function e(n,t){let a=new RegExp(`\\x1b\\[${t}m`,"g"),x=`\x1B[${n}m`,g=`\x1B[${t}m`;return function(i){return !M.enabled||i==null?i:x+(~(""+i).indexOf(g)?i.replace(a,g+x):i)+g}}var S=e(2,22),T=e(31,39),D=e(32,39);async function L(n){try{return await promises.readFile(n,"utf8")}catch(t){return N(`Error reading file ${n}: ${t}`),""}}async function R(n,t){try{await promises.writeFile(n,t,"utf8");}catch(a){N(`Error writing file ${n}: ${a}`);}}async function y(n,t,a){await R(n,t),a!==n&&fs.existsSync(a)&&await promises.unlink(a);}function U(n,t){let a=crypto.createHash("sha256").update(t).digest("hex").slice(0,8);return `${n.slice(0,-13)}.${a}.css`}function _(n){if(!(n instanceof URL))throw new TypeError("Expected a URL object");let t=url.fileURLToPath(n).replace(/\/+$/,"");return process.platform==="win32"?t.replace(/^\/+/,""):t}var I=new Intl.DateTimeFormat("en-us",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:false});function h(n){let t=I.format(new Date);console.log(S(t),D("\u25B6"),n);}function N(n){let t=I.format(new Date);console.error(S(t),T("\u25A0"),n);}var k="astro-purgecss",K=n=>n.match(/[\w-/:\.#\(\),';%]+(?<!:)/g)||[];function Q(n={}){let t,{strategy:a="default",__unsafeContent:x,...g}=n;return {name:k,hooks:{"astro:config:done":({config:i})=>{t=i;},...a==="cache-buster"&&{"astro:build:setup":({vite:i,logger:C})=>{i.plugins||(i.plugins=[]),i.plugins.push({name:"inject-css-cache-buster",apply:"build",enforce:"pre",transform(l,f){return /\.(css|scss|sass|less|styl)(\?|$)/.test(f)?(C.info(`Injecting cache-buster CSS into: ${f}`),{code:`/*! Build: ${crypto.randomUUID().slice(0,8)} */
|
|
2
|
+
`+l,map:null}):null}});}},"astro:build:done":async({dir:i,pages:C,logger:l})=>{let f=t.output;l.info(`\u{1F4E6} Running in '${f}' mode`);let s=_(i),j=f!=="static"||a==="cache-buster";if(!s||!t.build.format||!t.build.assets){l.warn(`${k} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`);return}let d=(await new purgecss.PurgeCSS().purge({css:[`${s}/**/*.css`.replace(/\\/g,"/")],defaultExtractor:K,...g,content:x??[`${s}/**/*.html`.replace(/\\/g,"/"),`${s}/**/*.js`.replace(/\\/g,"/"),...g.content||[]]})).filter(({file:c})=>c?.endsWith(".css"));if(d.length===0){l.info("\u2139\uFE0F No CSS files found to process");return}if(l.info(`Found ${d.length} CSS ${d.length===1?"file":"files"} to process`),j){await Promise.all(d.map(async({css:c,file:r})=>{await y(r,c,r),h(r.replace(s,""));})),l.info("\u{1F389} Purging completed successfully!");return}let w=(await Promise.all(d.map(async({css:c,file:r})=>{if(!r.includes(t.build.assets)){await y(r,c,r);let m=r.replace(s,"");return h(m),{oldFilename:m,newFilename:m}}let p=U(r,c);await y(p,c,r);let $=r.replace(s,""),b=p.replace(s,"");return h(b),{oldFilename:$,newFilename:b}}))).filter(({oldFilename:c,newFilename:r})=>c!==r);if(w.length>0){l.info(`Updating ${w.length} CSS ${w.length===1?"reference":"references"} in HTML files...`);let c=C.filter(r=>typeof r.pathname=="string").map(r=>{let o=r.pathname;if(o==="")return path.join(s,"index.html");if(o==="404/"||o==="404")return path.join(s,"404.html");if(o==="500/"||o==="500")return path.join(s,"500.html");switch(t.build.format){case "file":return path.join(s,`${o}.html`);case "directory":return path.join(s,o,"index.html");case "preserve":let p=path.join(s,`${o}.html`);return fs.existsSync(p)?p:path.join(s,o,"index.html")}});await Promise.all(c.map(async r=>{let o=await L(r);for(let{oldFilename:p,newFilename:$}of w){let b=p.replace(/\\/g,"/"),m=$.replace(/\\/g,"/");o=o.replace(new RegExp(b,"g"),m);}await R(r,o),h(r.replace(s,""));}));}l.info("\u{1F389} Purging completed successfully!");}}}}var _e=Q;module.exports=_e;//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/colors.mjs","../src/utils.ts","../src/index.ts"],"names":["FORCE_COLOR","NODE_DISABLE_COLORS","NO_COLOR","TERM","isTTY","$","init","x","y","rgx","open","close","txt","dim","red","green","readFileContent","filePath","readFile","err","error","writeFileContent","content","writeFile","writeCssFile","newFilePath","css","oldFilePath","existsSync","unlink","generateFileHash","hash","createHash","cleanPath","file","path","fileURLToPath","dt","success","message","date","INTEGRATION_NAME","defaultExtractor","Plugin","options","config","strategy","purgecssOptions","cfg","vite","logger","code","id","randomUUID","dir","pages","buildMode","outDir","skipRehash","purgedCssFiles","PurgeCSS","changedFiles","relativePath","hashedFilename","relativeOldPath","relativeNewPath","oldFilename","newFilename","htmlFiles","page","pathname","join","directFile","htmlFile","normalizedOldPath","normalizedNewPath","index_default"],"mappings":"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","file":"index.cjs","sourcesContent":["let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;\nif (typeof process !== 'undefined') {\n\t({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});\n\tisTTY = process.stdout && process.stdout.isTTY;\n}\n\nexport const $ = {\n\tenabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (\n\t\tFORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY\n\t)\n}\n\nfunction init(x, y) {\n\tlet rgx = new RegExp(`\\\\x1b\\\\[${y}m`, 'g');\n\tlet open = `\\x1b[${x}m`, close = `\\x1b[${y}m`;\n\n\treturn function (txt) {\n\t\tif (!$.enabled || txt == null) return txt;\n\t\treturn open + (!!~(''+txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;\n\t};\n}\n\n// modifiers\nexport const reset = init(0, 0);\nexport const bold = init(1, 22);\nexport const dim = init(2, 22);\nexport const italic = init(3, 23);\nexport const underline = init(4, 24);\nexport const inverse = init(7, 27);\nexport const hidden = init(8, 28);\nexport const strikethrough = init(9, 29);\n\n// colors\nexport const black = init(30, 39);\nexport const red = init(31, 39);\nexport const green = init(32, 39);\nexport const yellow = init(33, 39);\nexport const blue = init(34, 39);\nexport const magenta = init(35, 39);\nexport const cyan = init(36, 39);\nexport const white = init(37, 39);\nexport const gray = init(90, 39);\nexport const grey = init(90, 39);\n\n// background colors\nexport const bgBlack = init(40, 49);\nexport const bgRed = init(41, 49);\nexport const bgGreen = init(42, 49);\nexport const bgYellow = init(43, 49);\nexport const bgBlue = init(44, 49);\nexport const bgMagenta = init(45, 49);\nexport const bgCyan = init(46, 49);\nexport const bgWhite = init(47, 49);\n","import { dim, green, red } from 'kleur/colors';\nimport { createHash } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n const content = await readFile(filePath, 'utf8');\n return content;\n } catch (err) {\n error(`Error reading file ${filePath}: ${err}`);\n return '';\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string) {\n try {\n await writeFile(filePath, content, 'utf8');\n } catch (err) {\n error(`Error writing file ${filePath}: ${err}`);\n }\n}\n\nexport async function writeCssFile(\n newFilePath: string,\n css: string,\n oldFilePath: string\n) {\n await writeFileContent(newFilePath, css);\n\n // Remove old file if it exists and is different from new file\n if (oldFilePath !== newFilePath && existsSync(oldFilePath)) {\n await unlink(oldFilePath);\n }\n}\n\nexport function generateFileHash(filePath: string, content: string) {\n // Get content hash before writing to file\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n\n // Generate new file name with hash\n // Astro original hash is 8 characters long\n return `${filePath.slice(0, -13)}.${hash}.css`;\n}\n\n// Clean from extra slash on windows and trailing forward slash on non-windows\nexport function cleanPath(file: URL): string {\n if (!(file instanceof URL)) {\n throw new TypeError('Expected a URL object');\n }\n\n // Remove trailing forward slash if present\n let path = fileURLToPath(file).replace(/\\/+$/, '');\n\n // Remove leading forward slash on windows if present\n return process.platform === 'win32' ? path.replace(/^\\/+/, '') : path;\n}\n\nexport const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n});\n\nexport function success(message: string) {\n const date = dt.format(new Date());\n console.log(dim(date), green('▶'), message);\n}\n\nexport function error(message: string) {\n const date = dt.format(new Date());\n console.error(dim(date), red('■'), message);\n}\n","import type { AstroConfig, AstroIntegration } from 'astro';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { PurgeCSS, type UserDefinedOptions } from 'purgecss';\n\nimport {\n cleanPath,\n generateFileHash,\n readFileContent,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\n\ntype PurgeStrategy = 'default' | 'cache-buster';\n\n/**\n * Extended PurgeCSS options interface that allows partial configuration\n * of the standard PurgeCSS options\n */\nexport interface PurgeCSSOptions extends Partial<UserDefinedOptions> {\n strategy?: PurgeStrategy;\n}\n\nconst INTEGRATION_NAME = 'astro-purgecss' as const;\n\n/**\n * default extractor to handle various CSS selector patterns\n * @param content string\n */\nconst defaultExtractor = (content: string) =>\n content.match(/[\\w-/:\\.#\\(\\),';%]+(?<!:)/g) || [];\n\n/**\n * Astro integration for PurgeCSS that removes unused CSS from the final build\n * @param options - PurgeCSS configuration options\n * @returns AstroIntegration - The configured Astro integration\n */\nfunction Plugin(options: PurgeCSSOptions = {}): AstroIntegration {\n let config: AstroConfig;\n const { strategy = 'default', ...purgecssOptions } = options;\n\n return {\n name: INTEGRATION_NAME,\n hooks: {\n 'astro:config:done': ({ config: cfg }) => {\n config = cfg;\n },\n ...(strategy === 'cache-buster' && {\n 'astro:build:setup': ({ vite, logger }) => {\n if (!vite.plugins) vite.plugins = [];\n vite.plugins.push({\n name: 'inject-css-cache-buster',\n apply: 'build',\n enforce: 'pre',\n transform(code, id) {\n if (!/\\.(css|scss|sass|less|styl)(\\?|$)/.test(id)) {\n return null;\n }\n logger.info(`Injecting cache-buster CSS into: ${id}`);\n return {\n code: `/*! Build: ${randomUUID().slice(0, 8)} */\\n` + code,\n map: null\n };\n }\n });\n }\n }),\n 'astro:build:done': async ({ dir, pages, logger }) => {\n const buildMode = config.output;\n logger.info(`📦 Running in '${buildMode}' mode`);\n\n // Convert the URL to a filesystem path\n const outDir = cleanPath(dir);\n\n // skip file rehashing for SSR/Server mode or cache-buster strategy\n const skipRehash =\n buildMode !== 'static' || strategy === 'cache-buster';\n\n // Validate required Astro configuration\n if (!outDir || !config.build.format || !config.build.assets) {\n logger.warn(\n `${INTEGRATION_NAME} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`\n );\n return;\n }\n\n // Run PurgeCSS on all CSS files\n // Replace is needed to make sure to pass correct glob format on windows machines\n const purgeResults = await new PurgeCSS().purge({\n css: [`${outDir}/**/*.css`.replace(/\\\\/g, '/')],\n defaultExtractor,\n ...purgecssOptions,\n content: [\n `${outDir}/**/*.html`.replace(/\\\\/g, '/'),\n `${outDir}/**/*.js`.replace(/\\\\/g, '/'),\n ...(purgecssOptions.content || [])\n ]\n });\n\n // Filter out non-CSS files from purge results\n const purgedCssFiles = purgeResults.filter(({ file }) =>\n file?.endsWith('.css')\n ) as Array<{\n css: string;\n file: string;\n }>;\n\n if (purgedCssFiles.length === 0) {\n logger.info('ℹ️ No CSS files found to process');\n return;\n }\n\n logger.info(\n `Found ${purgedCssFiles.length} CSS ${purgedCssFiles.length === 1 ? 'file' : 'files'} to process`\n );\n\n // If SSR/Server mode or cache-buster strategy skip file rehash\n if (skipRehash) {\n await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n await writeCssFile(file, css, file);\n success(file.replace(outDir, ''));\n })\n );\n logger.info('🎉 Purging completed successfully!');\n return;\n }\n\n // Process files for static mode with content hashing\n let processedFiles = await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n const isAssetFile = file.includes(config.build.assets);\n\n // Skip rehashing for non-asset files (not generated by astro)\n // ex: assets/styles/light.css\n if (!isAssetFile) {\n await writeCssFile(file, css, file);\n const relativePath = file.replace(outDir, '');\n success(relativePath);\n return {\n oldFilename: relativePath,\n newFilename: relativePath\n };\n }\n\n // Generate new filename with content hash\n const hashedFilename = generateFileHash(file, css);\n await writeCssFile(hashedFilename, css, file);\n\n const relativeOldPath = file.replace(outDir, '');\n const relativeNewPath = hashedFilename.replace(outDir, '');\n success(relativeNewPath);\n\n return {\n oldFilename: relativeOldPath,\n newFilename: relativeNewPath\n };\n })\n );\n\n // Filter to only get files that actually changed\n const changedFiles = processedFiles.filter(\n ({ oldFilename, newFilename }) => oldFilename !== newFilename\n );\n\n if (changedFiles.length > 0) {\n logger.info(\n `Updating ${changedFiles.length} CSS ${changedFiles.length === 1 ? 'reference' : 'references'} in HTML files...`\n );\n // Get all HTML pages based on build format\n const htmlFiles = pages\n .filter((page) => typeof page.pathname === 'string')\n .map((page) => {\n const pathname = page.pathname as string;\n\n // Handle root/index page\n if (pathname === '') {\n return join(outDir, 'index.html');\n }\n\n /**\n * Custom 404 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-404-error-page\n */\n if (pathname === '404/' || pathname === '404') {\n return join(outDir, '404.html');\n }\n\n /**\n * Custom 500 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-500-error-page\n */\n if (pathname === '500/' || pathname === '500') {\n return join(outDir, '500.html');\n }\n\n switch (config.build.format) {\n case 'file':\n // Format: /blog -> /blog.html\n return join(outDir, `${pathname}.html`);\n\n case 'directory':\n // Format: /blog -> /blog/index.html\n return join(outDir, pathname, 'index.html');\n\n case 'preserve':\n // Check if direct HTML file exists, otherwise use directory format\n const directFile = join(outDir, `${pathname}.html`);\n return existsSync(directFile)\n ? directFile\n : join(outDir, pathname, 'index.html');\n }\n });\n\n // Update CSS references in HTML files\n await Promise.all(\n htmlFiles.map(async (htmlFile) => {\n let content = await readFileContent(htmlFile);\n\n for (const { oldFilename, newFilename } of changedFiles) {\n const normalizedOldPath = oldFilename.replace(/\\\\/g, '/');\n const normalizedNewPath = newFilename.replace(/\\\\/g, '/');\n\n content = content.replace(\n new RegExp(normalizedOldPath, 'g'),\n normalizedNewPath\n );\n }\n\n await writeFileContent(htmlFile, content);\n success(htmlFile.replace(outDir, ''));\n })\n );\n }\n\n logger.info('🎉 Purging completed successfully!');\n }\n }\n };\n}\n\nexport default Plugin;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/colors.mjs","../src/utils.ts","../src/index.ts"],"names":["FORCE_COLOR","NODE_DISABLE_COLORS","NO_COLOR","TERM","isTTY","$","init","x","y","rgx","open","close","txt","dim","red","green","readFileContent","filePath","readFile","err","error","writeFileContent","content","writeFile","writeCssFile","newFilePath","css","oldFilePath","existsSync","unlink","generateFileHash","hash","createHash","cleanPath","file","path","fileURLToPath","dt","success","message","date","INTEGRATION_NAME","defaultExtractor","Plugin","options","config","strategy","__unsafeContent","purgecssOptions","cfg","vite","logger","code","id","randomUUID","dir","pages","buildMode","outDir","skipRehash","purgedCssFiles","PurgeCSS","changedFiles","relativePath","hashedFilename","relativeOldPath","relativeNewPath","oldFilename","newFilename","htmlFiles","page","pathname","join","directFile","htmlFile","normalizedOldPath","normalizedNewPath","index_default"],"mappings":"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","file":"index.cjs","sourcesContent":["let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;\nif (typeof process !== 'undefined') {\n\t({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});\n\tisTTY = process.stdout && process.stdout.isTTY;\n}\n\nexport const $ = {\n\tenabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (\n\t\tFORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY\n\t)\n}\n\nfunction init(x, y) {\n\tlet rgx = new RegExp(`\\\\x1b\\\\[${y}m`, 'g');\n\tlet open = `\\x1b[${x}m`, close = `\\x1b[${y}m`;\n\n\treturn function (txt) {\n\t\tif (!$.enabled || txt == null) return txt;\n\t\treturn open + (!!~(''+txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;\n\t};\n}\n\n// modifiers\nexport const reset = init(0, 0);\nexport const bold = init(1, 22);\nexport const dim = init(2, 22);\nexport const italic = init(3, 23);\nexport const underline = init(4, 24);\nexport const inverse = init(7, 27);\nexport const hidden = init(8, 28);\nexport const strikethrough = init(9, 29);\n\n// colors\nexport const black = init(30, 39);\nexport const red = init(31, 39);\nexport const green = init(32, 39);\nexport const yellow = init(33, 39);\nexport const blue = init(34, 39);\nexport const magenta = init(35, 39);\nexport const cyan = init(36, 39);\nexport const white = init(37, 39);\nexport const gray = init(90, 39);\nexport const grey = init(90, 39);\n\n// background colors\nexport const bgBlack = init(40, 49);\nexport const bgRed = init(41, 49);\nexport const bgGreen = init(42, 49);\nexport const bgYellow = init(43, 49);\nexport const bgBlue = init(44, 49);\nexport const bgMagenta = init(45, 49);\nexport const bgCyan = init(46, 49);\nexport const bgWhite = init(47, 49);\n","import { dim, green, red } from 'kleur/colors';\nimport { createHash } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n const content = await readFile(filePath, 'utf8');\n return content;\n } catch (err) {\n error(`Error reading file ${filePath}: ${err}`);\n return '';\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string) {\n try {\n await writeFile(filePath, content, 'utf8');\n } catch (err) {\n error(`Error writing file ${filePath}: ${err}`);\n }\n}\n\nexport async function writeCssFile(\n newFilePath: string,\n css: string,\n oldFilePath: string\n) {\n await writeFileContent(newFilePath, css);\n\n // Remove old file if it exists and is different from new file\n if (oldFilePath !== newFilePath && existsSync(oldFilePath)) {\n await unlink(oldFilePath);\n }\n}\n\nexport function generateFileHash(filePath: string, content: string) {\n // Get content hash before writing to file\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n\n // Generate new file name with hash\n // Astro original hash is 8 characters long\n return `${filePath.slice(0, -13)}.${hash}.css`;\n}\n\n// Clean from extra slash on windows and trailing forward slash on non-windows\nexport function cleanPath(file: URL): string {\n if (!(file instanceof URL)) {\n throw new TypeError('Expected a URL object');\n }\n\n // Remove trailing forward slash if present\n let path = fileURLToPath(file).replace(/\\/+$/, '');\n\n // Remove leading forward slash on windows if present\n return process.platform === 'win32' ? path.replace(/^\\/+/, '') : path;\n}\n\nexport const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n});\n\nexport function success(message: string) {\n const date = dt.format(new Date());\n console.log(dim(date), green('▶'), message);\n}\n\nexport function error(message: string) {\n const date = dt.format(new Date());\n console.error(dim(date), red('■'), message);\n}\n","import type { AstroConfig, AstroIntegration } from 'astro';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { PurgeCSS, type UserDefinedOptions, type RawContent } from 'purgecss';\n\nimport {\n cleanPath,\n generateFileHash,\n readFileContent,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\n\ntype PurgeStrategy = 'default' | 'cache-buster';\n\n/**\n * Extended PurgeCSS options interface that allows partial configuration\n * of the standard PurgeCSS options\n */\nexport interface PurgeCSSOptions extends Partial<UserDefinedOptions> {\n strategy?: PurgeStrategy;\n /**\n * ⚠️ UNSAFE: Completely overrides the default content globs.\n * When provided, only these content sources will be scanned by PurgeCSS.\n * The default globs (outDir/**\\/*.html and outDir/**\\/*.js) will be ignored.\n *\n * Use this ONLY if the default globs cause performance issues on very large sites.\n * The double underscore prefix indicates this is an advanced option that should\n * be used with extreme caution.\n *\n * @example\n * ```ts\n * {\n * __unsafeContent: [\n * './dist/**\\/*.js',\n * './src/**\\/*.{astro,vue,jsx,tsx}'\n * ]\n * }\n * ```\n */\n __unsafeContent?: Array<string | RawContent>;\n}\n\nconst INTEGRATION_NAME = 'astro-purgecss' as const;\n\n/**\n * default extractor to handle various CSS selector patterns\n * @param content string\n */\nconst defaultExtractor = (content: string) =>\n content.match(/[\\w-/:\\.#\\(\\),';%]+(?<!:)/g) || [];\n\n/**\n * Astro integration for PurgeCSS that removes unused CSS from the final build\n * @param options - PurgeCSS configuration options\n * @returns AstroIntegration - The configured Astro integration\n */\nfunction Plugin(options: PurgeCSSOptions = {}): AstroIntegration {\n let config: AstroConfig;\n const { strategy = 'default', __unsafeContent, ...purgecssOptions } = options;\n\n return {\n name: INTEGRATION_NAME,\n hooks: {\n 'astro:config:done': ({ config: cfg }) => {\n config = cfg;\n },\n ...(strategy === 'cache-buster' && {\n 'astro:build:setup': ({ vite, logger }) => {\n if (!vite.plugins) vite.plugins = [];\n vite.plugins.push({\n name: 'inject-css-cache-buster',\n apply: 'build',\n enforce: 'pre',\n transform(code, id) {\n if (!/\\.(css|scss|sass|less|styl)(\\?|$)/.test(id)) {\n return null;\n }\n logger.info(`Injecting cache-buster CSS into: ${id}`);\n return {\n code: `/*! Build: ${randomUUID().slice(0, 8)} */\\n` + code,\n map: null\n };\n }\n });\n }\n }),\n 'astro:build:done': async ({ dir, pages, logger }) => {\n const buildMode = config.output;\n logger.info(`📦 Running in '${buildMode}' mode`);\n\n // Convert the URL to a filesystem path\n const outDir = cleanPath(dir);\n\n // skip file rehashing for SSR/Server mode or cache-buster strategy\n const skipRehash =\n buildMode !== 'static' || strategy === 'cache-buster';\n\n // Validate required Astro configuration\n if (!outDir || !config.build.format || !config.build.assets) {\n logger.warn(\n `${INTEGRATION_NAME} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`\n );\n return;\n }\n\n // Run PurgeCSS on all CSS files\n const purgeResults = await new PurgeCSS().purge({\n css: [`${outDir}/**/*.css`.replace(/\\\\/g, '/')],\n defaultExtractor,\n ...purgecssOptions,\n content: __unsafeContent ?? [\n `${outDir}/**/*.html`.replace(/\\\\/g, '/'),\n `${outDir}/**/*.js`.replace(/\\\\/g, '/'),\n ...(purgecssOptions.content || [])\n ]\n });\n\n // Filter out non-CSS files from purge results\n const purgedCssFiles = purgeResults.filter(({ file }) =>\n file?.endsWith('.css')\n ) as Array<{\n css: string;\n file: string;\n }>;\n\n if (purgedCssFiles.length === 0) {\n logger.info('ℹ️ No CSS files found to process');\n return;\n }\n\n logger.info(\n `Found ${purgedCssFiles.length} CSS ${purgedCssFiles.length === 1 ? 'file' : 'files'} to process`\n );\n\n // If SSR/Server mode or cache-buster strategy skip file rehash\n if (skipRehash) {\n await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n await writeCssFile(file, css, file);\n success(file.replace(outDir, ''));\n })\n );\n logger.info('🎉 Purging completed successfully!');\n return;\n }\n\n // Process files for static mode with content hashing\n let processedFiles = await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n const isAssetFile = file.includes(config.build.assets);\n\n // Skip rehashing for non-asset files (not generated by astro)\n // ex: assets/styles/light.css\n if (!isAssetFile) {\n await writeCssFile(file, css, file);\n const relativePath = file.replace(outDir, '');\n success(relativePath);\n return {\n oldFilename: relativePath,\n newFilename: relativePath\n };\n }\n\n // Generate new filename with content hash\n const hashedFilename = generateFileHash(file, css);\n await writeCssFile(hashedFilename, css, file);\n\n const relativeOldPath = file.replace(outDir, '');\n const relativeNewPath = hashedFilename.replace(outDir, '');\n success(relativeNewPath);\n\n return {\n oldFilename: relativeOldPath,\n newFilename: relativeNewPath\n };\n })\n );\n\n // Filter to only get files that actually changed\n const changedFiles = processedFiles.filter(\n ({ oldFilename, newFilename }) => oldFilename !== newFilename\n );\n\n if (changedFiles.length > 0) {\n logger.info(\n `Updating ${changedFiles.length} CSS ${changedFiles.length === 1 ? 'reference' : 'references'} in HTML files...`\n );\n // Get all HTML pages based on build format\n const htmlFiles = pages\n .filter((page) => typeof page.pathname === 'string')\n .map((page) => {\n const pathname = page.pathname as string;\n\n // Handle root/index page\n if (pathname === '') {\n return join(outDir, 'index.html');\n }\n\n /**\n * Custom 404 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-404-error-page\n */\n if (pathname === '404/' || pathname === '404') {\n return join(outDir, '404.html');\n }\n\n /**\n * Custom 500 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-500-error-page\n */\n if (pathname === '500/' || pathname === '500') {\n return join(outDir, '500.html');\n }\n\n switch (config.build.format) {\n case 'file':\n // Format: /blog -> /blog.html\n return join(outDir, `${pathname}.html`);\n\n case 'directory':\n // Format: /blog -> /blog/index.html\n return join(outDir, pathname, 'index.html');\n\n case 'preserve':\n // Check if direct HTML file exists, otherwise use directory format\n const directFile = join(outDir, `${pathname}.html`);\n return existsSync(directFile)\n ? directFile\n : join(outDir, pathname, 'index.html');\n }\n });\n\n // Update CSS references in HTML files\n await Promise.all(\n htmlFiles.map(async (htmlFile) => {\n let content = await readFileContent(htmlFile);\n\n for (const { oldFilename, newFilename } of changedFiles) {\n const normalizedOldPath = oldFilename.replace(/\\\\/g, '/');\n const normalizedNewPath = newFilename.replace(/\\\\/g, '/');\n\n content = content.replace(\n new RegExp(normalizedOldPath, 'g'),\n normalizedNewPath\n );\n }\n\n await writeFileContent(htmlFile, content);\n success(htmlFile.replace(outDir, ''));\n })\n );\n }\n\n logger.info('🎉 Purging completed successfully!');\n }\n }\n };\n}\n\nexport default Plugin;\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
|
-
import { UserDefinedOptions } from 'purgecss';
|
|
2
|
+
import { UserDefinedOptions, RawContent } from 'purgecss';
|
|
3
3
|
|
|
4
4
|
type PurgeStrategy = 'default' | 'cache-buster';
|
|
5
5
|
/**
|
|
@@ -8,6 +8,26 @@ type PurgeStrategy = 'default' | 'cache-buster';
|
|
|
8
8
|
*/
|
|
9
9
|
interface PurgeCSSOptions extends Partial<UserDefinedOptions> {
|
|
10
10
|
strategy?: PurgeStrategy;
|
|
11
|
+
/**
|
|
12
|
+
* ⚠️ UNSAFE: Completely overrides the default content globs.
|
|
13
|
+
* When provided, only these content sources will be scanned by PurgeCSS.
|
|
14
|
+
* The default globs (outDir/**\/*.html and outDir/**\/*.js) will be ignored.
|
|
15
|
+
*
|
|
16
|
+
* Use this ONLY if the default globs cause performance issues on very large sites.
|
|
17
|
+
* The double underscore prefix indicates this is an advanced option that should
|
|
18
|
+
* be used with extreme caution.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* {
|
|
23
|
+
* __unsafeContent: [
|
|
24
|
+
* './dist/**\/*.js',
|
|
25
|
+
* './src/**\/*.{astro,vue,jsx,tsx}'
|
|
26
|
+
* ]
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
__unsafeContent?: Array<string | RawContent>;
|
|
11
31
|
}
|
|
12
32
|
/**
|
|
13
33
|
* Astro integration for PurgeCSS that removes unused CSS from the final build
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
|
-
import { UserDefinedOptions } from 'purgecss';
|
|
2
|
+
import { UserDefinedOptions, RawContent } from 'purgecss';
|
|
3
3
|
|
|
4
4
|
type PurgeStrategy = 'default' | 'cache-buster';
|
|
5
5
|
/**
|
|
@@ -8,6 +8,26 @@ type PurgeStrategy = 'default' | 'cache-buster';
|
|
|
8
8
|
*/
|
|
9
9
|
interface PurgeCSSOptions extends Partial<UserDefinedOptions> {
|
|
10
10
|
strategy?: PurgeStrategy;
|
|
11
|
+
/**
|
|
12
|
+
* ⚠️ UNSAFE: Completely overrides the default content globs.
|
|
13
|
+
* When provided, only these content sources will be scanned by PurgeCSS.
|
|
14
|
+
* The default globs (outDir/**\/*.html and outDir/**\/*.js) will be ignored.
|
|
15
|
+
*
|
|
16
|
+
* Use this ONLY if the default globs cause performance issues on very large sites.
|
|
17
|
+
* The double underscore prefix indicates this is an advanced option that should
|
|
18
|
+
* be used with extreme caution.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* {
|
|
23
|
+
* __unsafeContent: [
|
|
24
|
+
* './dist/**\/*.js',
|
|
25
|
+
* './src/**\/*.{astro,vue,jsx,tsx}'
|
|
26
|
+
* ]
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
__unsafeContent?: Array<string | RawContent>;
|
|
11
31
|
}
|
|
12
32
|
/**
|
|
13
33
|
* Astro integration for PurgeCSS that removes unused CSS from the final build
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {existsSync}from'fs';import {join}from'path';import {randomUUID,createHash}from'crypto';import {PurgeCSS}from'purgecss';import {unlink,readFile,writeFile}from'fs/promises';import {fileURLToPath}from'url';var F,O,
|
|
2
|
-
`+
|
|
1
|
+
import {existsSync}from'fs';import {join}from'path';import {randomUUID,createHash}from'crypto';import {PurgeCSS}from'purgecss';import {unlink,readFile,writeFile}from'fs/promises';import {fileURLToPath}from'url';var F,O,P,E,A=true;typeof process<"u"&&({FORCE_COLOR:F,NODE_DISABLE_COLORS:O,NO_COLOR:P,TERM:E}=process.env||{},A=process.stdout&&process.stdout.isTTY);var M={enabled:!O&&P==null&&E!=="dumb"&&(F!=null&&F!=="0"||A)};function e(n,t){let a=new RegExp(`\\x1b\\[${t}m`,"g"),x=`\x1B[${n}m`,g=`\x1B[${t}m`;return function(i){return !M.enabled||i==null?i:x+(~(""+i).indexOf(g)?i.replace(a,g+x):i)+g}}var S=e(2,22),T=e(31,39),D=e(32,39);async function L(n){try{return await readFile(n,"utf8")}catch(t){return N(`Error reading file ${n}: ${t}`),""}}async function R(n,t){try{await writeFile(n,t,"utf8");}catch(a){N(`Error writing file ${n}: ${a}`);}}async function y(n,t,a){await R(n,t),a!==n&&existsSync(a)&&await unlink(a);}function U(n,t){let a=createHash("sha256").update(t).digest("hex").slice(0,8);return `${n.slice(0,-13)}.${a}.css`}function _(n){if(!(n instanceof URL))throw new TypeError("Expected a URL object");let t=fileURLToPath(n).replace(/\/+$/,"");return process.platform==="win32"?t.replace(/^\/+/,""):t}var I=new Intl.DateTimeFormat("en-us",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:false});function h(n){let t=I.format(new Date);console.log(S(t),D("\u25B6"),n);}function N(n){let t=I.format(new Date);console.error(S(t),T("\u25A0"),n);}var k="astro-purgecss",K=n=>n.match(/[\w-/:\.#\(\),';%]+(?<!:)/g)||[];function Q(n={}){let t,{strategy:a="default",__unsafeContent:x,...g}=n;return {name:k,hooks:{"astro:config:done":({config:i})=>{t=i;},...a==="cache-buster"&&{"astro:build:setup":({vite:i,logger:C})=>{i.plugins||(i.plugins=[]),i.plugins.push({name:"inject-css-cache-buster",apply:"build",enforce:"pre",transform(l,f){return /\.(css|scss|sass|less|styl)(\?|$)/.test(f)?(C.info(`Injecting cache-buster CSS into: ${f}`),{code:`/*! Build: ${randomUUID().slice(0,8)} */
|
|
2
|
+
`+l,map:null}):null}});}},"astro:build:done":async({dir:i,pages:C,logger:l})=>{let f=t.output;l.info(`\u{1F4E6} Running in '${f}' mode`);let s=_(i),j=f!=="static"||a==="cache-buster";if(!s||!t.build.format||!t.build.assets){l.warn(`${k} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`);return}let d=(await new PurgeCSS().purge({css:[`${s}/**/*.css`.replace(/\\/g,"/")],defaultExtractor:K,...g,content:x??[`${s}/**/*.html`.replace(/\\/g,"/"),`${s}/**/*.js`.replace(/\\/g,"/"),...g.content||[]]})).filter(({file:c})=>c?.endsWith(".css"));if(d.length===0){l.info("\u2139\uFE0F No CSS files found to process");return}if(l.info(`Found ${d.length} CSS ${d.length===1?"file":"files"} to process`),j){await Promise.all(d.map(async({css:c,file:r})=>{await y(r,c,r),h(r.replace(s,""));})),l.info("\u{1F389} Purging completed successfully!");return}let w=(await Promise.all(d.map(async({css:c,file:r})=>{if(!r.includes(t.build.assets)){await y(r,c,r);let m=r.replace(s,"");return h(m),{oldFilename:m,newFilename:m}}let p=U(r,c);await y(p,c,r);let $=r.replace(s,""),b=p.replace(s,"");return h(b),{oldFilename:$,newFilename:b}}))).filter(({oldFilename:c,newFilename:r})=>c!==r);if(w.length>0){l.info(`Updating ${w.length} CSS ${w.length===1?"reference":"references"} in HTML files...`);let c=C.filter(r=>typeof r.pathname=="string").map(r=>{let o=r.pathname;if(o==="")return join(s,"index.html");if(o==="404/"||o==="404")return join(s,"404.html");if(o==="500/"||o==="500")return join(s,"500.html");switch(t.build.format){case "file":return join(s,`${o}.html`);case "directory":return join(s,o,"index.html");case "preserve":let p=join(s,`${o}.html`);return existsSync(p)?p:join(s,o,"index.html")}});await Promise.all(c.map(async r=>{let o=await L(r);for(let{oldFilename:p,newFilename:$}of w){let b=p.replace(/\\/g,"/"),m=$.replace(/\\/g,"/");o=o.replace(new RegExp(b,"g"),m);}await R(r,o),h(r.replace(s,""));}));}l.info("\u{1F389} Purging completed successfully!");}}}}var _e=Q;export{_e as default};//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/colors.mjs","../src/utils.ts","../src/index.ts"],"names":["FORCE_COLOR","NODE_DISABLE_COLORS","NO_COLOR","TERM","isTTY","$","init","x","y","rgx","open","close","txt","dim","red","green","readFileContent","filePath","readFile","err","error","writeFileContent","content","writeFile","writeCssFile","newFilePath","css","oldFilePath","existsSync","unlink","generateFileHash","hash","createHash","cleanPath","file","path","fileURLToPath","dt","success","message","date","INTEGRATION_NAME","defaultExtractor","Plugin","options","config","strategy","purgecssOptions","cfg","vite","logger","code","id","randomUUID","dir","pages","buildMode","outDir","skipRehash","purgedCssFiles","PurgeCSS","changedFiles","relativePath","hashedFilename","relativeOldPath","relativeNewPath","oldFilename","newFilename","htmlFiles","page","pathname","join","directFile","htmlFile","normalizedOldPath","normalizedNewPath","index_default"],"mappings":"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","file":"index.js","sourcesContent":["let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;\nif (typeof process !== 'undefined') {\n\t({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});\n\tisTTY = process.stdout && process.stdout.isTTY;\n}\n\nexport const $ = {\n\tenabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (\n\t\tFORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY\n\t)\n}\n\nfunction init(x, y) {\n\tlet rgx = new RegExp(`\\\\x1b\\\\[${y}m`, 'g');\n\tlet open = `\\x1b[${x}m`, close = `\\x1b[${y}m`;\n\n\treturn function (txt) {\n\t\tif (!$.enabled || txt == null) return txt;\n\t\treturn open + (!!~(''+txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;\n\t};\n}\n\n// modifiers\nexport const reset = init(0, 0);\nexport const bold = init(1, 22);\nexport const dim = init(2, 22);\nexport const italic = init(3, 23);\nexport const underline = init(4, 24);\nexport const inverse = init(7, 27);\nexport const hidden = init(8, 28);\nexport const strikethrough = init(9, 29);\n\n// colors\nexport const black = init(30, 39);\nexport const red = init(31, 39);\nexport const green = init(32, 39);\nexport const yellow = init(33, 39);\nexport const blue = init(34, 39);\nexport const magenta = init(35, 39);\nexport const cyan = init(36, 39);\nexport const white = init(37, 39);\nexport const gray = init(90, 39);\nexport const grey = init(90, 39);\n\n// background colors\nexport const bgBlack = init(40, 49);\nexport const bgRed = init(41, 49);\nexport const bgGreen = init(42, 49);\nexport const bgYellow = init(43, 49);\nexport const bgBlue = init(44, 49);\nexport const bgMagenta = init(45, 49);\nexport const bgCyan = init(46, 49);\nexport const bgWhite = init(47, 49);\n","import { dim, green, red } from 'kleur/colors';\nimport { createHash } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n const content = await readFile(filePath, 'utf8');\n return content;\n } catch (err) {\n error(`Error reading file ${filePath}: ${err}`);\n return '';\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string) {\n try {\n await writeFile(filePath, content, 'utf8');\n } catch (err) {\n error(`Error writing file ${filePath}: ${err}`);\n }\n}\n\nexport async function writeCssFile(\n newFilePath: string,\n css: string,\n oldFilePath: string\n) {\n await writeFileContent(newFilePath, css);\n\n // Remove old file if it exists and is different from new file\n if (oldFilePath !== newFilePath && existsSync(oldFilePath)) {\n await unlink(oldFilePath);\n }\n}\n\nexport function generateFileHash(filePath: string, content: string) {\n // Get content hash before writing to file\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n\n // Generate new file name with hash\n // Astro original hash is 8 characters long\n return `${filePath.slice(0, -13)}.${hash}.css`;\n}\n\n// Clean from extra slash on windows and trailing forward slash on non-windows\nexport function cleanPath(file: URL): string {\n if (!(file instanceof URL)) {\n throw new TypeError('Expected a URL object');\n }\n\n // Remove trailing forward slash if present\n let path = fileURLToPath(file).replace(/\\/+$/, '');\n\n // Remove leading forward slash on windows if present\n return process.platform === 'win32' ? path.replace(/^\\/+/, '') : path;\n}\n\nexport const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n});\n\nexport function success(message: string) {\n const date = dt.format(new Date());\n console.log(dim(date), green('▶'), message);\n}\n\nexport function error(message: string) {\n const date = dt.format(new Date());\n console.error(dim(date), red('■'), message);\n}\n","import type { AstroConfig, AstroIntegration } from 'astro';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { PurgeCSS, type UserDefinedOptions } from 'purgecss';\n\nimport {\n cleanPath,\n generateFileHash,\n readFileContent,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\n\ntype PurgeStrategy = 'default' | 'cache-buster';\n\n/**\n * Extended PurgeCSS options interface that allows partial configuration\n * of the standard PurgeCSS options\n */\nexport interface PurgeCSSOptions extends Partial<UserDefinedOptions> {\n strategy?: PurgeStrategy;\n}\n\nconst INTEGRATION_NAME = 'astro-purgecss' as const;\n\n/**\n * default extractor to handle various CSS selector patterns\n * @param content string\n */\nconst defaultExtractor = (content: string) =>\n content.match(/[\\w-/:\\.#\\(\\),';%]+(?<!:)/g) || [];\n\n/**\n * Astro integration for PurgeCSS that removes unused CSS from the final build\n * @param options - PurgeCSS configuration options\n * @returns AstroIntegration - The configured Astro integration\n */\nfunction Plugin(options: PurgeCSSOptions = {}): AstroIntegration {\n let config: AstroConfig;\n const { strategy = 'default', ...purgecssOptions } = options;\n\n return {\n name: INTEGRATION_NAME,\n hooks: {\n 'astro:config:done': ({ config: cfg }) => {\n config = cfg;\n },\n ...(strategy === 'cache-buster' && {\n 'astro:build:setup': ({ vite, logger }) => {\n if (!vite.plugins) vite.plugins = [];\n vite.plugins.push({\n name: 'inject-css-cache-buster',\n apply: 'build',\n enforce: 'pre',\n transform(code, id) {\n if (!/\\.(css|scss|sass|less|styl)(\\?|$)/.test(id)) {\n return null;\n }\n logger.info(`Injecting cache-buster CSS into: ${id}`);\n return {\n code: `/*! Build: ${randomUUID().slice(0, 8)} */\\n` + code,\n map: null\n };\n }\n });\n }\n }),\n 'astro:build:done': async ({ dir, pages, logger }) => {\n const buildMode = config.output;\n logger.info(`📦 Running in '${buildMode}' mode`);\n\n // Convert the URL to a filesystem path\n const outDir = cleanPath(dir);\n\n // skip file rehashing for SSR/Server mode or cache-buster strategy\n const skipRehash =\n buildMode !== 'static' || strategy === 'cache-buster';\n\n // Validate required Astro configuration\n if (!outDir || !config.build.format || !config.build.assets) {\n logger.warn(\n `${INTEGRATION_NAME} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`\n );\n return;\n }\n\n // Run PurgeCSS on all CSS files\n // Replace is needed to make sure to pass correct glob format on windows machines\n const purgeResults = await new PurgeCSS().purge({\n css: [`${outDir}/**/*.css`.replace(/\\\\/g, '/')],\n defaultExtractor,\n ...purgecssOptions,\n content: [\n `${outDir}/**/*.html`.replace(/\\\\/g, '/'),\n `${outDir}/**/*.js`.replace(/\\\\/g, '/'),\n ...(purgecssOptions.content || [])\n ]\n });\n\n // Filter out non-CSS files from purge results\n const purgedCssFiles = purgeResults.filter(({ file }) =>\n file?.endsWith('.css')\n ) as Array<{\n css: string;\n file: string;\n }>;\n\n if (purgedCssFiles.length === 0) {\n logger.info('ℹ️ No CSS files found to process');\n return;\n }\n\n logger.info(\n `Found ${purgedCssFiles.length} CSS ${purgedCssFiles.length === 1 ? 'file' : 'files'} to process`\n );\n\n // If SSR/Server mode or cache-buster strategy skip file rehash\n if (skipRehash) {\n await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n await writeCssFile(file, css, file);\n success(file.replace(outDir, ''));\n })\n );\n logger.info('🎉 Purging completed successfully!');\n return;\n }\n\n // Process files for static mode with content hashing\n let processedFiles = await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n const isAssetFile = file.includes(config.build.assets);\n\n // Skip rehashing for non-asset files (not generated by astro)\n // ex: assets/styles/light.css\n if (!isAssetFile) {\n await writeCssFile(file, css, file);\n const relativePath = file.replace(outDir, '');\n success(relativePath);\n return {\n oldFilename: relativePath,\n newFilename: relativePath\n };\n }\n\n // Generate new filename with content hash\n const hashedFilename = generateFileHash(file, css);\n await writeCssFile(hashedFilename, css, file);\n\n const relativeOldPath = file.replace(outDir, '');\n const relativeNewPath = hashedFilename.replace(outDir, '');\n success(relativeNewPath);\n\n return {\n oldFilename: relativeOldPath,\n newFilename: relativeNewPath\n };\n })\n );\n\n // Filter to only get files that actually changed\n const changedFiles = processedFiles.filter(\n ({ oldFilename, newFilename }) => oldFilename !== newFilename\n );\n\n if (changedFiles.length > 0) {\n logger.info(\n `Updating ${changedFiles.length} CSS ${changedFiles.length === 1 ? 'reference' : 'references'} in HTML files...`\n );\n // Get all HTML pages based on build format\n const htmlFiles = pages\n .filter((page) => typeof page.pathname === 'string')\n .map((page) => {\n const pathname = page.pathname as string;\n\n // Handle root/index page\n if (pathname === '') {\n return join(outDir, 'index.html');\n }\n\n /**\n * Custom 404 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-404-error-page\n */\n if (pathname === '404/' || pathname === '404') {\n return join(outDir, '404.html');\n }\n\n /**\n * Custom 500 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-500-error-page\n */\n if (pathname === '500/' || pathname === '500') {\n return join(outDir, '500.html');\n }\n\n switch (config.build.format) {\n case 'file':\n // Format: /blog -> /blog.html\n return join(outDir, `${pathname}.html`);\n\n case 'directory':\n // Format: /blog -> /blog/index.html\n return join(outDir, pathname, 'index.html');\n\n case 'preserve':\n // Check if direct HTML file exists, otherwise use directory format\n const directFile = join(outDir, `${pathname}.html`);\n return existsSync(directFile)\n ? directFile\n : join(outDir, pathname, 'index.html');\n }\n });\n\n // Update CSS references in HTML files\n await Promise.all(\n htmlFiles.map(async (htmlFile) => {\n let content = await readFileContent(htmlFile);\n\n for (const { oldFilename, newFilename } of changedFiles) {\n const normalizedOldPath = oldFilename.replace(/\\\\/g, '/');\n const normalizedNewPath = newFilename.replace(/\\\\/g, '/');\n\n content = content.replace(\n new RegExp(normalizedOldPath, 'g'),\n normalizedNewPath\n );\n }\n\n await writeFileContent(htmlFile, content);\n success(htmlFile.replace(outDir, ''));\n })\n );\n }\n\n logger.info('🎉 Purging completed successfully!');\n }\n }\n };\n}\n\nexport default Plugin;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.pnpm/kleur@4.1.5/node_modules/kleur/colors.mjs","../src/utils.ts","../src/index.ts"],"names":["FORCE_COLOR","NODE_DISABLE_COLORS","NO_COLOR","TERM","isTTY","$","init","x","y","rgx","open","close","txt","dim","red","green","readFileContent","filePath","readFile","err","error","writeFileContent","content","writeFile","writeCssFile","newFilePath","css","oldFilePath","existsSync","unlink","generateFileHash","hash","createHash","cleanPath","file","path","fileURLToPath","dt","success","message","date","INTEGRATION_NAME","defaultExtractor","Plugin","options","config","strategy","__unsafeContent","purgecssOptions","cfg","vite","logger","code","id","randomUUID","dir","pages","buildMode","outDir","skipRehash","purgedCssFiles","PurgeCSS","changedFiles","relativePath","hashedFilename","relativeOldPath","relativeNewPath","oldFilename","newFilename","htmlFiles","page","pathname","join","directFile","htmlFile","normalizedOldPath","normalizedNewPath","index_default"],"mappings":"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","file":"index.js","sourcesContent":["let FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM, isTTY=true;\nif (typeof process !== 'undefined') {\n\t({ FORCE_COLOR, NODE_DISABLE_COLORS, NO_COLOR, TERM } = process.env || {});\n\tisTTY = process.stdout && process.stdout.isTTY;\n}\n\nexport const $ = {\n\tenabled: !NODE_DISABLE_COLORS && NO_COLOR == null && TERM !== 'dumb' && (\n\t\tFORCE_COLOR != null && FORCE_COLOR !== '0' || isTTY\n\t)\n}\n\nfunction init(x, y) {\n\tlet rgx = new RegExp(`\\\\x1b\\\\[${y}m`, 'g');\n\tlet open = `\\x1b[${x}m`, close = `\\x1b[${y}m`;\n\n\treturn function (txt) {\n\t\tif (!$.enabled || txt == null) return txt;\n\t\treturn open + (!!~(''+txt).indexOf(close) ? txt.replace(rgx, close + open) : txt) + close;\n\t};\n}\n\n// modifiers\nexport const reset = init(0, 0);\nexport const bold = init(1, 22);\nexport const dim = init(2, 22);\nexport const italic = init(3, 23);\nexport const underline = init(4, 24);\nexport const inverse = init(7, 27);\nexport const hidden = init(8, 28);\nexport const strikethrough = init(9, 29);\n\n// colors\nexport const black = init(30, 39);\nexport const red = init(31, 39);\nexport const green = init(32, 39);\nexport const yellow = init(33, 39);\nexport const blue = init(34, 39);\nexport const magenta = init(35, 39);\nexport const cyan = init(36, 39);\nexport const white = init(37, 39);\nexport const gray = init(90, 39);\nexport const grey = init(90, 39);\n\n// background colors\nexport const bgBlack = init(40, 49);\nexport const bgRed = init(41, 49);\nexport const bgGreen = init(42, 49);\nexport const bgYellow = init(43, 49);\nexport const bgBlue = init(44, 49);\nexport const bgMagenta = init(45, 49);\nexport const bgCyan = init(46, 49);\nexport const bgWhite = init(47, 49);\n","import { dim, green, red } from 'kleur/colors';\nimport { createHash } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { readFile, unlink, writeFile } from 'node:fs/promises';\nimport { fileURLToPath } from 'node:url';\n\nexport async function readFileContent(filePath: string): Promise<string> {\n try {\n const content = await readFile(filePath, 'utf8');\n return content;\n } catch (err) {\n error(`Error reading file ${filePath}: ${err}`);\n return '';\n }\n}\n\nexport async function writeFileContent(filePath: string, content: string) {\n try {\n await writeFile(filePath, content, 'utf8');\n } catch (err) {\n error(`Error writing file ${filePath}: ${err}`);\n }\n}\n\nexport async function writeCssFile(\n newFilePath: string,\n css: string,\n oldFilePath: string\n) {\n await writeFileContent(newFilePath, css);\n\n // Remove old file if it exists and is different from new file\n if (oldFilePath !== newFilePath && existsSync(oldFilePath)) {\n await unlink(oldFilePath);\n }\n}\n\nexport function generateFileHash(filePath: string, content: string) {\n // Get content hash before writing to file\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n\n // Generate new file name with hash\n // Astro original hash is 8 characters long\n return `${filePath.slice(0, -13)}.${hash}.css`;\n}\n\n// Clean from extra slash on windows and trailing forward slash on non-windows\nexport function cleanPath(file: URL): string {\n if (!(file instanceof URL)) {\n throw new TypeError('Expected a URL object');\n }\n\n // Remove trailing forward slash if present\n let path = fileURLToPath(file).replace(/\\/+$/, '');\n\n // Remove leading forward slash on windows if present\n return process.platform === 'win32' ? path.replace(/^\\/+/, '') : path;\n}\n\nexport const dt = new Intl.DateTimeFormat('en-us', {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n});\n\nexport function success(message: string) {\n const date = dt.format(new Date());\n console.log(dim(date), green('▶'), message);\n}\n\nexport function error(message: string) {\n const date = dt.format(new Date());\n console.error(dim(date), red('■'), message);\n}\n","import type { AstroConfig, AstroIntegration } from 'astro';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { PurgeCSS, type UserDefinedOptions, type RawContent } from 'purgecss';\n\nimport {\n cleanPath,\n generateFileHash,\n readFileContent,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\n\ntype PurgeStrategy = 'default' | 'cache-buster';\n\n/**\n * Extended PurgeCSS options interface that allows partial configuration\n * of the standard PurgeCSS options\n */\nexport interface PurgeCSSOptions extends Partial<UserDefinedOptions> {\n strategy?: PurgeStrategy;\n /**\n * ⚠️ UNSAFE: Completely overrides the default content globs.\n * When provided, only these content sources will be scanned by PurgeCSS.\n * The default globs (outDir/**\\/*.html and outDir/**\\/*.js) will be ignored.\n *\n * Use this ONLY if the default globs cause performance issues on very large sites.\n * The double underscore prefix indicates this is an advanced option that should\n * be used with extreme caution.\n *\n * @example\n * ```ts\n * {\n * __unsafeContent: [\n * './dist/**\\/*.js',\n * './src/**\\/*.{astro,vue,jsx,tsx}'\n * ]\n * }\n * ```\n */\n __unsafeContent?: Array<string | RawContent>;\n}\n\nconst INTEGRATION_NAME = 'astro-purgecss' as const;\n\n/**\n * default extractor to handle various CSS selector patterns\n * @param content string\n */\nconst defaultExtractor = (content: string) =>\n content.match(/[\\w-/:\\.#\\(\\),';%]+(?<!:)/g) || [];\n\n/**\n * Astro integration for PurgeCSS that removes unused CSS from the final build\n * @param options - PurgeCSS configuration options\n * @returns AstroIntegration - The configured Astro integration\n */\nfunction Plugin(options: PurgeCSSOptions = {}): AstroIntegration {\n let config: AstroConfig;\n const { strategy = 'default', __unsafeContent, ...purgecssOptions } = options;\n\n return {\n name: INTEGRATION_NAME,\n hooks: {\n 'astro:config:done': ({ config: cfg }) => {\n config = cfg;\n },\n ...(strategy === 'cache-buster' && {\n 'astro:build:setup': ({ vite, logger }) => {\n if (!vite.plugins) vite.plugins = [];\n vite.plugins.push({\n name: 'inject-css-cache-buster',\n apply: 'build',\n enforce: 'pre',\n transform(code, id) {\n if (!/\\.(css|scss|sass|less|styl)(\\?|$)/.test(id)) {\n return null;\n }\n logger.info(`Injecting cache-buster CSS into: ${id}`);\n return {\n code: `/*! Build: ${randomUUID().slice(0, 8)} */\\n` + code,\n map: null\n };\n }\n });\n }\n }),\n 'astro:build:done': async ({ dir, pages, logger }) => {\n const buildMode = config.output;\n logger.info(`📦 Running in '${buildMode}' mode`);\n\n // Convert the URL to a filesystem path\n const outDir = cleanPath(dir);\n\n // skip file rehashing for SSR/Server mode or cache-buster strategy\n const skipRehash =\n buildMode !== 'static' || strategy === 'cache-buster';\n\n // Validate required Astro configuration\n if (!outDir || !config.build.format || !config.build.assets) {\n logger.warn(\n `${INTEGRATION_NAME} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`\n );\n return;\n }\n\n // Run PurgeCSS on all CSS files\n const purgeResults = await new PurgeCSS().purge({\n css: [`${outDir}/**/*.css`.replace(/\\\\/g, '/')],\n defaultExtractor,\n ...purgecssOptions,\n content: __unsafeContent ?? [\n `${outDir}/**/*.html`.replace(/\\\\/g, '/'),\n `${outDir}/**/*.js`.replace(/\\\\/g, '/'),\n ...(purgecssOptions.content || [])\n ]\n });\n\n // Filter out non-CSS files from purge results\n const purgedCssFiles = purgeResults.filter(({ file }) =>\n file?.endsWith('.css')\n ) as Array<{\n css: string;\n file: string;\n }>;\n\n if (purgedCssFiles.length === 0) {\n logger.info('ℹ️ No CSS files found to process');\n return;\n }\n\n logger.info(\n `Found ${purgedCssFiles.length} CSS ${purgedCssFiles.length === 1 ? 'file' : 'files'} to process`\n );\n\n // If SSR/Server mode or cache-buster strategy skip file rehash\n if (skipRehash) {\n await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n await writeCssFile(file, css, file);\n success(file.replace(outDir, ''));\n })\n );\n logger.info('🎉 Purging completed successfully!');\n return;\n }\n\n // Process files for static mode with content hashing\n let processedFiles = await Promise.all(\n purgedCssFiles.map(async ({ css, file }) => {\n const isAssetFile = file.includes(config.build.assets);\n\n // Skip rehashing for non-asset files (not generated by astro)\n // ex: assets/styles/light.css\n if (!isAssetFile) {\n await writeCssFile(file, css, file);\n const relativePath = file.replace(outDir, '');\n success(relativePath);\n return {\n oldFilename: relativePath,\n newFilename: relativePath\n };\n }\n\n // Generate new filename with content hash\n const hashedFilename = generateFileHash(file, css);\n await writeCssFile(hashedFilename, css, file);\n\n const relativeOldPath = file.replace(outDir, '');\n const relativeNewPath = hashedFilename.replace(outDir, '');\n success(relativeNewPath);\n\n return {\n oldFilename: relativeOldPath,\n newFilename: relativeNewPath\n };\n })\n );\n\n // Filter to only get files that actually changed\n const changedFiles = processedFiles.filter(\n ({ oldFilename, newFilename }) => oldFilename !== newFilename\n );\n\n if (changedFiles.length > 0) {\n logger.info(\n `Updating ${changedFiles.length} CSS ${changedFiles.length === 1 ? 'reference' : 'references'} in HTML files...`\n );\n // Get all HTML pages based on build format\n const htmlFiles = pages\n .filter((page) => typeof page.pathname === 'string')\n .map((page) => {\n const pathname = page.pathname as string;\n\n // Handle root/index page\n if (pathname === '') {\n return join(outDir, 'index.html');\n }\n\n /**\n * Custom 404 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-404-error-page\n */\n if (pathname === '404/' || pathname === '404') {\n return join(outDir, '404.html');\n }\n\n /**\n * Custom 500 Error Page\n *\n * @see https://docs.astro.build/en/basics/astro-pages/#custom-500-error-page\n */\n if (pathname === '500/' || pathname === '500') {\n return join(outDir, '500.html');\n }\n\n switch (config.build.format) {\n case 'file':\n // Format: /blog -> /blog.html\n return join(outDir, `${pathname}.html`);\n\n case 'directory':\n // Format: /blog -> /blog/index.html\n return join(outDir, pathname, 'index.html');\n\n case 'preserve':\n // Check if direct HTML file exists, otherwise use directory format\n const directFile = join(outDir, `${pathname}.html`);\n return existsSync(directFile)\n ? directFile\n : join(outDir, pathname, 'index.html');\n }\n });\n\n // Update CSS references in HTML files\n await Promise.all(\n htmlFiles.map(async (htmlFile) => {\n let content = await readFileContent(htmlFile);\n\n for (const { oldFilename, newFilename } of changedFiles) {\n const normalizedOldPath = oldFilename.replace(/\\\\/g, '/');\n const normalizedNewPath = newFilename.replace(/\\\\/g, '/');\n\n content = content.replace(\n new RegExp(normalizedOldPath, 'g'),\n normalizedNewPath\n );\n }\n\n await writeFileContent(htmlFile, content);\n success(htmlFile.replace(outDir, ''));\n })\n );\n }\n\n logger.info('🎉 Purging completed successfully!');\n }\n }\n };\n}\n\nexport default Plugin;\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-purgecss",
|
|
3
3
|
"description": "Remove unused CSS rules from your final Astro bundle",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.0",
|
|
5
5
|
"homepage": "https://github.com/codiume/orbit",
|
|
6
6
|
"bugs": "https://github.com/codiume/orbit/issues",
|
|
7
7
|
"author": "codiume",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"astro": "^
|
|
42
|
-
"purgecss": "^
|
|
41
|
+
"astro": "^6.0.0",
|
|
42
|
+
"purgecss": "^8.0.0"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsup",
|