astro-purgecss 4.6.2 → 4.8.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 +48 -23
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
## 📦 Installation
|
|
12
12
|
|
|
13
|
-
### Quick Install
|
|
13
|
+
### ⚡ Quick Install
|
|
14
14
|
|
|
15
15
|
the `astro add` command-line tool automates the installation for you. Run one of the following commands in a new terminal window. (If you aren’t sure which package manager you’re using, run the first command.) Then, follow the prompts, and type “y” in the terminal (meaning “yes”) for each one.
|
|
16
16
|
|
|
@@ -23,7 +23,7 @@ npx astro add astro-purgecss
|
|
|
23
23
|
yarn astro add astro-purgecss
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
### Manual Install
|
|
26
|
+
### 🔧 Manual Install
|
|
27
27
|
|
|
28
28
|
First, install the `purgecss` & `astro-purgecss` packages using your package manager. (If you aren’t sure which package manager you’re using, run the first command.)
|
|
29
29
|
|
|
@@ -75,7 +75,7 @@ export default defineConfig({
|
|
|
75
75
|
});
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
##
|
|
78
|
+
## ⚙️ Configuration
|
|
79
79
|
|
|
80
80
|
[PurgeCSS][purgecss] has a list of options that allow you to customize its behavior. And this Astro integration allow you to pass those options easily in your `astro.config.mjs` file:
|
|
81
81
|
|
|
@@ -88,7 +88,7 @@ export default defineConfig({
|
|
|
88
88
|
safelist: ['random', 'yep', 'button', /^nav-/],
|
|
89
89
|
blocklist: ['usedClass', /^nav-/],
|
|
90
90
|
content: [
|
|
91
|
-
process.cwd() + '/src/**/*.{astro,vue}' // Watching astro and vue sources (
|
|
91
|
+
process.cwd() + '/src/**/*.{astro,vue}' // Watching astro and vue sources (read SSR docs below)
|
|
92
92
|
],
|
|
93
93
|
extractors: [
|
|
94
94
|
{
|
|
@@ -103,15 +103,11 @@ export default defineConfig({
|
|
|
103
103
|
});
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
>
|
|
108
|
-
> If you are using **Astro SSR** in your project, you must add your astro and framework sources files into the `content` option (see in the example). Otherwise, as the package only look at the final build sent to the client, with SSR, some pages may not be included and may break your CSS.
|
|
109
|
-
|
|
110
|
-
### Available Options
|
|
106
|
+
### 📖 Available Options
|
|
111
107
|
|
|
112
108
|
Here is a list of options, that are allowed to be passed in the config:
|
|
113
109
|
|
|
114
|
-
```
|
|
110
|
+
```typescript
|
|
115
111
|
export type PurgeCSSOptions = {
|
|
116
112
|
fontFace?: boolean; // removes any unused @font-face if set to true
|
|
117
113
|
keyframes?: boolean; // removes unused keyframes by setting if set to true
|
|
@@ -121,11 +117,11 @@ export type PurgeCSSOptions = {
|
|
|
121
117
|
safelist?: UserDefinedSafelist; // indicates which selectors are safe to leave in the final CSS
|
|
122
118
|
blocklist?: StringRegExpArray; // blocks the CSS selectors from appearing in the final output CSS
|
|
123
119
|
content?: Array<string | RawContent>;
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
// provides custom functions to extract CSS classes in specific ways (eg. when using tailwind.css)
|
|
121
|
+
extractors?: {
|
|
126
122
|
extractor: (content: string) => string[]; // matched css classes
|
|
127
123
|
extensions: string[]; // file extensions for which this extractor is to be used
|
|
128
|
-
}
|
|
124
|
+
}[];
|
|
129
125
|
};
|
|
130
126
|
```
|
|
131
127
|
|
|
@@ -133,22 +129,51 @@ To learn more about the available options, please refer to [PurgeCSS][purgecss-o
|
|
|
133
129
|
|
|
134
130
|
We have also setup an example repository available here: [example-purgecss](../../apps/example-purgecss)
|
|
135
131
|
|
|
136
|
-
|
|
132
|
+
## 🌐 SSR Mode
|
|
133
|
+
|
|
134
|
+
If you are using **Astro SSR** in your project, you must add your Astro and framework source files into the `content` option (see example below). Since the integration analyzes the final client-side build, some SSR-rendered pages might not be included in the initial scan, which could result in necessary CSS being incorrectly purged.
|
|
135
|
+
|
|
136
|
+
Example configuration for SSR:
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
export default defineConfig({
|
|
140
|
+
integrations: [
|
|
141
|
+
purgecss({
|
|
142
|
+
content: [
|
|
143
|
+
'./src/**/*.{astro,js,jsx,ts,tsx,vue,svelte}'
|
|
144
|
+
// Add any other template files that contain styles
|
|
145
|
+
]
|
|
146
|
+
})
|
|
147
|
+
]
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Important Notes
|
|
152
|
+
|
|
153
|
+
1. **CSS Retention**: Due to the integration's file scanning approach, some unused CSS might be retained. This is a deliberate trade-off to prevent accidentally removing dynamically used styles.
|
|
154
|
+
|
|
155
|
+
2. **Inline Styles vs External Stylesheets**: The integration can more accurately analyze and purge external stylesheets compared to inline styles embedded within components:
|
|
156
|
+
- ✅ **Recommended**: Use external stylesheet files (`.css`)
|
|
157
|
+
- ⚠️ **Less Effective**: Inline styles in component files
|
|
158
|
+
|
|
159
|
+
## ⚠️ Caveats
|
|
137
160
|
|
|
138
161
|
- Some options are not allowed to be passed in your `astro.config.mjs` config file, to not interfere with the internals of this integration.
|
|
139
162
|
|
|
140
163
|
- If you are using Astro view transitions, use the following options so that purgecss keeps the corresponding animations:
|
|
141
164
|
|
|
142
|
-
```
|
|
165
|
+
```js
|
|
143
166
|
export default defineConfig({
|
|
144
167
|
integrations: [
|
|
145
168
|
purgecss({
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
169
|
+
keyframes: false,
|
|
170
|
+
safelist: {
|
|
171
|
+
greedy: [
|
|
172
|
+
/*astro*/
|
|
173
|
+
]
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
]
|
|
152
177
|
});
|
|
153
178
|
```
|
|
154
179
|
|
|
@@ -170,11 +195,11 @@ export default defineConfig({
|
|
|
170
195
|
});
|
|
171
196
|
```
|
|
172
197
|
|
|
173
|
-
## Changelog
|
|
198
|
+
## 📝 Changelog
|
|
174
199
|
|
|
175
200
|
Please see the [Changelog](CHANGELOG.md) for more information on what has changed recently.
|
|
176
201
|
|
|
177
|
-
## Acknowledgements
|
|
202
|
+
## 💝 Acknowledgements
|
|
178
203
|
|
|
179
204
|
- [Purgecss][purgecss]
|
|
180
205
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var path=require('path'),purgecss=require('purgecss'),crypto=require('crypto'),promises=require('fs/promises')
|
|
1
|
+
'use strict';var fs=require('fs'),path=require('path'),url=require('url'),purgecss=require('purgecss'),crypto=require('crypto'),promises=require('fs/promises');var b,S,$,O,R=!0;typeof process<"u"&&({FORCE_COLOR:b,NODE_DISABLE_COLORS:S,NO_COLOR:$,TERM:O}=process.env||{},R=process.stdout&&process.stdout.isTTY);var L={enabled:!S&&$==null&&O!=="dumb"&&(b!=null&&b!=="0"||R)};function e(n,t){let s=new RegExp(`\\x1b\\[${t}m`,"g"),g=`\x1B[${n}m`,i=`\x1B[${t}m`;return function(l){return !L.enabled||l==null?l:g+(~(""+l).indexOf(i)?l.replace(s,i+g):l)+i}}var y=e(2,22),E=e(31,39),A=e(32,39);async function P(n){try{return await promises.readFile(n,"utf8")}catch(t){return N(`Error reading file ${n}: ${t}`),""}}async function F(n,t){try{await promises.writeFile(n,t,"utf8");}catch(s){return N(`Error writing file ${n}: ${s}`),""}}async function x(n,t,s){await F(n,t),fs.existsSync(s)&&s!==n&&await promises.unlink(s);}function T(n,t){let s=crypto.createHash("sha256").update(t).digest("hex").slice(0,8);return `${n.slice(0,-13)}.${s}.css`}var D=new Intl.DateTimeFormat("en-us",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});function d(n){let t=D.format(new Date);console.log(y(t),A("\u25B6"),n);}function N(n){let t=D.format(new Date);console.error(y(t),E("\u25A0"),n);}var v="astro-purgecss",G=n=>n.match(/[\w-/:]+(?<!:)/g)||[];function W(n={}){let t;return {name:v,hooks:{"astro:config:done":({config:s})=>{t=s;},"astro:build:done":async({dir:s,pages:g,logger:i})=>{let l=t.output;i.info(`\u{1F4E6} Running in '${l}' mode`);let o=url.fileURLToPath(s),I=l!=="static";if(!o||!t.build.format||!t.build.assets){i.warn(`${v} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`);return}let f=(await new purgecss.PurgeCSS().purge({css:[path.join(o,"/**/*.css")],defaultExtractor:G,...n,content:[path.join(o,"/**/*.html"),path.join(o,"/**/*.js"),...n.content||[]]})).filter(({file:c})=>c?.endsWith(".css"));if(f.length===0){i.info("\u2139\uFE0F No CSS files found to process");return}if(i.info(`Found ${f.length} CSS ${f.length===1?"file":"files"} to process`),I){await Promise.all(f.map(async({css:c,file:r})=>{await x(r,c,r),d(r.replace(o,""));})),i.info("\u{1F389} Purging completed successfully!");return}let m=(await Promise.all(f.map(async({css:c,file:r})=>{if(!r.includes(t.build.assets)){await x(r,c,r);let w=r.replace(o,"");return d(w),{oldFilename:w,newFilename:w}}let p=T(r,c);await x(p,c,r);let h=r.replace(o,""),C=p.replace(o,"");return d(C),{oldFilename:h,newFilename:C}}))).filter(({oldFilename:c,newFilename:r})=>c!==r);if(m.length>0){i.info(`Updating ${m.length} CSS ${m.length===1?"reference":"references"} in HTML files...`);let c=g.filter(r=>typeof r.pathname=="string").map(r=>{let a=r.pathname;if(a==="")return path.join(o,"index.html");switch(t.build.format){case"file":return path.join(o,`${a}.html`);case"directory":return path.join(o,a,"index.html");case"preserve":let p=path.join(o,`${a}.html`);return fs.existsSync(p)?p:path.join(o,a,"index.html")}});await Promise.all(c.map(async r=>{let a=await P(r);for(let{oldFilename:p,newFilename:h}of m)a.includes(p)&&(a=a.replace(new RegExp(p,"g"),h));await F(r,a),d(r.replace(o,""));}));}i.info("\u{1F389} Purging completed successfully!");}}}}var Ae=W;module.exports=Ae;//# sourceMappingURL=index.cjs.map
|
|
2
2
|
//# 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","italic","red","green","yellow","blue","readFileContent","filePath","readFile","err","error","writeFileContent","content","writeFile","replaceValueInFile","searchValue","replaceValue","cleanPath","file","path","fileURLToPath","writeCssFile","css","hash","createHash","newFile","unlink","dt","success","message","date","headline","Plugin","options","dir","pages","outDir","purged","PurgeCSS","processed","htmlPages","e","page","extname","join","oldFilename","newFilename","src_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 { blue, dim, green, red } from 'kleur/colors';\nimport { createHash } from 'node:crypto';\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 return '';\n }\n}\n\nexport function replaceValueInFile(\n filePath: string,\n content: string,\n searchValue: string,\n replaceValue: string\n): string {\n try {\n if (content.includes(searchValue)) {\n return content.replace(new RegExp(searchValue, 'g'), replaceValue);\n }\n\n return content;\n } catch (err) {\n error(`Error processing file ${filePath}: ${err}`);\n return '';\n }\n}\n\n// Clean from extra slash on windows and trailing forward slash on non-windows\nexport function cleanPath(file: URL): string {\n let path = fileURLToPath(file);\n\n // Remove trailing forward slash if present\n path = path.replace(/\\/+$/, '');\n\n if (process.platform !== 'win32') return path;\n\n // Remove leading forward slash if present\n return path.replace(/^\\/+/, '');\n}\n\nexport async function writeCssFile({\n css,\n file\n}: {\n css: string;\n file: string;\n}) {\n // Skip re-hashing a file if it's not generated by Astro ex: assets/styles/light.css\n if (!file.includes('_astro')) {\n await writeFileContent(file, css);\n return [file, file];\n }\n\n // Get content hash before writing to file\n const hash = createHash('sha256').update(css).digest('hex').substring(0, 8);\n\n // Generate new file name with hash\n // Astro orignal hash is 8 characters long\n const newFile = `${file.slice(0, -13)}.${hash}.css`;\n\n // Write purged CSS to new file\n await writeFileContent(newFile, css);\n\n // Remove old file\n await unlink(file);\n\n return [file, newFile];\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\nexport function headline(message: string) {\n const date = dt.format(new Date());\n console.log(dim(date), blue('[purgecss]'), message);\n}\n","import type { AstroIntegration } from 'astro';\nimport { extname, join } from 'node:path';\nimport { PurgeCSS, type UserDefinedOptions } from 'purgecss';\n\nimport {\n cleanPath,\n headline,\n readFileContent,\n replaceValueInFile,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\n\nexport interface PurgeCSSOptions extends Partial<UserDefinedOptions> {}\n\nfunction Plugin(options: PurgeCSSOptions = {}): AstroIntegration {\n return {\n name: 'astro-purgecss',\n hooks: {\n 'astro:build:done': async ({ dir, pages }) => {\n headline('Generating purged css files...');\n\n const outDir = cleanPath(dir);\n const purged = await new PurgeCSS().purge({\n css: [`${outDir}/**/*.css`],\n defaultExtractor: (content) => content.match(/[\\w-/:]+(?<!:)/g) || [],\n ...options,\n content: [\n `${outDir}/**/*.html`,\n `${outDir}/**/*.js`,\n ...(options.content || [])\n ]\n });\n\n const processed = await Promise.all(\n purged\n .filter(({ file }) => file?.endsWith('.css'))\n .map(async ({ css, file }) => {\n const processed = await writeCssFile({ css, file } as {\n css: string;\n file: string;\n });\n success(processed[1].replace(outDir, ''));\n\n return processed;\n })\n );\n\n headline('Generating purged html pages...');\n const htmlPages = pages\n .filter((e: any) => typeof e.pathname == 'string')\n .map((page) => {\n // see: https://docs.astro.build/en/reference/configuration-reference/#buildformat\n const isHtmlFile = extname(page.pathname).toLowerCase() === '.html';\n return isHtmlFile\n ? join(outDir, page.pathname)\n : join(outDir, page.pathname, 'index.html');\n });\n\n await Promise.all(\n htmlPages.map(async (page) => {\n let content = await readFileContent(page);\n\n for (const [oldFilename, newFilename] of processed) {\n // Replace only if name of the old file\n // is different from name of the new file (hash changes)\n if (oldFilename !== newFilename) {\n content = replaceValueInFile(\n page,\n content,\n oldFilename.replace(outDir, ''),\n newFilename.replace(outDir, '')\n );\n }\n }\n await writeFileContent(page, content);\n success(page.replace(outDir, ''));\n })\n );\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","dt","success","message","date","INTEGRATION_NAME","defaultExtractor","Plugin","options","config","cfg","dir","pages","logger","buildMode","outDir","fileURLToPath","isSSR","purgedCssFiles","PurgeCSS","join","file","changedFiles","relativePath","hashedFilename","relativeOldPath","relativeNewPath","oldFilename","newFilename","htmlFiles","page","pathname","directFile","htmlFile","src_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';\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 return '';\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 (existsSync(oldFilePath) && oldFilePath !== newFilePath) {\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 orignal hash is 8 characters long\n return `${filePath.slice(0, -13)}.${hash}.css`;\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 { fileURLToPath } from 'node:url';\nimport { PurgeCSS, type UserDefinedOptions } from 'purgecss';\n\nimport {\n generateFileHash,\n readFileContent,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\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\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\n return {\n name: INTEGRATION_NAME,\n hooks: {\n 'astro:config:done': ({ config: cfg }) => {\n config = cfg;\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 = fileURLToPath(dir);\n\n // Used to skip file rehashing for SSR/Hybrid modes\n const isSSR = buildMode !== 'static';\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: [join(outDir, '/**/*.css')],\n defaultExtractor,\n ...options,\n content: [\n join(outDir, '/**/*.html'),\n join(outDir, '/**/*.js'),\n ...(options.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 // Handle SSR/Hybrid mode\n if (isSSR) {\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 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 if (content.includes(oldFilename)) {\n content = content.replace(\n new RegExp(oldFilename, 'g'),\n newFilename\n );\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,8 +1,17 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
2
|
import { UserDefinedOptions } from 'purgecss';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Extended PurgeCSS options interface that allows partial configuration
|
|
6
|
+
* of the standard PurgeCSS options
|
|
7
|
+
*/
|
|
4
8
|
interface PurgeCSSOptions extends Partial<UserDefinedOptions> {
|
|
5
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Astro integration for PurgeCSS that removes unused CSS from the final build
|
|
12
|
+
* @param options - PurgeCSS configuration options
|
|
13
|
+
* @returns AstroIntegration - The configured Astro integration
|
|
14
|
+
*/
|
|
6
15
|
declare function Plugin(options?: PurgeCSSOptions): AstroIntegration;
|
|
7
16
|
|
|
8
17
|
export { type PurgeCSSOptions, Plugin as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import { AstroIntegration } from 'astro';
|
|
2
2
|
import { UserDefinedOptions } from 'purgecss';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Extended PurgeCSS options interface that allows partial configuration
|
|
6
|
+
* of the standard PurgeCSS options
|
|
7
|
+
*/
|
|
4
8
|
interface PurgeCSSOptions extends Partial<UserDefinedOptions> {
|
|
5
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Astro integration for PurgeCSS that removes unused CSS from the final build
|
|
12
|
+
* @param options - PurgeCSS configuration options
|
|
13
|
+
* @returns AstroIntegration - The configured Astro integration
|
|
14
|
+
*/
|
|
6
15
|
declare function Plugin(options?: PurgeCSSOptions): AstroIntegration;
|
|
7
16
|
|
|
8
17
|
export { type PurgeCSSOptions, Plugin as default };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {existsSync}from'node:fs';import {join}from'node:path';import {fileURLToPath}from'node:url';import {PurgeCSS}from'purgecss';import {createHash}from'node:crypto';import {writeFile,unlink,readFile}from'node:fs/promises';var b,S,$,O,R=!0;typeof process<"u"&&({FORCE_COLOR:b,NODE_DISABLE_COLORS:S,NO_COLOR:$,TERM:O}=process.env||{},R=process.stdout&&process.stdout.isTTY);var L={enabled:!S&&$==null&&O!=="dumb"&&(b!=null&&b!=="0"||R)};function e(n,t){let s=new RegExp(`\\x1b\\[${t}m`,"g"),g=`\x1B[${n}m`,i=`\x1B[${t}m`;return function(l){return !L.enabled||l==null?l:g+(~(""+l).indexOf(i)?l.replace(s,i+g):l)+i}}var y=e(2,22),E=e(31,39),A=e(32,39);async function P(n){try{return await readFile(n,"utf8")}catch(t){return N(`Error reading file ${n}: ${t}`),""}}async function F(n,t){try{await writeFile(n,t,"utf8");}catch(s){return N(`Error writing file ${n}: ${s}`),""}}async function x(n,t,s){await F(n,t),existsSync(s)&&s!==n&&await unlink(s);}function T(n,t){let s=createHash("sha256").update(t).digest("hex").slice(0,8);return `${n.slice(0,-13)}.${s}.css`}var D=new Intl.DateTimeFormat("en-us",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});function d(n){let t=D.format(new Date);console.log(y(t),A("\u25B6"),n);}function N(n){let t=D.format(new Date);console.error(y(t),E("\u25A0"),n);}var v="astro-purgecss",G=n=>n.match(/[\w-/:]+(?<!:)/g)||[];function W(n={}){let t;return {name:v,hooks:{"astro:config:done":({config:s})=>{t=s;},"astro:build:done":async({dir:s,pages:g,logger:i})=>{let l=t.output;i.info(`\u{1F4E6} Running in '${l}' mode`);let o=fileURLToPath(s),I=l!=="static";if(!o||!t.build.format||!t.build.assets){i.warn(`${v} requires the following astro.config options: 'outDir', 'build.format', 'build.assets'`);return}let f=(await new PurgeCSS().purge({css:[join(o,"/**/*.css")],defaultExtractor:G,...n,content:[join(o,"/**/*.html"),join(o,"/**/*.js"),...n.content||[]]})).filter(({file:c})=>c?.endsWith(".css"));if(f.length===0){i.info("\u2139\uFE0F No CSS files found to process");return}if(i.info(`Found ${f.length} CSS ${f.length===1?"file":"files"} to process`),I){await Promise.all(f.map(async({css:c,file:r})=>{await x(r,c,r),d(r.replace(o,""));})),i.info("\u{1F389} Purging completed successfully!");return}let m=(await Promise.all(f.map(async({css:c,file:r})=>{if(!r.includes(t.build.assets)){await x(r,c,r);let w=r.replace(o,"");return d(w),{oldFilename:w,newFilename:w}}let p=T(r,c);await x(p,c,r);let h=r.replace(o,""),C=p.replace(o,"");return d(C),{oldFilename:h,newFilename:C}}))).filter(({oldFilename:c,newFilename:r})=>c!==r);if(m.length>0){i.info(`Updating ${m.length} CSS ${m.length===1?"reference":"references"} in HTML files...`);let c=g.filter(r=>typeof r.pathname=="string").map(r=>{let a=r.pathname;if(a==="")return join(o,"index.html");switch(t.build.format){case"file":return join(o,`${a}.html`);case"directory":return join(o,a,"index.html");case"preserve":let p=join(o,`${a}.html`);return existsSync(p)?p:join(o,a,"index.html")}});await Promise.all(c.map(async r=>{let a=await P(r);for(let{oldFilename:p,newFilename:h}of m)a.includes(p)&&(a=a.replace(new RegExp(p,"g"),h));await F(r,a),d(r.replace(o,""));}));}i.info("\u{1F389} Purging completed successfully!");}}}}var Ae=W;export{Ae as default};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# 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","italic","red","green","yellow","blue","readFileContent","filePath","readFile","err","error","writeFileContent","content","writeFile","replaceValueInFile","searchValue","replaceValue","cleanPath","file","path","fileURLToPath","writeCssFile","css","hash","createHash","newFile","unlink","dt","success","message","date","headline","Plugin","options","dir","pages","outDir","purged","PurgeCSS","processed","htmlPages","e","page","extname","join","oldFilename","newFilename","src_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 { blue, dim, green, red } from 'kleur/colors';\nimport { createHash } from 'node:crypto';\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 return '';\n }\n}\n\nexport function replaceValueInFile(\n filePath: string,\n content: string,\n searchValue: string,\n replaceValue: string\n): string {\n try {\n if (content.includes(searchValue)) {\n return content.replace(new RegExp(searchValue, 'g'), replaceValue);\n }\n\n return content;\n } catch (err) {\n error(`Error processing file ${filePath}: ${err}`);\n return '';\n }\n}\n\n// Clean from extra slash on windows and trailing forward slash on non-windows\nexport function cleanPath(file: URL): string {\n let path = fileURLToPath(file);\n\n // Remove trailing forward slash if present\n path = path.replace(/\\/+$/, '');\n\n if (process.platform !== 'win32') return path;\n\n // Remove leading forward slash if present\n return path.replace(/^\\/+/, '');\n}\n\nexport async function writeCssFile({\n css,\n file\n}: {\n css: string;\n file: string;\n}) {\n // Skip re-hashing a file if it's not generated by Astro ex: assets/styles/light.css\n if (!file.includes('_astro')) {\n await writeFileContent(file, css);\n return [file, file];\n }\n\n // Get content hash before writing to file\n const hash = createHash('sha256').update(css).digest('hex').substring(0, 8);\n\n // Generate new file name with hash\n // Astro orignal hash is 8 characters long\n const newFile = `${file.slice(0, -13)}.${hash}.css`;\n\n // Write purged CSS to new file\n await writeFileContent(newFile, css);\n\n // Remove old file\n await unlink(file);\n\n return [file, newFile];\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\nexport function headline(message: string) {\n const date = dt.format(new Date());\n console.log(dim(date), blue('[purgecss]'), message);\n}\n","import type { AstroIntegration } from 'astro';\nimport { extname, join } from 'node:path';\nimport { PurgeCSS, type UserDefinedOptions } from 'purgecss';\n\nimport {\n cleanPath,\n headline,\n readFileContent,\n replaceValueInFile,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\n\nexport interface PurgeCSSOptions extends Partial<UserDefinedOptions> {}\n\nfunction Plugin(options: PurgeCSSOptions = {}): AstroIntegration {\n return {\n name: 'astro-purgecss',\n hooks: {\n 'astro:build:done': async ({ dir, pages }) => {\n headline('Generating purged css files...');\n\n const outDir = cleanPath(dir);\n const purged = await new PurgeCSS().purge({\n css: [`${outDir}/**/*.css`],\n defaultExtractor: (content) => content.match(/[\\w-/:]+(?<!:)/g) || [],\n ...options,\n content: [\n `${outDir}/**/*.html`,\n `${outDir}/**/*.js`,\n ...(options.content || [])\n ]\n });\n\n const processed = await Promise.all(\n purged\n .filter(({ file }) => file?.endsWith('.css'))\n .map(async ({ css, file }) => {\n const processed = await writeCssFile({ css, file } as {\n css: string;\n file: string;\n });\n success(processed[1].replace(outDir, ''));\n\n return processed;\n })\n );\n\n headline('Generating purged html pages...');\n const htmlPages = pages\n .filter((e: any) => typeof e.pathname == 'string')\n .map((page) => {\n // see: https://docs.astro.build/en/reference/configuration-reference/#buildformat\n const isHtmlFile = extname(page.pathname).toLowerCase() === '.html';\n return isHtmlFile\n ? join(outDir, page.pathname)\n : join(outDir, page.pathname, 'index.html');\n });\n\n await Promise.all(\n htmlPages.map(async (page) => {\n let content = await readFileContent(page);\n\n for (const [oldFilename, newFilename] of processed) {\n // Replace only if name of the old file\n // is different from name of the new file (hash changes)\n if (oldFilename !== newFilename) {\n content = replaceValueInFile(\n page,\n content,\n oldFilename.replace(outDir, ''),\n newFilename.replace(outDir, '')\n );\n }\n }\n await writeFileContent(page, content);\n success(page.replace(outDir, ''));\n })\n );\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","dt","success","message","date","INTEGRATION_NAME","defaultExtractor","Plugin","options","config","cfg","dir","pages","logger","buildMode","outDir","fileURLToPath","isSSR","purgedCssFiles","PurgeCSS","join","file","changedFiles","relativePath","hashedFilename","relativeOldPath","relativeNewPath","oldFilename","newFilename","htmlFiles","page","pathname","directFile","htmlFile","src_default"],"mappings":"iOAAA,IAAIA,CAAaC,CAAAA,CAAAA,CAAqBC,EAAUC,CAAMC,CAAAA,CAAAA,CAAM,CACxD,CAAA,CAAA,OAAO,OAAY,CAAA,GAAA,GACrB,CAAE,WAAAJ,CAAAA,CAAAA,CAAa,oBAAAC,CAAqB,CAAA,QAAA,CAAAC,EAAU,IAAAC,CAAAA,CAAK,CAAI,CAAA,OAAA,CAAQ,GAAO,EAAA,GACvEC,CAAQ,CAAA,OAAA,CAAQ,MAAU,EAAA,OAAA,CAAQ,MAAO,CAAA,KAAA,CAAA,CAGnC,IAAMC,CAAI,CAAA,CAChB,OAAS,CAAA,CAACJ,CAAuBC,EAAAA,CAAAA,EAAY,MAAQC,CAAS,GAAA,MAAA,GAC7DH,GAAe,IAAQA,EAAAA,CAAAA,GAAgB,KAAOI,CAEhD,CAAA,CAAA,CAEA,SAASE,CAAAA,CAAKC,CAAGC,CAAAA,CAAAA,CAAG,CACnB,IAAIC,CAAAA,CAAM,IAAI,MAAA,CAAO,CAAWD,QAAAA,EAAAA,CAAC,IAAK,GAAG,CAAA,CACrCE,CAAO,CAAA,CAAA,KAAA,EAAQH,CAAC,CAAA,CAAA,CAAA,CAAKI,EAAQ,CAAQH,KAAAA,EAAAA,CAAC,IAE1C,OAAO,SAAUI,EAAK,CACrB,OAAI,CAACP,CAAAA,CAAE,OAAWO,EAAAA,CAAAA,EAAO,KAAaA,CAC/BF,CAAAA,CAAAA,EAAU,CAAE,CAAA,EAAA,CAAGE,CAAK,EAAA,OAAA,CAAQD,CAAK,CAAIC,CAAAA,CAAAA,CAAI,OAAQH,CAAAA,CAAAA,CAAKE,CAAQD,CAAAA,CAAI,EAAIE,CAAOD,CAAAA,CAAAA,CACrF,CACD,CAGO,IAEME,CAAMP,CAAAA,CAAAA,CAAK,CAAG,CAAA,EAAE,EAShBQ,CAAAA,CAAMR,CAAK,CAAA,EAAA,CAAI,EAAE,CACjBS,CAAAA,CAAAA,CAAQT,EAAK,EAAI,CAAA,EAAE,EC9BhC,eAAsBU,CAAAA,CAAgBC,CAAmC,CAAA,CACvE,GAAI,CAEF,OADgB,MAAMC,QAAAA,CAASD,CAAU,CAAA,MAAM,CAEjD,CAASE,MAAAA,CAAAA,CAAK,CACZ,OAAAC,CAAAA,CAAM,sBAAsBH,CAAQ,CAAA,EAAA,EAAKE,CAAG,CAAA,CAAE,CACvC,CAAA,EACT,CACF,CAEA,eAAsBE,CAAiBJ,CAAAA,CAAAA,CAAkBK,CAAiB,CAAA,CACxE,GAAI,CACF,MAAMC,SAAUN,CAAAA,CAAAA,CAAUK,CAAS,CAAA,MAAM,EAC3C,CAASH,MAAAA,CAAAA,CAAK,CACZ,OAAAC,CAAAA,CAAM,sBAAsBH,CAAQ,CAAA,EAAA,EAAKE,CAAG,CAAA,CAAE,CACvC,CAAA,EACT,CACF,CAEA,eAAsBK,CACpBC,CAAAA,CAAAA,CACAC,CACAC,CAAAA,CAAAA,CACA,CACA,MAAMN,CAAAA,CAAiBI,CAAaC,CAAAA,CAAG,CAGnCE,CAAAA,UAAAA,CAAWD,CAAW,CAAKA,EAAAA,CAAAA,GAAgBF,GAC7C,MAAMI,MAAAA,CAAOF,CAAW,EAE5B,CAEO,SAASG,CAAAA,CAAiBb,CAAkBK,CAAAA,CAAAA,CAAiB,CAElE,IAAMS,CAAAA,CAAOC,UAAW,CAAA,QAAQ,CAAE,CAAA,MAAA,CAAOV,CAAO,CAAE,CAAA,MAAA,CAAO,KAAK,CAAA,CAAE,KAAM,CAAA,CAAA,CAAG,CAAC,CAI1E,CAAA,OAAO,GAAGL,CAAS,CAAA,KAAA,CAAM,EAAG,CAAG,EAAA,CAAC,CAAIc,CAAAA,EAAAA,CAAI,CAC1C,IAAA,CAAA,CAEO,IAAME,CAAK,CAAA,IAAI,IAAK,CAAA,cAAA,CAAe,OAAS,CAAA,CACjD,KAAM,SACN,CAAA,MAAA,CAAQ,SACR,CAAA,MAAA,CAAQ,SACR,CAAA,MAAA,CAAQ,EACV,CAAC,CAAA,CAEM,SAASC,CAAQC,CAAAA,CAAAA,CAAiB,CACvC,IAAMC,CAAAA,CAAOH,CAAG,CAAA,MAAA,CAAO,IAAI,IAAM,EACjC,OAAQ,CAAA,GAAA,CAAIpB,CAAIuB,CAAAA,CAAI,CAAGrB,CAAAA,CAAAA,CAAM,QAAG,CAAGoB,CAAAA,CAAO,EAC5C,CAEO,SAASf,CAAAA,CAAMe,EAAiB,CACrC,IAAMC,CAAOH,CAAAA,CAAAA,CAAG,MAAO,CAAA,IAAI,IAAM,CACjC,CAAA,OAAA,CAAQ,KAAMpB,CAAAA,CAAAA,CAAIuB,CAAI,CAAA,CAAGtB,EAAI,QAAG,CAAA,CAAGqB,CAAO,EAC5C,CCzCA,IAAME,EAAmB,gBAMnBC,CAAAA,CAAAA,CAAoBhB,CACxBA,EAAAA,CAAAA,CAAQ,KAAM,CAAA,iBAAiB,GAAK,EAAC,CAOvC,SAASiB,CAAOC,CAAAA,CAAAA,CAA2B,EAAsB,CAAA,CAC/D,IAAIC,CAAAA,CAEJ,OAAO,CACL,KAAMJ,CACN,CAAA,KAAA,CAAO,CACL,mBAAA,CAAqB,CAAC,CAAE,OAAQK,CAAI,CAAA,GAAM,CACxCD,CAAAA,CAASC,EACX,CAAA,CACA,mBAAoB,MAAO,CAAE,IAAAC,CAAK,CAAA,KAAA,CAAAC,EAAO,MAAAC,CAAAA,CAAO,CAAM,GAAA,CACpD,IAAMC,CAAAA,CAAYL,EAAO,MACzBI,CAAAA,CAAAA,CAAO,IAAK,CAAA,CAAA,sBAAA,EAAkBC,CAAS,CAAA,MAAA,CAAQ,EAG/C,IAAMC,CAAAA,CAASC,aAAcL,CAAAA,CAAG,CAG1BM,CAAAA,CAAAA,CAAQH,IAAc,QAG5B,CAAA,GAAI,CAACC,CAAU,EAAA,CAACN,EAAO,KAAM,CAAA,MAAA,EAAU,CAACA,CAAAA,CAAO,KAAM,CAAA,MAAA,CAAQ,CAC3DI,CAAO,CAAA,IAAA,CACL,CAAGR,EAAAA,CAAgB,CACrB,sFAAA,CAAA,CAAA,CACA,MACF,CAeA,IAAMa,CAZe,CAAA,CAAA,MAAM,IAAIC,QAAAA,GAAW,KAAM,CAAA,CAC9C,IAAK,CAACC,IAAAA,CAAKL,EAAQ,WAAW,CAAC,CAC/B,CAAA,gBAAA,CAAAT,CACA,CAAA,GAAGE,EACH,OAAS,CAAA,CACPY,IAAKL,CAAAA,CAAAA,CAAQ,YAAY,CAAA,CACzBK,KAAKL,CAAQ,CAAA,UAAU,CACvB,CAAA,GAAIP,CAAQ,CAAA,OAAA,EAAW,EACzB,CACF,CAAC,CAGmC,EAAA,MAAA,CAAO,CAAC,CAAE,IAAA,CAAAa,CAAK,CAAA,GACjDA,CAAM,EAAA,QAAA,CAAS,MAAM,CACvB,CAAA,CAKA,GAAIH,CAAAA,CAAe,MAAW,GAAA,CAAA,CAAG,CAC/BL,CAAO,CAAA,IAAA,CAAK,6CAAmC,CAAA,CAC/C,MACF,CAOA,GALAA,CAAO,CAAA,IAAA,CACL,SAASK,CAAe,CAAA,MAAM,QAAQA,CAAe,CAAA,MAAA,GAAW,CAAI,CAAA,MAAA,CAAS,OAAO,CAAA,WAAA,CACtF,EAGID,CAAO,CAAA,CACT,MAAM,OAAA,CAAQ,GACZC,CAAAA,CAAAA,CAAe,IAAI,MAAO,CAAE,GAAAxB,CAAAA,CAAAA,CAAK,IAAA2B,CAAAA,CAAK,IAAM,CAC1C,MAAM7B,EAAa6B,CAAM3B,CAAAA,CAAAA,CAAK2B,CAAI,CAClCnB,CAAAA,CAAAA,CAAQmB,CAAK,CAAA,OAAA,CAAQN,CAAQ,CAAA,EAAE,CAAC,EAClC,CAAC,CACH,CAAA,CACAF,CAAO,CAAA,IAAA,CAAK,2CAAoC,CAChD,CAAA,MACF,CAmCA,IAAMS,CAhCe,CAAA,CAAA,MAAM,QAAQ,GACjCJ,CAAAA,CAAAA,CAAe,GAAI,CAAA,MAAO,CAAE,GAAA,CAAAxB,EAAK,IAAA2B,CAAAA,CAAK,CAAM,GAAA,CAK1C,GAAI,CAJgBA,EAAK,QAASZ,CAAAA,CAAAA,CAAO,KAAM,CAAA,MAAM,CAInC,CAAA,CAChB,MAAMjB,CAAa6B,CAAAA,CAAAA,CAAM3B,CAAK2B,CAAAA,CAAI,CAClC,CAAA,IAAME,EAAeF,CAAK,CAAA,OAAA,CAAQN,EAAQ,EAAE,CAAA,CAC5C,OAAAb,CAAQqB,CAAAA,CAAY,CACb,CAAA,CACL,WAAaA,CAAAA,CAAAA,CACb,YAAaA,CACf,CACF,CAGA,IAAMC,CAAiB1B,CAAAA,CAAAA,CAAiBuB,EAAM3B,CAAG,CAAA,CACjD,MAAMF,CAAAA,CAAagC,CAAgB9B,CAAAA,CAAAA,CAAK2B,CAAI,CAE5C,CAAA,IAAMI,EAAkBJ,CAAK,CAAA,OAAA,CAAQN,EAAQ,EAAE,CAAA,CACzCW,CAAkBF,CAAAA,CAAAA,CAAe,OAAQT,CAAAA,CAAAA,CAAQ,EAAE,CACzD,CAAA,OAAAb,CAAQwB,CAAAA,CAAe,CAEhB,CAAA,CACL,YAAaD,CACb,CAAA,WAAA,CAAaC,CACf,CACF,CAAC,CACH,GAGoC,MAClC,CAAA,CAAC,CAAE,WAAAC,CAAAA,CAAAA,CAAa,YAAAC,CAAY,CAAA,GAAMD,CAAgBC,GAAAA,CACpD,CAEA,CAAA,GAAIN,EAAa,MAAS,CAAA,CAAA,CAAG,CAC3BT,CAAAA,CAAO,IACL,CAAA,CAAA,SAAA,EAAYS,EAAa,MAAM,CAAA,KAAA,EAAQA,CAAa,CAAA,MAAA,GAAW,CAAI,CAAA,WAAA,CAAc,YAAY,CAC/F,iBAAA,CAAA,CAAA,CAEA,IAAMO,CAAYjB,CAAAA,CAAAA,CACf,OAAQkB,CAAS,EAAA,OAAOA,CAAK,CAAA,QAAA,EAAa,QAAQ,CAAA,CAClD,IAAKA,CAAS,EAAA,CACb,IAAMC,CAAAA,CAAWD,CAAK,CAAA,QAAA,CAGtB,GAAIC,CAAa,GAAA,EAAA,CACf,OAAOX,IAAAA,CAAKL,CAAQ,CAAA,YAAY,EAGlC,OAAQN,CAAAA,CAAO,MAAM,MAAQ,EAC3B,IAAK,MAEH,CAAA,OAAOW,IAAKL,CAAAA,CAAAA,CAAQ,CAAGgB,EAAAA,CAAQ,OAAO,CAExC,CAAA,IAAK,WAEH,CAAA,OAAOX,IAAKL,CAAAA,CAAAA,CAAQgB,EAAU,YAAY,CAAA,CAE5C,IAAK,UAAA,CAEH,IAAMC,CAAAA,CAAaZ,KAAKL,CAAQ,CAAA,CAAA,EAAGgB,CAAQ,CAAO,KAAA,CAAA,CAAA,CAClD,OAAOnC,UAAWoC,CAAAA,CAAU,CACxBA,CAAAA,CAAAA,CACAZ,IAAKL,CAAAA,CAAAA,CAAQgB,EAAU,YAAY,CAC3C,CACF,CAAC,CAGH,CAAA,MAAM,QAAQ,GACZF,CAAAA,CAAAA,CAAU,GAAI,CAAA,MAAOI,CAAa,EAAA,CAChC,IAAI3C,CAAU,CAAA,MAAMN,EAAgBiD,CAAQ,CAAA,CAE5C,OAAW,CAAE,WAAA,CAAAN,CAAa,CAAA,WAAA,CAAAC,CAAY,CAAA,GAAKN,EACrChC,CAAQ,CAAA,QAAA,CAASqC,CAAW,CAAA,GAC9BrC,CAAUA,CAAAA,CAAAA,CAAQ,QAChB,IAAI,MAAA,CAAOqC,CAAa,CAAA,GAAG,CAC3BC,CAAAA,CACF,GAIJ,MAAMvC,CAAAA,CAAiB4C,CAAU3C,CAAAA,CAAO,CACxCY,CAAAA,CAAAA,CAAQ+B,EAAS,OAAQlB,CAAAA,CAAAA,CAAQ,EAAE,CAAC,EACtC,CAAC,CACH,EACF,CAEAF,CAAO,CAAA,IAAA,CAAK,2CAAoC,EAClD,CACF,CACF,CACF,CAEA,IAAOqB,EAAQ3B,CAAAA","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';\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 return '';\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 (existsSync(oldFilePath) && oldFilePath !== newFilePath) {\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 orignal hash is 8 characters long\n return `${filePath.slice(0, -13)}.${hash}.css`;\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 { fileURLToPath } from 'node:url';\nimport { PurgeCSS, type UserDefinedOptions } from 'purgecss';\n\nimport {\n generateFileHash,\n readFileContent,\n success,\n writeCssFile,\n writeFileContent\n} from './utils';\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\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\n return {\n name: INTEGRATION_NAME,\n hooks: {\n 'astro:config:done': ({ config: cfg }) => {\n config = cfg;\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 = fileURLToPath(dir);\n\n // Used to skip file rehashing for SSR/Hybrid modes\n const isSSR = buildMode !== 'static';\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: [join(outDir, '/**/*.css')],\n defaultExtractor,\n ...options,\n content: [\n join(outDir, '/**/*.html'),\n join(outDir, '/**/*.js'),\n ...(options.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 // Handle SSR/Hybrid mode\n if (isSSR) {\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 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 if (content.includes(oldFilename)) {\n content = content.replace(\n new RegExp(oldFilename, 'g'),\n newFilename\n );\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.
|
|
4
|
+
"version": "4.8.0",
|
|
5
5
|
"homepage": "https://github.com/codiume/orbit",
|
|
6
6
|
"bugs": "https://github.com/codiume/orbit/issues",
|
|
7
7
|
"author": "codiume",
|