Skip to content

Commit

Permalink
fix: astro-purgecss is modifying files keeping old hash (#564)
Browse files Browse the repository at this point in the history
* fix: astro-purgecss is modifying files keeping the hash fix #450

* x

* x

* Address the-dijkstra comments

* missing utils on build command
  • Loading branch information
Diviei authored Aug 3, 2024
1 parent 8f5ed26 commit 26df36e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 16 deletions.
2 changes: 1 addition & 1 deletion packages/astro-purgecss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Remove unused CSS rules from your final Astro bundle",
"version": "4.1.1",
"scripts": {
"build": "astro-build --src src/index.ts",
"build": "astro-build --src src/index.ts src/utils.ts",
"typecheck": "tsc --declaration --emitDeclarationOnly"
},
"type": "module",
Expand Down
43 changes: 28 additions & 15 deletions packages/astro-purgecss/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import type { AstroIntegration } from 'astro';
import { PurgeCSS, type UserDefinedOptions } from 'purgecss';
import { writeFile } from 'node:fs/promises';
import { createHash } from 'crypto';
import { rename, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { PurgeCSS, type UserDefinedOptions } from 'purgecss';
import { handleWindowsPath, replaceStringInDirectory } from './utils';

export interface PurgeCSSOptions extends Partial<UserDefinedOptions> {}

function handleWindowsPath(outputPath: string): string {
if (process.platform !== 'win32') return outputPath;

if (outputPath.endsWith('\\')) {
outputPath = outputPath.substring(0, outputPath.length - 1);
}
outputPath = outputPath.replaceAll('\\', '/');

return outputPath;
}

export default function (options: PurgeCSSOptions = {}): AstroIntegration {
return {
name: 'astro-purgecss',
Expand All @@ -30,12 +22,33 @@ export default function (options: PurgeCSSOptions = {}): AstroIntegration {
`${outDir}/**/*.html`,
`${outDir}/**/*.js`,
...(options.content || [])
],
]
});
await Promise.all(
purged
.filter(({ file }) => file?.endsWith('.css'))
.map(async ({ css, file }) => await writeFile(file!, css))
.map(async ({ css, file }) => {
if (!file) return;

await writeFile(file, css);

// Get content hash
const hash = await createHash('sha256')
.update(css)
.digest('hex')
.substring(0, 7);

// Rename file
const newPath = file.slice(0, -12) + hash + '.css';
await rename(file, newPath);

// Replace old name references by newPath
await replaceStringInDirectory(
outDir + '../',
path.basename(file),
path.basename(newPath)
);
})
);
}
}
Expand Down
50 changes: 50 additions & 0 deletions packages/astro-purgecss/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { readdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';

export function handleWindowsPath(outputPath: string): string {
if (process.platform !== 'win32') return outputPath;

if (outputPath.endsWith('\\')) {
outputPath = outputPath.substring(0, outputPath.length - 1);
}
outputPath = outputPath.replaceAll('\\', '/');

return outputPath;
}

export async function replaceStringInFile(
filePath: string,
searchValue: string,
replaceValue: string
) {
try {
const fileContent = await readFile(filePath, 'utf8');
if (fileContent.includes(searchValue)) {
const re = new RegExp(searchValue, 'g');
const newContent = fileContent.replace(re, replaceValue);
await writeFile(filePath, newContent, 'utf8');
}
} catch (err) {
console.error(`Error processing file ${filePath}: ${err}`);
}
}

export async function replaceStringInDirectory(
directory: string,
searchValue: string,
replaceValue: string
) {
try {
const files = await readdir(directory, { withFileTypes: true });
for (const file of files) {
const fullPath = path.join(directory, file.name);
if (file.isDirectory()) {
await replaceStringInDirectory(fullPath, searchValue, replaceValue);
} else if (file.isFile()) {
await replaceStringInFile(fullPath, searchValue, replaceValue);
}
}
} catch (err) {
console.error(`Error processing directory ${directory}: ${err}`);
}
}

0 comments on commit 26df36e

Please sign in to comment.